Background: What is the problem
My app has this acronym for a word let us assume it is
ABC
When I use Google's voice service it reads out the letters which is great
However when I use Samsung Voice (S Voice), it reads it out as 1 word which is not great!
So why not just set content descriptions?
ABC appears in many places, it is not viable to setup alternative content descriptions. Also it could break the content description for other voice over services that read it out correctly like Google's one
My Plan
So I had an issue a while back and I found this great method
for classes that extend ViewGroup
which was onRequestSendAccessibilityEvent
.
To sum up, this method allows you to catch a AccessibilityEvent
to modify it in some way before it is processed. Among other things you can grab the content description to be read out and modify it.
My idea is to obtain what the current TTS or TalkBack service engine is being used and use regex to edit a content description for the letters ABC and make it A B C if it Samsung Voice (S Voice). Hopefully!
My question
Anyone know a listener or callback to get the AccessibilityEvent
to be processed in a global or generic case?
onRequestSendAccessibilityEvent
is only for ViewGroup
. I could not find an alternative for Activity
.
Anyone know how to catch all incoming AccessibilityEvent
or maybe an alternative solution to my problem
Thanks for reading!
TalkBack is the Google screen reader included on Android devices. TalkBack gives you eyes-free control of your device. The setup of your device depends on the device manufacturer, Android version, and TalkBack version. These help pages apply to most devices, but you might experience some differences.
More details: if you are strictly interested in whether TalkBack is enabled, use am. isTouchExplorationEnabled() . (If Select to Speak is enabled and TalkBack disabled, am. isEnabled() will still return true.)
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.
No accessibility events/delegates do not apply to Activities, and they don't need to. Every Activity
should have a root/content view that is an instance of ViewGroup
. This has worked well for me to filter all accessibility events within an activity:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
View contentView = findViewById(android.R.id.content);
contentView.setAccessibilityDelegate(new View.AccessibilityDelegate(){
@Override
public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child, AccessibilityEvent event) {
Log.wtf("Event: " + event.toString());
return super.onRequestSendAccessibilityEvent(host, child, event);
}
});
}
I would also point out, that TalkBack supports the ability to navigate by character, and that such a solution may be solving a problem that TalkBack users do not see as a problem. In fact in some circumstances this could be viewed as worse. Any time you're changing the content an individual with a disability sees in compared to the actual content you have to do so VERY carefully. Even though the announcement is cleaner:
"ABC" != "A B C"
For example in a different case, one might view this behavior as a "feature" like:
"NASA"
A naive implementation of this might be to just "toLowerCase" all of your content descriptions or add a space betwenn all capital letters. Clearly each of these solutions creates a different type of problem.
My point is, TalkBack gives users the ability to navigate by character if content on the screen is confusing them. AT users on various platforms will become accustomed to the "quarks" of their platform. By using one of the above solutions you have forced on them a different quark. Sometimes, the most accessible solution is to just let "ABC" == "ABC"
, and allow AT users to sort things out for themselves.
If you're not going to go to the trouble to fix all of your strings in the "ideal" way specifically, it is most certainly better to just leave things alone. Though, the best case scenario is to properly consider both of these problems and which solution best applies given the scenario.
Some examples of times when I prefer overriding with a content description, that could potentially be caught with regular expressions or string matching. A good implementation of this would be spotting these specific scenarios and fixing them via a REGEX -> String dictionary with "replace" to the text or content description property, and set it as the new content description.
"OFF" -> "off" //This one is super dumb on Google's part. "OFF" shows up on every switch in the OS!
"ON" -> "on" //See above comment.
"NASA" -> "nasa"
etc.
Note that in my dictionary, I'm always going towards the word and not towards the individual character announcement :). The reason for this is, I am not changing the nature of the string. Or rather, in every insance the following is true:
oldString.equalsIgnoreCase(newString);
Now add string localization into the equation and well... this is a very complicated problem indeed. Maybe just leaving things alone is the best option.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With