Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android: How to force Explore-By-Touch/Talkback to repeat the ContentDescription of the current View in AccessibilityFocus?

In my Android app, I have a View which displays an image and has an associated ContentDescription.

I can enable Settings->Accessibility->Talkback, with Explore By Touch from the Talkback settings, and then single tap on the View to read the ContentDescription aloud.

This is all as expected so far.

However, I would like Explore By Touch to repeat the ContentDescription if I single tap the same View again. For example, my image and description may be updated while it has the AccessibilityFocus, so saying the new phrase would be helpful to the user. How can I achieve this?

I've tried experimenting with View.clearFocus() and View.invalidate(), but with no success.

Any constructive ideas would be welcome.

Update

I should have also mentioned that I want to add support from API 8 onwards. Hence, I'm trying to do the best I can with the Accessibility interface from API 4.

I'm currently working on a solution that uses View.clearFocus() followed by View.requestFocus() to work around the updated-view issue. This appears to work so far on my test kit with APIs 8 and 16.

I'll update again with the final result, but welcome further suggestions in the interim.

like image 598
AwayTeam Avatar asked Jul 17 '14 17:07

AwayTeam


People also ask

How do I change the Accessibility focus on Android?

In Android Studio, using Java, to set the accessibility focus on a certain myview you have to do myview. sendAccessibilityEvent(AccessibilityEvent. WINDOWS_CHANGE_ACCESSIBILITY_FOCUSED) and it works fine.

What is TalkBack shortcut?

Option 1: With the volume key shortcut On the side of your device, find both volume keys. Press and hold both volume keys for 3 seconds. To confirm that you want to turn TalkBack on or off, press both volume keys for 3 seconds again.

How do I navigate Android with TalkBack?

To open the TalkBack menu, swipe down then right, or swipe up then right. Or on devices with multi-finger gestures*, you can also do a three-finger tap. Reading controls: allow adjustment of reading settings, such as being able to swipe to read by headings or by lines, and to change the speech rate.


1 Answers

As promised in my question, here are the results of my investigation and a working solution.

Firstly, many thanks to alanv for his help and support, and for answering the question for later APIs (14 and upwards). Although he didn't find the solution for older APIs, he did provide critical information which helped me find an answer.

At the time of writing, it is not possible to construct a successfully-spoken AccessibilityEvent, due to a known bug in TalkBack - see Send accessibility event not linked to view for further details. If the event source is null, the event is ignored by TalkBack (v3.5.0_r105) and as AccessibilityEvent.setSource(View) first appeared in API 14, it is not possible to set the source prior to that - see Google Eyes-Free issue #379

However, it is possible to make Android generate such events by using View.requestFocus() as I previously hinted.

  1. Make your View focusable in its XML layout using:

    android:focusable="true"
    android:focusableInTouchMode="true"

  2. Set the spoken text using View.setContentDescription(text) in Activity.onCreate or with android:contentDescription="text" in the XML layout if it is static, or dynamically in code if necessary.

  3. When the spoken text is required, move the focus to the correct view using View.requestFocus() to trigger an AccessibilityEvent.

  4. To ensure that a phrase is repeated (my original question), call View.clearFocus() before requesting focus in the previous step.

I have a tested implementation of this approach working on API 8, and it also works on API 16. It should work all the way back to API 4, when the Accessibility API was first introduced.

This solution may not be required for developers who only support more recent Android APIs (14 and later), but I believe there are few other options currently for those supporting Accessibility in earlier APIs. Good luck.

Update

Unfortunately, alanv's answer seems to have disappeared - possibly deleted - taking with it all the associated detail and discussion in the comments. I have attempted to recapture the main points below.

  1. For Android API 14 and later, it is possible to create focused events as follows:

    if (mAccessibilityService.isEnabled()) { AccessibilityEvent event = AccessibilityEvent.obtain( AccessibilityEvent.TYPE_VIEW_FOCUSED); event.setSource(myView); // API 14 & later event.setClassName(myView.getClass().getName()); event.setPackageName(myView.getContext().getPackageName()); event.setEnabled(true); event.setContentDescription(text); myView.sendAccessibilityEventUnchecked(event); }

  2. For Android API 16 and later, View.announceForAccessibility(text) can be used.

like image 103
AwayTeam Avatar answered Sep 21 '22 01:09

AwayTeam