In my Android app, I have a View
which displays an image and has an associated ContentDescription
.
I can enable Settings->Accessibility
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.
Make your View focusable in its XML layout using:
android:focusable="true"
android:focusableInTouchMode="true"
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.
When the spoken text is required, move the focus to the correct view using View.requestFocus()
to trigger an AccessibilityEvent
.
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.
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);
}
For Android API 16 and later, View.announceForAccessibility(text)
can be used.