Android Shell执行点击过慢,while循环屏幕点击提速方法咨询
你遇到的每秒仅1次点击的情况,大概率是循环里用了Thread.sleep(1000)这类固定长间隔,或是在主线程里死循环导致UI阻塞,甚至每次循环都重复查找目标View。试试这些实用优化:
提前缓存View引用,避免重复查找
如果你的代码里每次循环都调用findViewById,这会极大拖慢速度。先在循环外把要点击的View实例存下来:Button targetBtn = findViewById(R.id.target_button); // 之后循环里直接用targetBtn.performClick()用ScheduledExecutorService替代Sleep/PostDelayed
别在子线程里死循环加sleep,用定时任务池来调度点击,既能灵活控制间隔,又不会阻塞线程。比如设置每50毫秒点击一次(可根据需求调整,别太频繁导致系统卡顿):ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); executor.scheduleAtFixedRate(() -> { // 回到主线程执行点击 runOnUiThread(() -> targetBtn.performClick()); }, 0, 50, TimeUnit.MILLISECONDS);这种方式比while+sleep高效得多,线程调度更合理。
用更底层的触摸事件模拟替代performClick
如果performClick()还是不够快,直接模拟MotionEvent的DOWN和UP事件,跳过View的一些内部回调开销:private void simulateClick(View view) { float x = view.getLeft() + view.getWidth() / 2; float y = view.getTop() + view.getHeight() / 2; MotionEvent downEvent = MotionEvent.obtain(System.currentTimeMillis(), System.currentTimeMillis(), MotionEvent.ACTION_DOWN, x, y, 0); view.dispatchTouchEvent(downEvent); MotionEvent upEvent = MotionEvent.obtain(System.currentTimeMillis(), System.currentTimeMillis(), MotionEvent.ACTION_UP, x, y, 0); view.dispatchTouchEvent(upEvent); downEvent.recycle(); upEvent.recycle(); }调用这个方法比
performClick()能省一点时间,适合高频点击场景。跨App点击:用AccessibilityService的dispatchGesture
要是你是给其他App做自动点击,别用常规的View点击,用无障碍服务的手势调度,这是系统级的接口,速度快很多,而且不需要获取目标App的View实例。
Shell里用input tap慢,核心原因是每次执行都会启动一个新的input进程,进程启动的开销远大于点击本身。试试这些方案:
进入input交互式模式,批量发送指令
不要每次单独调用input tap x y,而是启动一次input进程,然后连续发送多个tap命令,这样只开销一次进程启动:# 写个简单的脚本 #!/system/bin/sh exec /system/bin/input <<EOF tap 100 200 tap 100 200 tap 100 200 # 这里可以加N个tap命令 EOF或者用管道批量传:
# 比如连续点击100次 yes "tap 100 200" | head -n 100 | /system/bin/input这种方式能把点击速度提升几十倍,因为不用反复启动进程。
直接操作/dev/input/event设备(最快方案)
绕过input命令,直接给触摸输入设备节点发送事件,这是最底层的方式,速度拉满。步骤:- 先找到你的触摸设备节点,执行
getevent -l,看输出里带ABS_MT_POSITION_X/Y的设备,比如/dev/input/event2 - 用
sendevent发送按下和抬起的事件(注意参数要对应你的设备,不同设备的坐标编码可能有差异):
# 模拟按下(x=100, y=200) sendevent /dev/input/event2 3 57 10 # ABS_MT_TRACKING_ID sendevent /dev/input/event2 3 53 100 # ABS_MT_POSITION_X sendevent /dev/input/event2 3 54 200 # ABS_MT_POSITION_Y sendevent /dev/input/event2 0 0 0 # SYN_REPORT # 模拟抬起 sendevent /dev/input/event2 3 57 -1 # ABS_MT_TRACKING_ID(-1表示结束) sendevent /dev/input/event2 0 0 0 # SYN_REPORT把这些命令写到脚本里循环执行,速度能达到每秒几百次,完全碾压input命令。
- 先找到你的触摸设备节点,执行
用脚本循环减少进程开销
要是不想搞太复杂,至少把循环放到shell脚本里,不要每次从外部调用input命令。比如:#!/system/bin/sh for i in $(seq 1 100); do input tap 100 200 done虽然还是每次启动input进程,但比你在外部循环调用100次命令要快不少。
内容的提问来源于stack exchange,提问作者otto

