How to know if Android TalkBack is active?

I'm developing an application that uses TalkBack to guide people through it. However, in those situations I want to have some subtile differences in the layout of the application so navigation is easier and also have extra voice outputs (with TextToSpeech) to help guide the user.

My problem is that I only want those changes and extra outputs if the user has TalkBack active.

Is there any way to know if it is? I didn't find anything specific to access TalkBack settings directly, but I was hoping there was some form of accessing general phone settings that could let me know what I need.

Regards and thanks in advance.


The recommended way of doing this is to query the AccessibilityManager for the enabled state of accessibility services.

AccessibilityManager am = (AccessibilityManager) getSystemService(ACCESSIBILITY_SERVICE);
boolean isAccessibilityEnabled = am.isEnabled();
boolean isExploreByTouchEnabled = am.isTouchExplorationEnabled();

Novoda have released a library called accessibilitools which does this check. It queries the accessibility manager to check if there are any accessibility services enabled that support the "spoken feedback" flag.

AccessibilityServices services = AccessibilityServices.newInstance(context);
services.isSpokenFeedbackEnabled();

public boolean isSpokenFeedbackEnabled() {
    List<AccessibilityServiceInfo> enabledServices = getEnabledServicesFor(AccessibilityServiceInfo.FEEDBACK_SPOKEN);
    return !enabledServices.isEmpty();
}

private List<AccessibilityServiceInfo> getEnabledServicesFor(int feedbackTypeFlags) {
    return accessibilityManager.getEnabledAccessibilityServiceList(feedbackTypeFlags);
}

You can create an inline function in kotlin like:

fun Context.isScreenReaderOn():Boolean{
    val am = getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager
    if (am != null && am.isEnabled) {
        val serviceInfoList =
            am.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_SPOKEN)
        if (!serviceInfoList.isEmpty())
            return true
    }
    return false}

And then you can just call it whenever you need it like:

if(context.isScreenReaderOn()){
...
}

Tested and works fine for now.