安卓无障碍笔记-AccessibilityService

项目demo地址,demo_accessibility目录下;
https://gitee.com/catface7/catface_app

核心服务lib模块

在这里插入图片描述

  • res>xml>accessibility_config.xml

    <?xml version="1.0" encoding="utf-8"?>
    <accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
        android:accessibilityEventTypes="typeAllMask"
        android:accessibilityFeedbackType="feedbackGeneric"
        android:accessibilityFlags="flagReportViewIds|flagRetrieveInteractiveWindows|flagRequestFilterKeyEvents"
        android:canPerformGestures="true"
        android:canRequestFilterKeyEvents="true"
        android:canRetrieveWindowContent="true"
        android:description="@string/accessibility_description"
        android:notificationTimeout="100" />
    
  • res>values>strings.xml

    <resources>
        <string name="accessibility_description">辅助功能测试</string>
    </resources>
    
  • AndroidManifest.xml中声明无障碍服务

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="cc.catface.accessibility">
    
        <application>
            <service
                android:name=".ProAccessibilityService"
                android:enabled="true"
                android:exported="true"
                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/accessibility_config" />
            </service>
        </application>
    </manifest>
    
  • 服务启动帮助类AccessibilitySettingOpenHelper

    import android.app.ActivityManager;
    import android.content.ComponentName;
    import android.content.Context;
    import android.content.Intent;
    import android.provider.Settings;
    
    import java.util.List;
    
    public class AccessibilitySettingOpenHelper {
    
        //跳转到开启无障碍设置页面
        public static void jumpToSettingPage(Context context) {
            Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(intent);
        }
    
        //判断自定义辅助功能服务是否开启
        public static boolean isAccessibilitySettingsOn(Context context, String className) {
            if (context == null) return false;
            ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
            if (activityManager == null) return false;
            //判断当前无障碍服务是否在运行服务列表中
            List<ActivityManager.RunningServiceInfo> runningServices = activityManager.getRunningServices(100);
            runningServices.size();
            for (int i = 0; i < runningServices.size(); i++) {
                ComponentName service = runningServices.get(i).service;
                if (service.getClassName().equals(className)) {
                    return true;
                }
            }
            return false;
        }
    }
    
  • 核心服务类ProAccessibilityService,包含根据id,文本内容,描述内容查找控件,模拟控件点击,绝对位置点击等功能;

    import android.accessibilityservice.AccessibilityService;
    import android.accessibilityservice.GestureDescription;
    import android.annotation.SuppressLint;
    import android.graphics.Path;
    import android.graphics.Rect;
    import android.os.CountDownTimer;
    import android.text.TextUtils;
    import android.view.accessibility.AccessibilityEvent;
    import android.view.accessibility.AccessibilityNodeInfo;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;
    import java.util.stream.Collectors;
    
    /**
     * 无障碍
     * rootNode.findAccessibilityNodeInfosByViewId(id): 根据详细id查找控件
     * rootNode.findAccessibilityNodeInfosByText(text): 根据文本内容查找控件
     */
    public class ProAccessibilityService extends AccessibilityService {
        private static final String TAG = "ProAccessibilityService";
    
        private static ProAccessibilityService instance;
    
        public static ProAccessibilityService getInstance() {
            return instance;
        }
    
        //仅根据具体id/文本内容/描述查找控件|全开
        private boolean findByIdEnabled, findByTextEnabled, findByDescEnabled, findByAllEnabled;
        private int textMatchType = 0, descMatchType = 0;//0完全匹配1部分匹配2开头匹配3结尾匹配
        private FindByIdCallback findByIdCallback;
        private FindByTextCallback findByTextCallback;
        private FindByDescCallback findByDescCallback;
        private int[] clickId, clickText, clickDesc;//[0,0,1,1000](p1:0开启点击1关闭点击|p2:点击第几个控件|p3:每次点击前延时)
        private CountDownTimer idTimer, textTimer, descTimer;
    
    
        public void setClickId(int[] clickId) {
            releaseAllTimer();
            this.clickId = clickId;
        }
    
        public void setClickText(int[] clickText) {
            releaseAllTimer();
            this.clickText = clickText;
        }
    
        public void setClickDesc(int[] clickDesc) {
            releaseAllTimer();
            if (originNodeByDesc != null) originNodeByDesc.clear();
            this.clickDesc = clickDesc;
        }
    
        public interface FindByIdCallback {
            //原始节点集合;封装的节点集合
            void byIdResult(List<AccessibilityNodeInfo> originNodes, List<NodeInfo> nodeInfos);
        }
    
        public interface FindByTextCallback {
            //原始节点集合;封装的节点集合
            void byTextResult(List<AccessibilityNodeInfo> originNodes, List<NodeInfo> nodeInfos);
        }
    
        public interface FindByDescCallback {
            //原始节点集合;封装的节点集合
            void byDescResult(List<AccessibilityNodeInfo> originNodes, List<NodeInfo> nodeInfos);
        }
    
        //id/文本内容/描述
        private String id, text, desc;
    
        public void setFindByAllEnabled() {
            this.findByIdEnabled = true;
            this.findByTextEnabled = true;
            this.findByDescEnabled = true;
        }
    
        public void setFindByIdEnabled(FindByIdCallback callback) {
            this.findByIdEnabled = true;
            this.findByTextEnabled = false;
            this.findByDescEnabled = false;
            this.findByIdCallback = callback;
        }
    
        public void setFindByTextEnabled(FindByTextCallback callback) {
            this.findByIdEnabled = false;
            this.findByTextEnabled = true;
            this.findByDescEnabled = false;
            this.findByTextCallback = callback;
        }
    
        public void setFindByDescEnabled(FindByDescCallback callback) {
            this.findByIdEnabled = false;
            this.findByTextEnabled = false;
            this.findByDescEnabled = true;
            this.findByDescCallback = callback;
        }
    
        public void setId(String id) {
            this.id = id;
        }
    
        public void setTextAndFilterType(String text, int type) {
            this.text = text;
            this.textMatchType = type;
        }
    
        public void setDescAndFilterType(String desc, int type) {
            this.desc = desc;
            this.descMatchType = type;
        }
    
    
        @Override//服务初始化连接
        protected void onServiceConnected() {
            super.onServiceConnected();
            instance = this;
        }
    
        //原始节点信息转换目标节点信息
        private List<NodeInfo> getTransNodes(List<AccessibilityNodeInfo> originNodes) {
            List<NodeInfo> nodeInfos = new ArrayList<>();
            for (AccessibilityNodeInfo n : originNodes) {
                if (n.getText() == null) return new ArrayList<>();
                NodeInfo info = new NodeInfo();
                info.setViewIdResourceName(n.getViewIdResourceName());
                info.setText(n.getText());
                info.setContentDescription(n.getContentDescription());
                info.setClassName(n.getClassName());
                info.setPackageName(n.getPackageName());
                info.setChildCount(n.getChildCount());
                Rect rectInScreen = new Rect();
                n.getBoundsInScreen(rectInScreen);
                info.setBoundsInScreen(new int[]{rectInScreen.left, rectInScreen.top, rectInScreen.right, rectInScreen.bottom});
                Rect rectInParent = new Rect();
                n.getBoundsInParent(rectInParent);
                info.setBoundsInParent(new int[]{rectInParent.left, rectInParent.top, rectInParent.right, rectInParent.bottom});
                info.setClickable(n.isClickable());
                nodeInfos.add(info);
            }
            return nodeInfos;
        }
    
        private List<AccessibilityNodeInfo> originNodeByDesc;
    
        @SuppressLint("NewApi")
        private void iteratorNode(AccessibilityNodeInfo rootNode) {
            if (rootNode.getChildCount() != 0) {
                for (int i = 0; i < rootNode.getChildCount(); i++) {
                    AccessibilityNodeInfo child = rootNode.getChild(i);
                    if (child.getChildCount() != 0) {
                        iteratorNode(child);
                    }
                    originNodeByDesc.add(child);
                }
            }
        }
    
        /*显示节点信息*/
        private void showNodesInfo(String byWhat, List<AccessibilityNodeInfo> nodes) {
            if (nodes == null || nodes.size() < 1) return;
            int size = nodes.size();
            for (int i = 0; i < nodes.size(); i++) {
                AccessibilityNodeInfo child = nodes.get(i);
                TLog.d(TAG, "===通过" + byWhat + "查找的节点结果, 第" + (i + 1) + "/" + size + "个", "id:" + child.getViewIdResourceName() + ", 类:" + child.getClassName() + ", 文本:" + child.getText() + ", 描述:" + child.getContentDescription());
            }
        }
    
        private List<AccessibilityNodeInfo> originNodesByText;
        private AccessibilityNodeInfo mClickNodeById;
        private AccessibilityNodeInfo mClickNodeByText;
        private AccessibilityNodeInfo mClickNodeByDesc;
    
        @SuppressLint("NewApi")
        @Override
        public void onAccessibilityEvent(AccessibilityEvent event) {
            if (event == null) return;
            //TLog.d(getClass().getSimpleName(), "=>进入无障碍核心回调onAccessibilityEvent(), packageName:" + event.getPackageName() + ", eventType:" + event.getEventType() + ", idTimer:" + idTimer + ", textTimer:" + textTimer + ", descTimer:" + descTimer);
            AccessibilityNodeInfo rootNode = getRootInActiveWindow();
            if (rootNode == null) return;
    
            //根据id查找
            if (this.findByIdEnabled && this.id != null && !TextUtils.isEmpty(this.id) && this.findByIdCallback != null) {
                TLog.d(TAG, "====================>开始通过id[" + id + "]&clickId[" + Arrays.toString(clickId) + "]查找节点");
                final List<AccessibilityNodeInfo> originNodesById = rootNode.findAccessibilityNodeInfosByViewId(this.id);
                showNodesInfo("id", originNodesById);//打印结果
                this.findByIdCallback.byIdResult(originNodesById, getTransNodes(originNodesById));
                //点击事件
                if (this.clickId != null && this.clickId.length == 3 && this.clickId[0] == 0 && this.clickId[1] < originNodesById.size()) {
                    int clickNodeIndex = this.clickId[1];//第几个控件
                    int intervalMillis = this.clickId[2];//延时(ms)
                    mClickNodeById = originNodesById.get(clickNodeIndex);
                    if (idTimer == null) {
                        idTimer = new CountDownTimer(Integer.MAX_VALUE, intervalMillis) {
                            @Override
                            public void onTick(long l) {
                                performClick(mClickNodeById);
                            }
    
                            @Override
                            public void onFinish() {}
                        };
                        idTimer.start();
                    }
                }
            }
            //根据text查找
            if (this.findByTextEnabled && this.text != null && !TextUtils.isEmpty(this.text) && this.findByTextCallback != null) {
                TLog.d(TAG, "====================>开始通过text[" + text + "]&clickText[" + Arrays.toString(clickText) + "]查找节点");
                originNodesByText = rootNode.findAccessibilityNodeInfosByText(this.text);//根据文本内容查找控件
                //根据文本内容匹配规则过滤[0完全匹配1部分匹配2开头匹配3结尾匹配]
                if (originNodesByText == null || originNodesByText.size() < 1) {
                    this.findByTextCallback.byTextResult(new ArrayList<>(), new ArrayList<>());
                } else {
                    originNodesByText = originNodesByText.stream().filter(accessibilityNodeInfo -> accessibilityNodeInfo.getText() != null).collect(Collectors.toList());
                    if (this.textMatchType == 0) {
                        originNodesByText = originNodesByText.stream().filter(accessibilityNodeInfo -> accessibilityNodeInfo.getText().toString().equals(this.text)).collect(Collectors.toList());
                    } else if (this.textMatchType == 1) {
                        originNodesByText = originNodesByText.stream().filter(accessibilityNodeInfo -> accessibilityNodeInfo.getText().toString().contains(this.text)).collect(Collectors.toList());
                    } else if (this.textMatchType == 2) {
                        originNodesByText = originNodesByText.stream().filter(accessibilityNodeInfo -> accessibilityNodeInfo.getText().toString().startsWith(this.text)).collect(Collectors.toList());
                    } else if (this.textMatchType == 3) {
                        originNodesByText = originNodesByText.stream().filter(accessibilityNodeInfo -> accessibilityNodeInfo.getText().toString().endsWith(this.text)).collect(Collectors.toList());
                    }
                    showNodesInfo("text", originNodesByText);//打印结果
                    this.findByTextCallback.byTextResult(originNodesByText, getTransNodes(originNodesByText));
                }
                //点击事件
                if (this.clickText != null && this.clickText.length == 3 && this.clickText[0] == 0 && this.clickText[1] < originNodesByText.size()) {
                    int clickNodeIndex = this.clickText[1];//第几个控件
                    int intervalMillis = this.clickText[2];//延时(ms)
                    //判断这个控件是否可点
                    mClickNodeByText = originNodesByText.get(clickNodeIndex);
                    if (textTimer == null) {
                        textTimer = new CountDownTimer(Integer.MAX_VALUE, intervalMillis) {
                            @Override
                            public void onTick(long l) {
                                performClick(mClickNodeByText);
                            }
    
                            @Override
                            public void onFinish() {}
                        };
                        textTimer.start();
                    }
                }
            }
            if (this.findByDescEnabled && this.desc != null && !TextUtils.isEmpty(this.desc) && this.findByDescCallback != null) {
                TLog.d(getClass().getSimpleName(), "====================>开始通过desc[" + desc + "]&clickDesc[" + Arrays.toString(clickDesc) + "]查找节点");
                //遍历所有控件
                originNodeByDesc = new ArrayList<>();
                iteratorNode(rootNode);
                //打印遍历的页面所有节点信息
                showNodesInfo("desc[原始]", originNodeByDesc);
                if (originNodeByDesc == null || originNodeByDesc.size() < 1) {
                    this.findByDescCallback.byDescResult(new ArrayList<>(), new ArrayList<>());
                } else {
                    originNodeByDesc = originNodeByDesc.stream().filter(accessibilityNodeInfo -> accessibilityNodeInfo.getContentDescription() != null).collect(Collectors.toList());
                    if (this.descMatchType == 0) {
                        originNodeByDesc = originNodeByDesc.stream().filter(accessibilityNodeInfo -> accessibilityNodeInfo.getContentDescription().toString().equals(this.desc)).collect(Collectors.toList());
                    } else if (this.descMatchType == 1) {
                        originNodeByDesc = originNodeByDesc.stream().filter(accessibilityNodeInfo -> accessibilityNodeInfo.getContentDescription().toString().contains(this.desc)).collect(Collectors.toList());
                    } else if (this.descMatchType == 2) {
                        originNodeByDesc = originNodeByDesc.stream().filter(accessibilityNodeInfo -> accessibilityNodeInfo.getContentDescription().toString().startsWith(this.desc)).collect(Collectors.toList());
                    } else if (this.descMatchType == 3) {
                        originNodeByDesc = originNodeByDesc.stream().filter(accessibilityNodeInfo -> accessibilityNodeInfo.getContentDescription().toString().endsWith(this.desc)).collect(Collectors.toList());
                    }
                    showNodesInfo("desc[过滤]", originNodeByDesc);//打印信息
                    this.findByDescCallback.byDescResult(originNodeByDesc, getTransNodes(originNodeByDesc));
                }
                //点击事件
                if (this.clickDesc != null && this.clickDesc.length == 3 && this.clickDesc[0] == 0 && this.clickDesc[1] < originNodeByDesc.size()) {
                    int clickNodeIndex = this.clickDesc[1];//第几个控件
                    int intervalMillis = this.clickDesc[2];//延时(ms)
                    mClickNodeByDesc = originNodeByDesc.get(clickNodeIndex);
                    if (descTimer == null) {
                        descTimer = new CountDownTimer(Integer.MAX_VALUE, intervalMillis) {
                            @Override
                            public void onTick(long l) {
                                performClick(mClickNodeByDesc);
                            }
    
                            @Override
                            public void onFinish() {}
                        };
                        descTimer.start();
                    }
                }
                //一次全页面搜索控件结束后清空暂存的控件列表
                if (originNodeByDesc != null) {
                    originNodeByDesc.clear();
                    originNodeByDesc = null;
                }
            }
        }
    
        @Override
        public void onInterrupt() {
            releaseAllTimer();
            instance = null;
            TLog.d(TAG, "onInterrupt()");
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
            releaseAllTimer();
            instance = null;
            TLog.d(TAG, "onDestroy()");
        }
    
        private void releaseAllTimer() {
            if (idTimer != null) {
                idTimer.cancel();
                idTimer = null;
            }
            if (textTimer != null) {
                textTimer.cancel();
                textTimer = null;
            }
            if (descTimer != null) {
                descTimer.cancel();
                descTimer = null;
            }
        }
    
        //当前服务是否正在运行
        public static boolean isRunning() {
            return instance != null;
        }
    
        //模拟点击-绝对坐标
        @SuppressLint("NewApi")
        public void performClickAbsXY(int x, int y) {
            Path path = new Path();
            path.moveTo(x - 1, y - 1);
            path.lineTo(x + 1, y + 1);
            TLog.d(TAG, "模拟点击=>performClickAbsXY()=绝对坐标, x:" + x + ", y:" + y);
            dispatchGesture(new GestureDescription.Builder().addStroke(new GestureDescription.StrokeDescription(path, 0, 100)).build(), null, null);
        }
    
        //模拟点击-控件
        private void performClick(AccessibilityNodeInfo... nodes) {
            if (nodes == null || nodes.length < 1) return;
            for (AccessibilityNodeInfo node : nodes) {
                if (!node.isClickable()) continue;
                TLog.d(TAG, "模拟点击=>performClick()=控件, id:" + node.getViewIdResourceName() + ", text:" + node.getText());
                node.performAction(AccessibilityNodeInfo.ACTION_CLICK);
            }
        }
    
        //模拟点击-返回
        @SuppressWarnings("all")
        public boolean performClickBackKey() {
            TLog.d(TAG, "模拟点击=>performClickBackKey()=点击");
            return performGlobalAction(AccessibilityService.GLOBAL_ACTION_BACK);
        }
    }
    
  • 简化的节点信息包装实例NodeInfo

    public class NodeInfo {
        private String viewIdResourceName;//app.catface.accessibility:id/bt1
        private CharSequence text;
        private CharSequence contentDescription;
        private CharSequence className;//android.widget.Button
        private CharSequence packageName;//包名
        private int childCount;//子控件个数
        private int[] boundsInScreen;//屏幕位置
        private int[] boundsInParent;//父布局位置
        private boolean isClickable;
    }
    
  • 日志打印Tlog

    public class TLog {
    
        public static final String DEFAULT_TAG = "accessibility-test";
    
        public static void d(String className, String msg) {
            d(DEFAULT_TAG, className, msg);
        }
    
        public static void d(String tag, String className, String msg) {
            Log.d(tag, "[" + className + "]" + msg);
        }
    }
    

调用示例app模块

  • activity_main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".MainActivity">
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">
    
            <Button
                android:id="@+id/btStartService"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginHorizontal="20dp"
                android:layout_weight="1"
                android:text="开启服务" />
    
            <Button
                android:id="@+id/btStopService"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_marginHorizontal="20dp"
                android:layout_weight="1"
                android:text="关闭服务" />
        </LinearLayout>
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">
    
            <EditText
                android:id="@+id/etDestId"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="3"
                android:hint="控件id"
                android:text="app.catface.accessibility:id/bt1" />
    
            <Button
                android:id="@+id/btSearchId"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="搜索" />
        </LinearLayout>
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">
    
            <EditText
                android:id="@+id/etText"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="3"
                android:hint="节点内容"
                android:text="试试" />
    
            <EditText
                android:id="@+id/etTextMatchType"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:hint="0123"
                android:text="1" />
    
            <Button
                android:id="@+id/btSearchText"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="搜索" />
    
        </LinearLayout>
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">
    
            <EditText
                android:id="@+id/etDesc"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="3"
                android:hint="描述内容"
                android:text="试试" />
    
            <EditText
                android:id="@+id/etDescMatchType"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:hint="0123"
                android:text="1" />
    
            <Button
                android:id="@+id/btSearchDesc"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="搜索" />
    
        </LinearLayout>
    
        <Button
            android:id="@+id/btClearClick"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="取消点击事件" />
    
        <Button
            android:id="@+id/bt2Page2"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="跳转到第二页" />
    
        <Button
            android:id="@+id/btStartClick"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="开启自由点击" />
    
    
        <Button
            android:id="@+id/btClickBack"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="模拟返回" />
    
    </androidx.appcompat.widget.LinearLayoutCompat>
    
  • MainActivity.java

    import android.content.Intent;
    import android.os.Build;
    import android.os.Bundle;
    import android.os.CountDownTimer;
    import android.view.accessibility.AccessibilityNodeInfo;
    import android.widget.EditText;
    import android.widget.Toast;
    
    import androidx.annotation.RequiresApi;
    import androidx.appcompat.app.AppCompatActivity;
    
    import java.util.List;
    
    import cc.catface.accessibility.AccessibilitySettingOpenHelper;
    import cc.catface.accessibility.NodeInfo;
    import cc.catface.accessibility.ProAccessibilityService;
    import cc.catface.accessibility.TLog;
    
    public class MainActivity extends AppCompatActivity implements ProAccessibilityService.FindByIdCallback, ProAccessibilityService.FindByTextCallback, ProAccessibilityService.FindByDescCallback {
    
        @RequiresApi(api = Build.VERSION_CODES.N)
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            //开启无障碍服务
            findViewById(R.id.btStartService).setOnClickListener(v -> {
                if (!AccessibilitySettingOpenHelper.isAccessibilitySettingsOn(this, ProAccessibilityService.class.getName())) {
                    AccessibilitySettingOpenHelper.jumpToSettingPage(this);
                } else {
                    Toast.makeText(this, "无障碍服务已开启", Toast.LENGTH_SHORT).show();
                }
            });
            //关闭无障碍服务
            findViewById(R.id.btStopService).setOnClickListener(v -> {
                ProAccessibilityService.getInstance().disableSelf();
            });
            //跳转到第二页
            findViewById(R.id.bt2Page2).setOnClickListener(v -> {
                startActivity(new Intent(this, SecondActivity.class));
            });
    
            //设置搜索指定控件id
            findViewById(R.id.btSearchId).setOnClickListener(v -> {
                String id = ((EditText) findViewById(R.id.etDestId)).getText().toString();
                ProAccessibilityService.getInstance().setId(id);//指定控件id如:app.catface.accessibility:id/bt1
                ProAccessibilityService.getInstance().setFindByIdEnabled(this);//回调结果
                ProAccessibilityService.getInstance().setClickId(new int[]{0, 0, 3000});//点击:p1=0开启点击;p2=0点击第几个控件;p3点击延时
            });
            //设置搜索内容text
            findViewById(R.id.btSearchText).setOnClickListener(v -> {
                String text = ((EditText) findViewById(R.id.etText)).getText().toString();
                String typeStr = ((EditText) findViewById(R.id.etTextMatchType)).getText().toString();
                //text:文本内容;p2匹配类型[0完全匹配1部分匹配2开头匹配3结尾匹配]
                ProAccessibilityService.getInstance().setTextAndFilterType(text, Integer.parseInt(typeStr));
                ProAccessibilityService.getInstance().setFindByTextEnabled(this);//回调结果
                ProAccessibilityService.getInstance().setClickText(new int[]{0, 0, 3000});//点击:p1=0开启点击;p2=0点击第几个控件;p3点击延时
            });
            //设置搜索描述desc
            findViewById(R.id.btSearchDesc).setOnClickListener(v -> {
                String desc = ((EditText) findViewById(R.id.etDesc)).getText().toString();
                String typeStr = ((EditText) findViewById(R.id.etDescMatchType)).getText().toString();
                //desc:描述内容;p2匹配类型[0完全匹配1部分匹配2开头匹配3结尾匹配]
                ProAccessibilityService.getInstance().setDescAndFilterType(desc, Integer.parseInt(typeStr));
                ProAccessibilityService.getInstance().setFindByDescEnabled(this);//回调结果
                ProAccessibilityService.getInstance().setClickDesc(new int[]{0, 0, 3000});//点击:p1=0开启点击;p2=0点击第几个控件;p3点击延时
            });
    
            //清空模拟点击
            findViewById(R.id.btClearClick).setOnClickListener(v -> {
                ProAccessibilityService.getInstance().setClickId(null);//清空模拟点击
                ProAccessibilityService.getInstance().setClickText(null);//清空模拟点击
                ProAccessibilityService.getInstance().setClickDesc(null);//清空模拟点击
            });
            //模拟点击绝对位置
            findViewById(R.id.btStartClick).setOnClickListener(v -> {
                new CountDownTimer(2000, 2000) {
                    @Override
                    public void onTick(long millisUntilFinished) {}
    
                    @Override
                    public void onFinish() {
                        ProAccessibilityService.getInstance().performClickAbsXY(5, 85);
                    }
                }.start();
            });
            //模拟返回
            findViewById(R.id.btClickBack).setOnClickListener(v -> {
                new CountDownTimer(2000, 2000) {
                    @Override
                    public void onTick(long millisUntilFinished) {}
    
                    @Override
                    public void onFinish() {
                        ProAccessibilityService.getInstance().performClickBackKey();
                    }
                }.start();
            });
        }
    
    
        @Override
        public void byIdResult(List<AccessibilityNodeInfo> originNodes, List<NodeInfo> nodeInfos) {
            for (NodeInfo info : nodeInfos) {
                TLog.d(getClass().getSimpleName(), "IDID节点#RESULT:" + info.toString());
            }
        }
    
        @Override
        public void byTextResult(List<AccessibilityNodeInfo> originNodes, List<NodeInfo> nodeInfos) {
            for (NodeInfo info : nodeInfos) {
                TLog.d(getClass().getSimpleName(), "TEXT内容#RESULT:" + info.toString());
            }
        }
    
        @Override
        public void byDescResult(List<AccessibilityNodeInfo> originNodes, List<NodeInfo> nodeInfos) {
            for (NodeInfo info : nodeInfos) {
                TLog.d(getClass().getSimpleName(), "DESC描述#RESULT:" + info.toString());
            }
        }
    }
    
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值