安卓无障碍获取录屏权限

每次需要录屏操作时,都会弹窗需要用户手动授权比较麻烦,可以通过无障碍模拟用户点击进行授权。

方法主要有三种:

1.查找"立即开始"(华为手机是"允许")节点,模拟点击;

java 复制代码
 @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        Log.i("AccessibilityEvent", event.toString());

        if (event == null || !event.getPackageName().toString()
                .contains("com.android.systemui"))//不写完整包名,是因为某些手机(如小米)安装器包名是自定义的
            return;
        /*
        某些手机安装页事件返回节点有可能为null,无法获取安装按钮
        例如华为mate10安装页就会出现event.getSource()为null,所以取巧改变当前页面状态,重新获取节点。
        该方法在华为mate10上生效,但其它手机没有验证...(目前小米手机没有出现这个问题)
        */
        Log.i(TAG, "onAccessibilityEvent: " + event);
        AccessibilityNodeInfo eventNode = event.getSource();
  

        /*
        模拟点击->立即开始,只验证了小米5s plus(MIUI 9.8.4.26)、小米Redmi 5A(MIUI 9.2)、华为mate 10
        其它品牌手机可能还要适配,适配最可恶的就是出现安装广告按钮,误点安装其它垃圾APP(典型就是小米安装后广告推荐按钮,华为安装开始官方安装)
        */
        AccessibilityNodeInfo nodeInfo= getRootInActiveWindow(); //当前窗口根节点
        if (rootNode == null)
            return;

        if (event.getClassName().toString().contains("MediaProjectionPermissionActivity")) {
           
    List<AccessibilityNodeInfo> nodes = nodeInfo.findAccessibilityNodeInfosByText("立即开始");
        Log.i(TAG, "findTxtClick: " + txt + ", " + nodes.size() + ", " + nodes);
        if (nodes == null || nodes.isEmpty()) {
            return;
        }
        Log.i(TAG, "findTxtClick: " + txt + ", " + nodes.size() + ", " + nodes);
        for (AccessibilityNodeInfo node : nodes) {
            node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
        }
        // 回收节点实例来重用
        if (eventNode != null) {
            eventNode.recycle();
        }

        rootNode.recycle();
    }

2.查找buttonId;经我研究立即开始id是

复制代码
android:id/button1
java 复制代码
 List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewId = rootNode.findAccessibilityNodeInfosByViewId("android:id/button1");
                Log.i(TAG, "findTxtClick: 立即开始"   + "button1 " + findAccessibilityNodeInfosByViewId.size());
                if (findAccessibilityNodeInfosByViewId.size() > 0) {
                    System.out.println("5=====================" + findAccessibilityNodeInfosByViewId.size());
                    Iterator<AccessibilityNodeInfo> it = findAccessibilityNodeInfosByViewId.iterator();
                    while (it.hasNext()) {
                        it.next().performAction(16);
                    }
                    return;
                }

3.某些手机不给你查找,只能查到"取消",这时候需要模拟一个区域,计算这个区域位置与"允许"重合,进行点击。

java 复制代码
  List<AccessibilityNodeInfo> findAccessibilityNodeInfosByViewId2 = nodeInfo.findAccessibilityNodeInfosByViewId("android:id/button3");
            System.out.println("findTxtClick取消 " + findAccessibilityNodeInfosByViewId2.size());
            if (findAccessibilityNodeInfosByViewId2.size() == 0) {
                return;
            }
            AccessibilityNodeInfo accessibilityNodeInfo = findAccessibilityNodeInfosByViewId2.get(0);
            Rect rect = new Rect();
            accessibilityNodeInfo.getBoundsInScreen(rect);
            Path path = new Path();
            int screenWidth = getScreenWidth(this);
            int i = screenWidth - ((rect.left + rect.right) / 2);
            if (i < (screenWidth / 2) + 50 && i > (screenWidth / 2) - 50) {
                if (getResources().getConfiguration().orientation == 1) {
                    float f = i;
                    int i2 = rect.top;
                    int i3 = rect.bottom;
                    path.moveTo(f, ((i2 + i3) / 2) - (i3 - i2));
                } else {
                    float f2 = i;
                    int i4 = rect.top;
                    int i5 = rect.bottom;
                    path.moveTo(f2, ((i4 + i5) / 2) - (i5 - i4));
                }
            } else if (getResources().getConfiguration().orientation == 1) {
                path.moveTo(i, (rect.top + rect.bottom) / 2);
            } else {
                path.moveTo(i, (rect.top + rect.bottom) / 2);
            }
            Gesture(path, 50L, 0L);
            return;
java 复制代码
 public void Gesture(final Path path, final long time, final long delay) {

        new Thread() { // from class: com.stardust.autojs.core.accessibility.AccessibilityService.1
            @Override // java.lang.Thread, java.lang.Runnable
            @SuppressLint({"NewApi"})
            public void run() {
                try {
                    if (path.isEmpty()) {
                        return;
                    }
                    if (Looper.myLooper() == null) {
                        Looper.prepare();
                    }
                    Handler handler = new Handler(Looper.myLooper());
                    Log.i(TAG, "findTxtClick: 立即开始"   + ", dispatchGesture" );
                    dispatchGesture(new GestureDescription.Builder().addStroke(new GestureDescription.StrokeDescription(path, delay, time)).build(), new AccessibilityService.GestureResultCallback() { // from class: com.stardust.autojs.core.accessibility.AccessibilityService.1.1
                        @Override // android.accessibilityservice.AccessibilityService.GestureResultCallback
                        public void onCancelled(GestureDescription gestureDescription) {
                            Log.i(TAG, "findTxtClick: 立即开始"   + ", 没点击" );
                        }

                        @Override // android.accessibilityservice.AccessibilityService.GestureResultCallback
                        public void onCompleted(GestureDescription gestureDescription) {
                            Log.i(TAG, "findTxtClick: 立即开始"   + ", 点击了" );
                            MyApplication.getInstance().closetan=false;
                        }
                    }, handler);

                    Looper.loop();
                } catch (Throwable th) {
                    Log.i(TAG, "findTxtClick: 立即开始"   + ", th"+th.toString());
                    th.printStackTrace();
                }
            }
        }.start();
    }

即便完成了以上操作,还需要配置不同系统版本的xml权限才能成功。

xml

XML 复制代码
<accessibility-service
    xmlns:android="http://schemas.android.com/apk/res/android"


    android:description="@string/readme"
    android:packageNames="com.android.systemui"

    android:accessibilityEventTypes="typeAllMask"

    android:accessibilityFeedbackType="feedbackAllMask"

    android:notificationTimeout="100"

    android:settingsActivity="com.angcyo.SettingsActivity"

    android:accessibilityFlags="flagDefault"
    android:canPerformGestures="true"

    android:canRetrieveWindowContent="true"/>

xml30

XML 复制代码
<accessibility-service
    xmlns:android="http://schemas.android.com/apk/res/android"


    android:description="@string/readme"
    android:packageNames="com.android.systemui"


    android:settingsActivity="com.angcyo.SettingsActivity"


    android:canRequestTouchExplorationMode="true"



    android:accessibilityEventTypes="typeAllMask"
    android:accessibilityFeedbackType="feedbackAllMask"
    android:notificationTimeout="10"
    android:accessibilityFlags="flagRetrieveInteractiveWindows|flagRequestFilterKeyEvents|flagReportViewIds|flagRequestEnhancedWebAccessibility|flagIncludeNotImportantViews"
    android:canRetrieveWindowContent="true"
    android:canRequestEnhancedWebAccessibility="true"
    android:canRequestFilterKeyEvents="false"
    android:canPerformGestures="true"
    android:canTakeScreenshot="true"
 />

xml31

XML 复制代码
<accessibility-service
    xmlns:android="http://schemas.android.com/apk/res/android"


    android:description="@string/readme"
    android:packageNames="com.android.systemui"


    android:settingsActivity="com.angcyo.SettingsActivity"


    android:canRequestTouchExplorationMode="true"



    android:accessibilityEventTypes="typeAllMask"
    android:accessibilityFeedbackType="feedbackAllMask"
    android:notificationTimeout="10"
    android:accessibilityFlags="flagRetrieveInteractiveWindows|flagRequestFilterKeyEvents|flagReportViewIds|flagRequestEnhancedWebAccessibility|flagIncludeNotImportantViews"
    android:canRetrieveWindowContent="true"
    android:canRequestEnhancedWebAccessibility="true"
    android:canRequestFilterKeyEvents="false"
    android:canPerformGestures="true"
    android:canTakeScreenshot="true"
    />

全部代码我已上传 https://download.csdn.net/download/guodashen007/89874977