Search code examples
androidandroid-webviewaccessibilitytext-to-speechtalkback

Using a webview and TTS regardless of TalkBack


I'm developing an Android webapp (an app built with Android Studio mainly based on a single webview which loads remote content) that is meant to be used by visually impaired people.

Standard accessibility features, such as those provided by Android itself and Talkback, are completely useless for my use case, because this app is meant to be used in a completely non standard way, by using the headset button as the only input, and spoken text as the output.

The webapp is NOT meant to be used by people who are not visually impaired alike. We already have a completely different version of the webapp for that. However, I do want the spoken texts to be displayed on screen, mainly for testing/debugging purposes.

So, I don't need nor want to take advantage of Google Talkback, and my webapp, built from scratch using native TTS called from JavaScript (and TTS events, such as ending of utterances, triggering JavaScript code), already works fine when TalkBack is disabled.

However, my app is going to be used mostly on phones whose users DO have accessibility and TalkBack enabled (or perhaps other accessibility extensions - hopefully not, given the nearly nonexistent standardization of the framework for accessibility features). So I need to prevent it from interfering with my own calls to the TTS engine.

Which is complicated as hell. Also, I need it to be compatible with Android 2.x through 4.x.

On older Android versions, the problem is relatively small, as TalkBack doesn't inject scripts into the webview, and the webview is almost opaque, its contents being "invisible" to Talkback.

On newer versions, it's a nightmare. Android doesn't provide a way to simply disable accessibility features from the app, which is ridiculous. The AccessibilityManager.interrupt() method doesn't seem to do the trick, and it's practically undocumented, so I can hardly figure out in which ways I could try to use it.

There doesn't seem to be any documentation about how the injected scripts work and how I could try to interact with them.

And to screw things further, I'm reading that since 4.4.something, the scripts formerly injected by TalkBack are now replaced by something else, integrated into the very web engine, or something like that. So maybe even any hack I can figure out for TalkBack injected scripts may not work with the most recent versions.

Is there some workaround/hack to completely disable TalkBack from my app, for my app, when my app is running? Is there a way to prevent the injection of javascript code from TalkBack (when the script injection is enabled systemwise)? (obviously without disabling javascript altogether in my webview, since I do use my own javascript) Is there at least some documentation of those scripts available? Or their code? So that I could at least try to "fool" them? Is there a way I can make some parts of the webview's content "invisible" to TalkBack?

Or any other suggestion in order to be able to have my app do its own call to TTS while avoiding Talkback to interfere with them, and render text on screen while preventing TalkBack from interacting with it?


Solution

  • I've been working with TalkBack and Android for about a month now and find the same frustrations you have - little to no documentation other than reading thousands of lines of source code. In 4.4 the WebView component changed to use the Chromium engine, which is from what I can tell the reason the scripts injected aren't exactly the same. Both still seem to be using ChromeVox. There are no public APIs for disabling TalkBack, it can be done with reflection if you're included to deal with the headaches that come with that. You're best bet is to disable ChromeVox (it's injected into your WebView automatically on 4.4+ and on lower 4.x assuming the web accessibility setting is enabled) from the JS side.

    I can only test on 4.4 now, but this does the trick for me:

    cvox.ChromeVox.host.activateOrDeactivateChromeVox(false);
    

    https://code.google.com/p/google-axs-chrome/source/browse/trunk/chromevox/chromevox/injected/init_document.js?r=193