安卓基础(无障碍点击)

无障碍点击核心代码

java 复制代码
// 自定义无障碍服务类,继承自Android系统的AccessibilityService
public class MyAccessibilityService extends AccessibilityService {

    // 当系统产生无障碍事件时的回调方法(如界面变化、焦点切换等)
    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        // 这里可以监听屏幕内容变化(默认空实现)
    }

    // 当系统需要中断服务时的回调方法(如用户关闭服务)
    @Override
    public void onInterrupt() {
        // 服务中断处理逻辑(默认空实现)
    }

    // 核心方法:通过坐标执行点击操作
    public void clickAtPoint(int x, int y) {
        // 构建手势描述对象
        GestureDescription.Builder builder = new GestureDescription.Builder();
        
        // 创建路径对象(用于定义手势轨迹)
        Path path = new Path();
        // 将路径起点移动到目标坐标
        path.moveTo(x, y);
        // 在同一个坐标点画线(形成点击手势)
        path.lineTo(x, y); // 单点点击的核心逻辑
        
        // 构建手势描述:
        // 添加手势笔画(Stroke),参数说明:
        // path - 手势路径
        // 0    - 开始时间(单位:毫秒,0表示立即开始)
        // 50   - 持续时间(单位:毫秒,50ms足够完成点击)
        GestureDescription gesture = builder
            .addStroke(new GestureDescription.StrokeDescription(path, 0, 50))
            .build();
        
        // 执行手势操作
        dispatchGesture(gesture, new GestureResultCallback() {
            // 手势成功完成的回调
            @Override
            public void onCompleted(GestureDescription gestureDescription) {
                super.onCompleted(gestureDescription);
                Log.d("TAG", "点击完成"); // 日志记录点击成功
            }

            // 手势被取消的回调
            @Override
            public void onCancelled(GestureDescription gestureDescription) {
                super.onCancelled(gestureDescription);
                Log.e("TAG", "点击取消"); // 日志记录点击失败
            }
        }, null); // 第三个参数Handler可设置为null(使用默认线程)
    }
}

无障碍滑动核心代码

java 复制代码
public class MyAccessibilityService extends AccessibilityService {

    // 核心方法:通过坐标执行滑动操作
    public void swipe(int startX, int startY, int endX, int endY, int durationMs) {
        GestureDescription.Builder builder = new GestureDescription.Builder();
        Path path = new Path();
        
        // 定义滑动路径
        path.moveTo(startX, startY);     // 起点
        path.lineTo(endX, endY);          // 终点
        
        // 构建手势描述:
        // 参数说明:
        // path - 滑动路径
        // 0    - 开始时间(0表示立即开始)
        // durationMs - 滑动持续时间(毫秒)
        GestureDescription gesture = builder
            .addStroke(new GestureDescription.StrokeDescription(path, 0, durationMs))
            .build();

        // 执行滑动操作
        dispatchGesture(gesture, new GestureResultCallback() {
            @Override
            public void onCompleted(GestureDescription gestureDescription) {
                super.onCompleted(gestureDescription);
                Log.d("TAG", "滑动完成");
            }

            @Override
            public void onCancelled(GestureDescription gestureDescription) {
                super.onCancelled(gestureDescription);
                Log.e("TAG", "滑动取消");
            }
        }, null);
    }
}

通过无障碍服务在指定坐标 (100,100) 处粘贴剪贴板内容 "你好"

java 复制代码
public class MyAccessibilityService extends AccessibilityService {

    // 核心方法:在指定坐标粘贴文本
    public void pasteTextAtPoint(int x, int y, String text) {
        // 1. 模拟点击坐标以聚焦输入框
        clickAtPoint(x, y);
        
        // 2. 等待输入框获得焦点(建议300-500ms延迟)
        new Handler(Looper.getMainLooper()).postDelayed(() -> {
            // 3. 获取当前窗口根节点
            AccessibilityNodeInfo rootNode = getRootInActiveWindow();
            if (rootNode == null) return;

            // 4. 查找焦点所在的输入控件
            AccessibilityNodeInfo focusedNode = rootNode.findFocus(
                AccessibilityNodeInfo.FOCUS_INPUT
            );
            
            if (focusedNode != null) {
                // 5. 设置剪贴板内容
                setClipboardText(text);
                
                // 6. 执行粘贴操作
                Bundle args = new Bundle();
                args.putInt(
                    AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT, 
                    AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
                );
                focusedNode.performAction(AccessibilityNodeInfo.ACTION_PASTE, args);
                
                // 或者直接设置文本(API 21+)
                // Bundle setTextArgs = new Bundle();
                // setTextArgs.putCharSequence(
                //     AccessibilityNodeInfo.ACTION_ARGUMENT_SET_TEXT_CHARSEQUENCE, 
                //     text
                // );
                // focusedNode.performAction(
                //     AccessibilityNodeInfo.ACTION_SET_TEXT, 
                //     setTextArgs
                // );
            }
            rootNode.recycle();
        }, 500); // 延迟500ms确保焦点稳定
    }

    // 点击坐标方法
    private void clickAtPoint(int x, int y) {
        Path path = new Path();
        path.moveTo(x, y);
        GestureDescription gesture = new GestureDescription.Builder()
            .addStroke(new StrokeDescription(path, 0, 50))
            .build();
        dispatchGesture(gesture, null, null);
    }

    // 设置剪贴板内容
    private void setClipboardText(String text) {
        ClipboardManager clipboard = 
            (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
        ClipData clip = ClipData.newPlainText("label", text);
        clipboard.setPrimaryClip(clip);
    }
}

无障碍返回

java 复制代码
public class MyAccessibilityService extends AccessibilityService {

    // 核心方法:模拟返回键
    public void performBack() {
        // 调用系统级返回操作
        boolean isSuccess = performGlobalAction(GLOBAL_ACTION_BACK);
        Log.d("TAG", "返回操作结果: " + (isSuccess ? "成功" : "失败"));
    }

    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        // 可监听返回操作后的界面变化(可选)
    }

    @Override
    public void onInterrupt() {
        // 中断处理
    }
}

无障碍回到主页

java 复制代码
public class MyAccessibilityService extends AccessibilityService {

    // 核心方法:模拟Home键
    public void pressHomeButton() {
        boolean isSuccess = performGlobalAction(GLOBAL_ACTION_HOME);
        Log.d("TAG", "Home键操作结果: " + (isSuccess ? "成功" : "失败"));
    }

    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        // 可监听界面变化(可选)
    }

    @Override
    public void onInterrupt() {
        // 中断处理
    }
}
相关推荐
安东尼肉店16 小时前
Android compose屏幕适配终极解决方案
android
2501_9160074716 小时前
HTTPS 抓包乱码怎么办?原因剖析、排查步骤与实战工具对策(HTTPS 抓包乱码、gzipbrotli、TLS 解密、iOS 抓包)
android·ios·小程序·https·uni-app·iphone·webview
feiyangqingyun18 小时前
基于Qt和FFmpeg的安卓监控模拟器/手机摄像头模拟成onvif和28181设备
android·qt·ffmpeg
用户2018792831671 天前
ANR之RenderThread不可中断睡眠state=D
android
煤球王子1 天前
简单学:Android14中的Bluetooth—PBAP下载
android
小趴菜82271 天前
安卓接入Max广告源
android
齊家治國平天下1 天前
Android 14 系统 ANR (Application Not Responding) 深度分析与解决指南
android·anr
ZHANG13HAO1 天前
Android 13.0 Framework 实现应用通知使用权默认开启的技术指南
android
【ql君】qlexcel1 天前
Android 安卓RIL介绍
android·安卓·ril
写点啥呢1 天前
android12解决非CarProperty接口深色模式设置后开机无法保持
android·车机·aosp·深色模式·座舱