天天看點

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();

}
           

注意:該方式必須跑在子線程裡面,不能跑在主線程裡面。