【问题标题】:How to check if Talkback is active in JellyBean如何检查 JellyBean 中的 Talkback 是否处于活动状态
【发布时间】:2012-08-03 14:58:24
【问题描述】:

This question 询问如何知道 Android Talkback 是否处于活动状态;直到果冻豆为止。从 Android 4.1 开始,这些步骤不再起作用,因为提到的光标是空的。

话虽如此,我想问的是是否有办法在 Jelly Bean 中进行相同的检查。

编辑 我试图搜索 TalkBack 代码并找到它here。 为了检查 TalkBack 是否处于活动状态,我使用以下代码:

Intent screenReaderIntent = new Intent("android.accessibilityservice.AccessibilityService");
screenReaderIntent.addCategory("android.accessibilityservice.category.FEEDBACK_SPOKEN");
List<ResolveInfo> screenReaders = getPackageManager().queryIntentServices(screenReaderIntent, 0);
Cursor cursor = null;
ContentResolver cr = getContentResolver();
for (ResolveInfo screenReader : screenReaders) {
    cursor = cr.query(Uri.parse("content://" + screenReader.serviceInfo.packageName
            + ".providers.StatusProvider"), null, null, null, null);
    //here, cursor is not null, but calling cursor.moveToFirst() returns false, which means the cursor is empty
}

话虽如此,如果光标为空,我们如何知道 TalkBack 是否正在运行?

编辑 2 根据@JoxTraex 的建议,我现在发送一个广播来查询是否启用了 TalkBack:

Intent i = new Intent();
i.setAction("com.google.android.marvin.talkback.ACTION_QUERY_TALKBACK_ENABLED_COMMAND");
sendBroadcast(i);

现在我应该如何接收响应?

我尝试将以下内容添加到清单中,但我的接收器没有收到任何响应:

<receiver android:name="my.package.MyBroadcastReceiver"
android:permission="com.google.android.marvin.talkback.PERMISSION_SEND_INTENT_BROADCAST_COMMANDS_TO_TALKBACK">
<intent-filter>
    <action android:name="com.google.android.marvin.talkback.ACTION_QUERY_TALKBACK_ENABLED_COMMAND" />
</intent-filter>

【问题讨论】:

  • 我的建议是浏览 AOSP 源代码,看看哪些 API 用于 TalkBack。 TalkBack 的源代码是否可用。
  • @JoxTraex 感谢您的回复。我用新信息编辑了帖子,您有什么建议吗?

标签: android accessibility talkback android-4.1-jelly-bean


【解决方案1】:

使用AccessibilityManager 可以更轻松地实现这一点。

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

【讨论】:

  • 我想在屏幕阅读器处于活动状态时禁用一项功能,这对我来说非常有效。谢谢! :)
【解决方案2】:

您可以检查已启用的语音无障碍服务器

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
}

【讨论】:

    【解决方案3】:

    在查看 TalkBackService.java 时,我发现了这些代码段。这些细分应该提供一些关于如何查询状态的见解。

    代码

    /**
         * {@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);
                }
            }
                ...
        }
    

    说明

    您必须使用以下操作向 TalkBackService 发送 Intent 广播:

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

    然后检查 Extras 的内容并进行相应的处理。

    确保您拥有正确的权限:

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

    【讨论】:

    • 所以我想我应该使用Intent i = new Intent(); i.setAction(ACTION_QUERY_TALKBACK_ENABLED_COMMAND); sendBroadcast(i); 来发送广播。但是如何得到答案呢?我应该在应用清单中声明一个接收器,它会收到答案吗?
    • 你好@JoxTraex!我试图弄清楚如何从广播中接收响应,但到目前为止我没有成功(我在BroadcastReceiver 中没有收到任何答案)。您能否更详细地解释如何接收对讲的响应?
    • 赞成建议,但我发布了我找到的解决方案
    • 嘿看...我在 TODO 中! :) 如果您刚刚偶然发现此页面,请避免使用此方法,因为无法保证屏幕阅读器支持此行为。如有必要,请改为使用AccessibilityManager 查询屏幕阅读器状态。
    【解决方案4】:

    我不确定这是实现建议的最佳方式,但我设法通过使用以下代码完成了这项工作:

    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
            }
        }
    }
    

    这可能不是最好的方法,但它是我能想到的唯一一种适用于 Jelly Bean 和以前的 Android 版本的方法

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-11
      • 2019-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多