如何检查辅助功能服务是否崩溃(Android Pie现在在设置中显示此信息)?

watbbzwu  于 2022-12-02  发布在  Android
关注(0)|答案(3)|浏览(255)

我发现Android 9现在shows info if accessibility service stopped working.

对于试图利用可访问性API的开发人员来说,这一直是一个痛苦。

  • 辅助功能看起来像是已启用,但服务已停止。要使其恢复工作,需要关闭辅助功能,然后再打开。
  • 如果谷歌能完全修复这个问题,我会很高兴,但现在他们只是暗示手动禁用启用它是件好事。

不是最好的东西,但至少有一些东西。

  • 所以,我试着找出系统是如何知道服务是否崩溃的。碰巧有一个名为AccessibilityUtil的类,它包含hasServiceCrashed方法。
  • 不幸的是,它会检查AccessibilityNodeInfo中的一个隐藏字段crashed,该字段不适用于第三方开发者(因为反射拒绝),也不适用于以前的Android版本。

所以我想知道是否有一个替代的方法来从系统中获取信息,澄清我的无障碍服务崩溃/停止工作,用户的行动是必需的。从棒棒糖开始。提示感谢。

eit6fx6z

eit6fx6z1#

我想出了一个主意,使用一个静态布尔值来指示可访问性服务的状态,并将其与Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES进行比较。我在多个设备上进行了测试,没有发现此方法有任何问题。
1.在辅助功能服务中声明静态布尔值。

private static boolean bServiceRunning = false;

2.在可访问性服务中,设置onServiceConnectedonUnbind中的布尔值

@Override
protected void onServiceConnected() {

    super.onServiceConnected();
    bServiceRunning = true; //put this at the very beginning to reduce time gap
}

@Override
public boolean onUnbind(Intent intent) {
        
   bServiceRunning = false;
   return super.onUnbind(intent);
}

3.在可访问性服务中创建静态函数

public static boolean bGetServiceStatus(){
    return bServiceRunning;
}

通过布尔标志,我可以知道辅助功能服务是否在期望的状态下运行。当服务被强制停止时,onUnbind将被调用,因此布尔值变为false。
4.我们使用Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES来获取可访问性服务切换状态

public static boolean bIsAccessibilityServiceEnabled(Context context, Class<?> accessibilityService) {

        ComponentName expectedComponentName = new ComponentName(context, accessibilityService);
        String strServicesSettingResult = Settings.Secure.getString(context.getContentResolver(),  Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
        if (strServicesSettingResult == null){
            return false;
        }

        TextUtils.SimpleStringSplitter colonSplitter = new TextUtils.SimpleStringSplitter(':');
        colonSplitter.setString(strServicesSettingResult);

        while (colonSplitter.hasNext()) {
            String strComponentName = colonSplitter.next();
            ComponentName enabledService = ComponentName.unflattenFromString(strComponentName);

            if (enabledService != null && enabledService.equals(expectedComponentName))
                return true;
        }

        return false;
    }

5.这也是我们想要的,我们使用上述两种方法进行检查,以确定可访问性服务的真实的状态。

public static int intIsAccessibilityServiceEnabled_WithCrashCheck(Context context, Class<?> accessibilityService){
        //return 0 if Accessibility Service enabled and running
        //return -1 if Accessibility Service disabled and not running
        //return -2 if Accessibility Service enabled but stopped working or crashed

        //first check Accessibility Service boolean

        if(bGetServiceStatus()){
            //service is running
            return 0;
        }else{
            //service not running, now double check with Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES
            boolean bResult = bIsAccessibilityServiceEnabled(context, accessibilityService);

            if(!bResult){
                //Accessibility Service is disabled
                return -1;
            }else{
                //Accessibility Service is enabled, but service is not actually running, Accessibility Service is crashed
                return -2;
            }
        }

    }

使用“AccessibilityManager”也是一样的,但是我更喜欢一个带有静态布尔值的更“轻量级”的版本,以获得更好的性能。
注意:使用Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES而不进行再次检查会导致错误。值不同步。结果并不总是代表真实的的服务状态。以下步骤可能会导致这种情况:
1.启动辅助功能服务,然后转到应用程序设置强制停止应用程序。
1.现在您可以看到辅助功能服务开关已关闭。(目前看来已经足够了,但下一步会产生问题)
1.再次启动辅助功能服务,在Android 9.0以上的设备上,您会发现开关是打开的,但服务实际上没有运行,现在它显示“Not working. Tap for info”。
2022年11月29日编辑:此错误已根据this issue tracker修复。我不能再在我的新Android 12和13设备上重现此错误。然而,使用旧Android固件的设备仍有此错误。(此补丁也适用于最新的AVD映像。要在AVD上测试此错误,现在您必须下载旧版本的AVD映像。)

sulc1iza

sulc1iza2#

Android通常会阻止应用程序在反复崩溃时运行。无障碍服务的这种行为显然会影响依赖该服务的用户,但由于这些服务可以有效地控制UI,因此如果应用程序反复崩溃,也可能导致设备无法使用。
我没有想到其他人会对AccessibilityServiceInfo中的崩溃字段感兴趣。不幸的是,我使用仅对系统可用的数据填充了该字段。我将启用的服务列表与绑定的服务列表进行了比较。
如果您对服务是否被阻止运行感兴趣,您可能会通过跟踪onBind和onUnbind的调用时间并从AccessibilityManager查看已启用服务的列表来执行类似的操作。

3htmauhk

3htmauhk3#

我不知道这是不是一个解决方案。但我发现当它不起作用:如果我使用“dumpsys accessibility",服务部分为空,如下所示:

User state[attributes:{id=0, 
                       currentUser=true, 
                       touchExplorationEnabled=false,  
                       displayMagnificationEnabled=false,   
                       navBarMagnificationEnabled=false,  
                       autoclickEnabled=false}
           services:{}]

也许你可以检查一下服务是否为空。

相关问题