天天看点

Android 模拟点击

Android 模拟点击

前言

最近提出一个需求让做模拟点击,什么意思呢?就是有一个按钮,你点击这个按钮触发的不是按钮本身,而是其他的地方。其实就是在用户不触摸手机屏幕的时候,模拟触发手机屏幕的某个地方。

不知道大家平时开发的过程用到的 adb shell命令 的地方多不多呢?

今天这个需求,我们就用adb shell命令 来完成。

真机实验

我们先用USB连接真机,在cmd命令行工具里:

adb shell
[email protected]:/ $ input tap 125 521
[email protected]:/ $ 
           

这里的意思就是点击屏幕上 (x, y) = (125, 521)的地方。果然手机响应了,缺点就是响应时间略长,感觉有1秒左右。

同理其他手势操作也可以完成,这里不作详解,感兴趣的可以自行搜索。

下面我们需要做的就是在代码里完成上述操作,并且可以持续在后台运行。这里我也是踩坑无数,听我慢慢吐槽

方式一 ProcessBuilder

直接上代码:

/**
     * 传入在屏幕中的坐标,坐标左上角为基准
     * 模拟点击
     *
     * @param x 需要点击的x坐标
     * @param y 需要点击的y坐标
     */
    public static void autoClickPos(final double x, final double y) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                // 利用ProcessBuilder执行shell命令
                String[] order = {"input", "tap", "" + x, "" + y};
                try {
                    new ProcessBuilder(order).start();
                    LogUtil.e("命令执行了");
                } catch (IOException e) {
                    e.printStackTrace();
                    LogUtil.e("命令执行了,但是出错啦");
                }
            }
        }).start();
    }

           

方式二:Instrumentation

/**
 * 传入在屏幕中的坐标,坐标左上角为基准
 * 模拟点击
 *
 * @param x 需要点击的x坐标
 * @param y 需要点击的y坐标
 */
public static void onStartClickView(final float x, final float y) {

    new Thread(new Runnable() {
        @Override
        public void run() {
            try {
                Instrumentation inst = new Instrumentation();
                inst.sendPointerSync(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, x, y, 0));
                inst.sendPointerSync(MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, x, y, 0));
                LogUtil.i("模拟点击" + x + ", " + y);
            } catch (Exception e) {
                LogUtil.e(e.toString());
            }
        }
    }).start();

}
           

注意:该方式必须跑在子线程里面,不能跑在主线程里面。