通过AccessibilityService(无障碍服务)自动在设置界面打开App所需要的对应权限

本文介绍了如何利用Android的AccessibilityService类来自动设置应用权限,特别是在华为Honor9i(Android 9.0)设备上。通过监听系统设置界面的事件,模拟用户操作,如点击和滑动,逐步开启所需权限。代码示例展示了监听不同界面元素并执行相应操作的逻辑,但需要注意的是,由于不同手机设置界面的差异,实际应用中需要针对不同机型进行适配。
摘要由CSDN通过智能技术生成

最近看到一个项目比如说需要允许访问应用权限、以及录屏等权限的时候 在手机运行的时候点击跳转至无障碍界面点击打开无障碍服务,然后调转至设置界面,然后手机就自动的一步一步的打开App所需的权限,看起来特别牛逼和智能的亚子。了解了一下发现通过AccessibilityService这个类可以完成上述需求。但是由于每款手机的设置界面是不相同的,所以需要做不同的机型判断适配机型。我的是在华为 Honor 9i(Android 9.0系统)中完成自动设置权限的功能的。

关于AccessibilityService类我就不做过多的解释了,直接撸代码

1.在清单文件的application中添加:

    <service
        android:name="com.hxf.childapp.AutoDebugService"
        android:enabled="true"
        android:exported="true"
        android:label="你的包名"
        android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
        <intent-filter>
            <action android:name="android.accessibilityservice.AccessibilityService"/>
        </intent-filter>
        <meta-data
            android:name="android.accessibilityservice"
            android:resource="@xml/autodebug"/>
    </service>

2.配置需要监听的包名和行为,也就是@xml/autodebug文件:在xml文件夹中创建autodebug文件。

<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:accessibilityEventTypes="typeAllMask|typeWindowStateChanged|typeWindowContentChanged"
    android:accessibilityFeedbackType="feedbackGeneric"
    android:accessibilityFlags="flagReportViewIds"
    android:canPerformGestures="true"
    android:notificationTimeout="100"
    android:canRetrieveWindowContent="true"
    android:packageNames="com.android.settings" />

这里说一下 android:packageNames中的值就是需要监听的应用。

3.创建AutoDebugService类继承自AccessibilityService类:

public class AutoDebugService extends AccessibilityService {
	
}

4.重写方法:

@Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
    
    }

需要重写的核心方法 所有事件都是从这个方法监听的,比如界面改变,点击,长按等事件。

5.通过事件判断是否监听:

if (AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED == event.getEventType() || AccessibilityEvent.TYPE_VIEW_CLICKED == event.getEventType()) {

}

此处我是通过界面改变和点击事件进行过滤,逻辑都是写在此回调方法中,

以下就是全部代码,只供参考思路,不同的手机是需要适配的。

public class AutoDebugService extends AccessibilityService {
    int index = 0;

    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        if (AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED == event.getEventType() || AccessibilityEvent.TYPE_VIEW_CLICKED == event.getEventType()) {
            if (step == 0) {
                try {
                    Thread.sleep(700);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED == event.getEventType()) {
                    event("com.android.settings:id/dashboard_container", "帐户");
                    Log.e("lee", step + "*******");
                }
            } else if (step == 1) {
                try {
                    Thread.sleep(700);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED == event.getEventType()) {
                    Log.e("lee", step + "*******");
                    back();
                }
            } else if (step == 2) {
                if (AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED == event.getEventType()) {
                    back();
                }
            } else if (step == 3) {
                Log.e("lee", step + "*******");
                try {
                    Thread.sleep(700);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED == event.getEventType()) {
                    event("com.android.settings:id/dashboard_container", "安全和隐私");
                }
            } else if (step == 4) {
                Log.e("lee", step + "*******");
                try {
                    Thread.sleep(700);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                back();
            } else if (step == 5) {
                try {
                    Thread.sleep(700);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                back();
            } else if (step == 6) {
                Log.e("lee", step + "*******");
                try {
                    Thread.sleep(700);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                event("com.android.settings:id/dashboard_container", "桌面和壁纸");
            } else if (step == 7) {
                Log.e("lee", step + "*******");
                try {
                    Thread.sleep(700);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                event("com.android.settings:id/list", "桌面风格");
            } else if (step == 8) {
                Log.e("lee", step + "*******");
                try {
                    Thread.sleep(700);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                event("com.android.settings:id/normal_l_ui_sector", "标准风格");
            } else if (step == 9) {
                Log.e("lee", step + "*******");
                try {
                    Thread.sleep(700);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                back();
            } else if (step == 10) {
                Log.e("lee", step + "*******");
                try {
                    Thread.sleep(700);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                back();
            } else if (step == 11) {
                try {
                    Thread.sleep(700);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                back();
            } else if (step == 12) {
                Log.e("lee", step + "*******");
                try {
                    Thread.sleep(700);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                event("com.android.settings:id/dashboard_container", "应用");
            } else if (step == 13) {
                Log.e("lee", step + "*******");
                try {
                    Thread.sleep(700);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                event("com.android.settings:id/list", "应用分身");
            } else if (step == 14) {
                Log.e("lee", step + "*******");
                try {
                    Thread.sleep(700);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                check("com.android.settings:id/clone_app_switche");
            } else if (step == 15) {
                Log.e("lee", step + "*******");
                try {
                    Thread.sleep(700);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                back();
            } else if (step == 16) {
                Log.e("lee", step + "*******");
                try {
                    Thread.sleep(700);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                back();
            } else if (step == 17) {
                try {
                    Thread.sleep(700);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                back();
            } else if (step == 18) {
                Log.e("lee", step + "*******");
                try {
                    Thread.sleep(700);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                event("com.android.settings:id/dashboard_container", "应用");
            } else if (step == 19) {
                Log.e("lee", step + "*******");
                try {
                    Thread.sleep(700);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                event("com.android.settings:id/list", "应用启动管理");
            } else if (step == 20) {
                Log.e("lee", step + "*******");
                try {
                    Thread.sleep(700);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                check("com.huawei.systemmanager:id/app_control_switch");
            } else if (step == 21) {
                Log.e("lee", step + "*******");
                try {
                    Thread.sleep(700);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                back();
            } else if (step == 22) {
                Log.e("lee", step + "*******");
                try {
                    Thread.sleep(700);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                back();
            } else if (step == 23) {
                try {
                    Thread.sleep(700);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                back();
            } else if (step == 24) {
                Log.e("lee", step + "*******");
                try {
                    Thread.sleep(700);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                event("com.android.settings:id/dashboard_container", "系统");
            } else if (step == 25) {
                Log.e("lee", step + "*******");
                try {
                    Thread.sleep(700);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                event("com.android.settings:id/list", "开发人员选项");
            } else if (step == 26) {
                Log.e("lee", step + "*******");
                try {
                    Thread.sleep(700);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                event("com.android.settings:id/list", "USB 调试");
            } else if (step == 27) {
                Log.e("lee", step + "*******");
                try {
                    Thread.sleep(700);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                back();
            } else if (step == 28) {
                Log.e("lee", step + "*******");
                try {
                    Thread.sleep(700);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                back();
            } else if (step == 29) {
                Log.e("lee", step + "*******");
                try {
                    Thread.sleep(700);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                back();
            }
        }
    }

    /**
     * 通过Id获取AccessibilityNodeInfo
     *
     * @param id
     * @return
     */
    private List<AccessibilityNodeInfo> findNodesById(String id) {
        AccessibilityNodeInfo root = getRootInActiveWindow();
        if (root != null) {
            return root.findAccessibilityNodeInfosByViewId(id);
        }
        return null;
    }

    /**
     * 通过Text获取AccessibilityNodeInfo
     *
     * @param text
     * @return
     */
    private List<AccessibilityNodeInfo> findNodesByText(String text) {
        AccessibilityNodeInfo root = getRootInActiveWindow();
        if (root != null) {
            return root.findAccessibilityNodeInfosByText(text);
        }
        return null;
    }

    /**
     * 处理事件
     *
     * @param id
     * @param text
     */
    private void event(String id, String text) {
        List<AccessibilityNodeInfo> byIdList = findNodesById(id);
        List<AccessibilityNodeInfo> byTextList = findNodesByText(text);
        if (byTextList != null && byTextList.size() > 0) {
            AccessibilityNodeInfo info = byTextList.get(0);
            if (!info.isChecked()) {
                info.getParent().performAction(AccessibilityNodeInfo.ACTION_CLICK);
                step++;
            } else {
                byTextList.get(0).performAction(AccessibilityNodeInfo.ACTION_CLICK);
                step++;
            }
        } else {
            if (byIdList != null && byIdList.size() > 0) {
                byIdList.get(0).performAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
            }
        }
    }

    private void check(String id) {
        List<AccessibilityNodeInfo> byIdList = findNodesById(id);
        if (byIdList != null && byIdList.size() > 0) {
            for (int i = 0; i < byIdList.size(); i++) {
                if (!byIdList.get(i).isChecked()) {
                    byIdList.get(i).performAction(AccessibilityNodeInfo.ACTION_CLICK);
                }
            }
        }
        step++;
    }


    /**
     * 返回上一层级
     */
    private void back() {
        performGlobalAction(GLOBAL_ACTION_BACK);
        step++;
    }
}

调用的方法,先判断是否打开了无障碍服务:
如果打开了就跳转到设置界面进行一步一步的设置

if (isAccessibilitySettingsOn(AutoDebugService.class.getName())) {//打开了无障碍权限
                Intent intent = new Intent(Settings.ACTION_SETTINGS);
                startActivity(intent);
            }

未打开的话就去打开:

 Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
startActivityForResult(intent, REQUEST_ACCESSIBLE_PERMISSION);

以上就完成了自动设置权限的功能。 如果不知道视图的id 可以使用sdk自带的DDMS工具查看视图。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值