通过ADB命令开启无障碍服务,导致其他应用的无障碍权限被关闭

首先说一下如何通过adb命令开启无障碍服务(需要root权限)

try {
                Process process = Runtime.getRuntime().exec("su");
                DataOutputStream dos = new DataOutputStream(process.getOutputStream());
                dos.writeBytes("dumpsys deviceidle whitelist +com.example.beautycamera\n");//获取电池白名单权限
                dos.flush();
                dos.writeBytes("settings put secure enabled_accessibility_services com.example.beautycamera/.MyAccessibilityService\n");//开启无障碍服务
                dos.flush();
         
            } catch (IOException e) {
                e.printStackTrace();
            }

通过以上命令可以直接无感开启无障碍服务,当然也可以跳转设置让用户手动开启

Intent intent = new Intent(android.provider.Settings.ACTION_ACCESSIBILITY_SETTINGS);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(intent);

目前我有多个应用用到无障碍服务,发现一个应用通过adb开启后,另一个就会被关闭,原因:

  1. 无障碍服务的排他性
    Android系统设计中,某些版本对无障碍服务的启用有较强的排他性。每次启用一个新的无障碍服务时,系统会重新初始化无障碍服务列表。这意味着,如果你通过ADB 命令启用了一个新的无障碍服务,系统会将所有其他未在当前列表中的服务关闭或禁用,以确保只有你刚启用的服务是有效的。
  2. 系统安全限制
    无障碍服务被认为是一个非常高权限的功能,允许应用程序读取屏幕内容、自动点击等操作。为了防止恶意应用程序滥用此功能,Android
    系统会在无障碍服务配置发生变化时进行严格的权限检查,从而移除掉可能存在风险或未经用户明确同意的服务。
  3. ADB 命令修改无障碍服务状态
    使用 ADB 命令启用无障碍服务时,通常会使用类似以下的命令:
adb shell settings put secure enabled_accessibility_services your.package.name/your.service.name

这个命令直接修改了系统的无障碍服务设置,它会将无障碍服务列表重置为你指定的服务,清空了其他未被包括在内的服务。因此,其他应用的无障碍服务会被系统视为未启用状态,从而被关闭。

解决方案

保留现有的无障碍服务 如果你希望在启用新的无障碍服务时保留现有的服务,可以首先获取当前已启用的无障碍服务列表,然后在启用新服务时将它们一起设置。你可以通过以下命令获取已启用的服务列表:

adb shell settings get secure enabled_accessibility_services

也可以通过AccessibilityManager来获取已开启无障碍列表:

// 获取AccessibilityManager实例
        AccessibilityManager accessibilityManager = (AccessibilityManager) getSystemService(Context.ACCESSIBILITY_SERVICE);
        List<AccessibilityServiceInfo> enabledServices = accessibilityManager.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_ALL_MASK);

然后,将新服务和已有服务拼接在一起,再重新设置回系统:(拼接要用 : 分割)

adb shell settings put secure enabled_accessibility_services your.package.name/your.service.name:your.package.name2/your.service.name2

逐步启用无障碍服务 避免一次性直接通过 ADB 命令覆盖无障碍服务列表,而是逐步启用服务,以确保其他服务不会被意外禁用。

判断无障碍权限是否获取到方法

// 获取AccessibilityManager实例
AccessibilityManager accessibilityManager = (AccessibilityManager) getSystemService(Context.ACCESSIBILITY_SERVICE);

// 检查无障碍服务是否已开启
boolean isAccessibilityEnabled = accessibilityManager.isEnabled();

这个方法判断不准确,有开启任意一个无障碍返回就是true,实际本身应用没有开启,可以通过获取无障碍列表,然后看看是否包含当前应用包名来判断,完整代码:

new Thread() {
            @Override
            public void run() {
                try {
                    Process process = Runtime.getRuntime().exec("su");
                    DataOutputStream dos = new DataOutputStream(process.getOutputStream());
                    dos.writeBytes("settings get secure enabled_accessibility_services\n");//获取无障碍服务列表
                    dos.flush();
                    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));

                    while (isRead) {
                        String line = null;
                        line = bufferedReader.readLine();

                        if (!TextUtils.isEmpty(line)) {
                            isRead = false;
                            Log.e("TAG", "enabled_accessibility_services: " + line);
                            if(!line.contains(getPackageName())){//不包含说明没开启无障碍服务
                                dos.writeBytes("dumpsys deviceidle whitelist +com.example.beautycamera\n");//获取电池白名单权限
                                dos.flush();
                                dos.writeBytes("settings put secure enabled_accessibility_services "+line+":com.example.beautycamera/.MyAccessibilityService\n");//开启无障碍服务
                                dos.flush();
                            }
                        }

                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }finally {
                    isRead = false;
                }
            }
        }.start();

通过AccessibilityManager获取列表实现:

// 获取AccessibilityManager实例
        AccessibilityManager accessibilityManager = (AccessibilityManager) getSystemService(Context.ACCESSIBILITY_SERVICE);
        List<AccessibilityServiceInfo> enabledServices = accessibilityManager.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_ALL_MASK);
   
        String enabled_accessibility_services = "";
        for (int i = 0; i < enabledServices.size(); i++) {
            if(i == 0){
                enabled_accessibility_services+=enabledServices.get(i).getId();
            }else{
                enabled_accessibility_services+=":"+enabledServices.get(i).getId();
            }
        }
        Log.d(TAG, "=======enabled_accessibility_services: "+enabled_accessibility_services);
        if(enabled_accessibility_services.contains(getPackageName())){
            isAccessibilityEnabled = true;
        }
        Log.e("TAG", "====isAccessibilityEnabled: " + isAccessibilityEnabled);
        if(!isAccessibilityEnabled){
            try {
                Process process = Runtime.getRuntime().exec("su");
                DataOutputStream dos = new DataOutputStream(process.getOutputStream());
                dos.writeBytes("dumpsys deviceidle whitelist +com.example.startapp\n");//获取电池白名单权限
                dos.flush();
                dos.writeBytes("settings put secure enabled_accessibility_services "+enabled_accessibility_services+":com.example.startapp/.MyAccessibilityService\n");//开启无障碍服务
                dos.flush();


            } catch (IOException e) {
                e.printStackTrace();
            }
        }

总结

使用 ADB 命令直接开启无障碍服务时,会因为重置系统无障碍服务设置而导致其他服务被关闭。为了避免这个问题,你可以在修改之前获取当前服务列表,并在启用新的服务时合并已有服务列表。这样可以减少对其他应用无障碍服务的影响。

Android开发中,要通过`adb shell`命令启用应用程序的无障碍(Accessibility)权限,首先需要获取设备的root权限,因为通常开发者模式或ADB Shell操作需要这个权限。以下是步骤: 1. **连接设备**: 使用USB线将手机连接到电脑,并确保手机处于调试模式(设置 -> 关于手机 -> 调试选项打开)。 2. **启动ADB shell**: 打开命令行终端(Windows用户可以打开CMD或PowerShell),然后输入 `adb devices` 确认设备已连接,如果显示设备信息,则表示连接成功。接着运行 `adb shell` 进入设备的shell环境。 3. **进入应用目录**: 切换到包含目标应用的文件夹,这通常是 `/data/app/<package_name>`,其中 `<package_name>` 是应用的包名。例如: ``` cd /data/app/com.example.myapp ``` 4. **启用无障碍权限**: 使用 `chmod` 命令改变权限,允许当前用户(通常为adb)访问无障碍服务。假设应用的文件名为 `myapp.apk`,则运行: ``` chmod 755 myapp.apk ``` 如果应用是系统应用,可能需要更高权限,如 `chmod 644 myapp.apk` 或者 `su` 后执行。 5. **重启应用**: 为了应用能读取新权限,需要重启应用。在shell中,运行: ``` am force-stop com.example.myapp monkey -p com.example.myapp 1 ``` 第二条命令使用 Monkey 工具快速启动应用一次,以便它加载新的权限。 6. **检查权限**: 最后,你可以检查应用是否启用了无障碍权限,可以在shell中使用 `dumpsys accessibility service <package_name>` 来查看。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ぃ随风逍遥う

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值