Bootstrap

android模拟点击

模拟点击两套方案:

1、使用Instrumentation

                new Thread(() -> {
                    Instrumentation inst = new Instrumentation();
                    long curTime = SystemClock.uptimeMillis();
                    inst.sendPointerSync(MotionEvent.obtain(curTime, curTime,
                            MotionEvent.ACTION_DOWN, otr.x, otr.y, 0));
                    inst.sendPointerSync(MotionEvent.obtain(curTime, curTime,
                            MotionEvent.ACTION_UP, otr.x, otr.y, 0));
                }).start();

问题:应用内界面没有问题,能正常触发点击效果

但是在应用外的界面(当前应用后台运行,在其他应用界面),比如系统设置的界面,出现的是长按的效果。如下视频。

2024-10-29-15-58-43_模拟点击异常_哔哩哔哩_bilibili

2、用adb模拟点击

input tap x y
。。。。。。
                new Thread(() -> {
                    String cmd = "input tap " + otr.x + " " + otr.y;
                    Log.d(TAG, "forceClick cmd: " + cmd);
                    CmdUtils.fetchRoot(cmd);
                }).start();
。。。。。。


// CmdUtils.java
package com.example.helloworld.utils;

import android.util.Log;

import java.io.DataOutputStream;
import java.io.IOException;

public class CmdUtils {
    public static String execRootCmd(String cmd) {
        String content = "";
        cmd = cmd.replace("adb shell", "");
        //先获取root权限
//        fetchRootCmd();
        try {
            Process process = Runtime.getRuntime().exec(cmd);
            Log.d("Main", "process " + process.toString());
            content = process.toString();
        } catch (IOException e) {
            Log.d("Main", "exception " + e.toString());
           return e.getMessage();
        }
        return content;
    }

    public static void fetchRoot(String cmd){
        try {
            Process ps = Runtime.getRuntime().exec("su"); //1、执行su切换到root权限
            Log.d("Main", "fetchRoot: " + ps.toString());
            DataOutputStream dos = new DataOutputStream(ps.getOutputStream());
            dos.writeBytes(cmd + "\n"); // 2、向进程内写入shell指令,cmd为要执行的shell命令字符串
            dos.flush();
            dos.close();
            ps.waitFor();
        } catch (IOException | InterruptedException e) {
            Log.e("TAG", "fetchRootError: "+ e.getMessage() );

        }
    }
}

这个写法,因为fetchroot里使用root权限,所以需要系统签名。

note:

这两个写法都使用了new Thread(() -> {}).start()写法,因为不这样,会触发运行崩溃。

;