How to check if Talkback is active in JellyBean

后端 未结 4 1349
半阙折子戏
半阙折子戏 2021-01-06 08:49

This question asked how to know if Android Talkback is active; that worked until Jelly Bean. Starting from Android 4.1, that steps no longer work, because the mentioned curs

相关标签:
4条回答
  • 2021-01-06 09:04

    This can be achieved much easier by using AccessibilityManager.

    AccessibilityManager am = (AccessibilityManager) getSystemService(ACCESSIBILITY_SERVICE);
    boolean isAccessibilityEnabled = am.isEnabled();
    boolean isExploreByTouchEnabled = am.isTouchExplorationEnabled();
    
    0 讨论(0)
  • 2021-01-06 09:08

    While looking at TalkBackService.java, I found these code segments. These segments should provide some insight on how to query the status.

    Code

    /**
         * {@link Intent} broadcast action for querying the state of TalkBack. </p>
         * Note: Sending intent broadcast commands to TalkBack must be performed
         * through {@link Context#sendBroadcast(Intent, String)}
         */
        @Deprecated
        // TODO(caseyburkhardt): Remove when we decide to no longer support intent broadcasts for
        // querying the current state of TalkBack.
        public static final String ACTION_QUERY_TALKBACK_ENABLED_COMMAND = "com.google.android.marvin.talkback.ACTION_QUERY_TALKBACK_ENABLED_COMMAND";
    
        /**
         * Result that TalkBack is enabled.
         *
         * @see #ACTION_QUERY_TALKBACK_ENABLED_COMMAND
         */
        public static final int RESULT_TALKBACK_ENABLED = 0x00000001;
    
        /**
         * Result that TalkBack is disabled.
         *
         * @see #ACTION_QUERY_TALKBACK_ENABLED_COMMAND
         */
        public static final int RESULT_TALKBACK_DISABLED = 0x00000002;
    
        /**
         * Permission to send {@link Intent} broadcast commands to TalkBack.
         */
        public static final String PERMISSION_SEND_INTENT_BROADCAST_COMMANDS_TO_TALKBACK = "com.google.android.marvin.talkback.PERMISSION_SEND_INTENT_BROADCAST_COMMANDS_TO_TALKBACK";
    
        /**
         * Tag for logging.
         */
        private static final String LOG_TAG = "TalkBackService";
    
    public static final String ACTION_QUERY_TALKBACK_ENABLED_COMMAND = "com.google.android.marvin.talkback.ACTION_QUERY_TALKBACK_ENABLED_COMMAND";
    ..
    
                } else if (ACTION_QUERY_TALKBACK_ENABLED_COMMAND.equals(intentAction)) {
                // TODO(caseyburkhardt): Remove this block when we decide to no
                // longer support
                // intent broadcasts for determining the state of TalkBack in
                // favor of the content
                // provider method.
                if (sInfrastructureInitialized) {
                    setResultCode(RESULT_TALKBACK_ENABLED);
                } else {
                    setResultCode(RESULT_TALKBACK_DISABLED);
                }
            }
                ...
        }
    

    Explanation

    You must send an Intent broadcast to the TalkBackService using the action of:

    public static final String ACTION_QUERY_TALKBACK_ENABLED_COMMAND = "com.google.android.marvin.talkback.ACTION_QUERY_TALKBACK_ENABLED_COMMAND";
    

    Then examine the contents of the Extras and process it accordingly.

    ALSO insure that you have the right permission:

    public static final String PERMISSION_SEND_INTENT_BROADCAST_COMMANDS_TO_TALKBACK = "com.google.android.marvin.talkback.PERMISSION_SEND_INTENT_BROADCAST_COMMANDS_TO_TALKBACK";
    
    0 讨论(0)
  • 2021-01-06 09:16

    I'm not sure this is the best way of achieving what is proposed, but I managed to make this work by using the following code:

    Intent screenReaderIntent = new Intent("android.accessibilityservice.AccessibilityService");
    screenReaderIntent.addCategory("android.accessibilityservice.category.FEEDBACK_SPOKEN");
    List<ResolveInfo> screenReaders = getPackageManager().queryIntentServices(screenReaderIntent, 0);
    Cursor cursor = null;
    int status = 0;
    ContentResolver cr = getContentResolver();
    
    List<String> runningServices = new ArrayList<String>();
    ActivityManager manager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
    for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
        runningServices.add(service.service.getPackageName());
    }
    
    for (ResolveInfo screenReader : screenReaders) {
        cursor = cr.query(Uri.parse("content://" + screenReader.serviceInfo.packageName
                + ".providers.StatusProvider"), null, null, null, null);
    
        if (cursor != null && cursor.moveToFirst()) { //this part works for Android <4.1
            status = cursor.getInt(0);
            cursor.close();
            if (status == 1) {
                //screen reader active!
            } else {
                //screen reader inactive
            }
        } else {  //this part works for Android 4.1+
            if (runningServices.contains(screenReader.serviceInfo.packageName)) {
                //screen reader active!
            } else {
                //screen reader inactive
            }
        }
    }
    

    Probably this is not the best way but it is the only one I can think of that works in Jelly Bean and in previous Android versions

    0 讨论(0)
  • 2021-01-06 09:21

    You can check the enabled spoken accessibility servers

    fun Context.isScreenReaderEnabled(): Boolean {
        val accessibilityManager = getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager
    
        if (!accessibilityManager.isEnabled)
            return false
    
        val serviceInfoList = accessibilityManager.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_SPOKEN)
    
        if (serviceInfoList.isNullOrEmpty())
            return false
    
        return true
    }
    
    0 讨论(0)
提交回复
热议问题