关闭

【Android】技术调研:用代码模拟屏幕点击、触摸事件

标签: android
14501人阅读 评论(9) 收藏 举报
分类:

在Android中,有些场景需要使用代码来模拟人的操作,比如微信自动抢红包、UI测试等都需要模拟实现点击事件(Click)、触摸事件(Touch)、键盘事件(KeyBoard)等。那么,有没有现成的方案可以实现呢?答案当然是肯定的啦,往下看。


经过调研发现,给系统模拟注入输入事件有如下几种方式:


一、使用shell命令

使用android自带的adb shell,里面自带一个input工具,使用方法如下:

adb shell #进入系统
input keyevent KEYCODE_BACK  #模拟按返回键
input keyevent KEYCODE_HOME  #模拟按Home键

还可以直接输入点击屏幕的事件,模拟点击屏幕:

input tap 100 200  #在屏幕坐标(100, 200)处点击 

详细的用法如下:

这里写图片描述


二、使用 Instrumentation

Instrumentation本身是Android用来做测试的工具,可以通过它监测系统与应用程序之间的交互。详情可以参考官方文档[Test Your App]。我们这里只关注怎么使用Instrumentation产生发送按键或者触屏事件。

它可以发送按键:

Instrumentation mInst = new Instrumentation();  
mInst.sendKeyDownUpSync(KeyEvent.KEYCODE_CAMERA);  

也可以发送触屏事件:

Instrumentation mInst = new Instrumentation();  
mInst.sendPointerSync(MotionEvent.obtain(SystemClock.uptimeMillis(),  
    SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, x, y, 0);    //x,y 即是事件的坐标
mInst.sendPointerSync(MotionEvent.obtain(SystemClock.uptimeMillis(),  
    SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, x, y, 0);

与Shell工具一样,还有类似sendStringSync()发送文本,sendTrackballEventSync()发送轨迹球事件等方法。

sendCharacterSync(int keyCode)            //用于发送指定KeyCode的按键
sendKeyDownUpSync(int key)                //用于发送指定KeyCode的按键
sendPointerSync(MotionEvent event)        //用于模拟Touch
sendStringSync(String text)               //用于发送字符串

需要注意的是,这些方法均不可以在UI主线程中执行,必须放到子线程中调用,否则就会报错。另外,使用上面的方法,需要在AndroidManifast.xml中申明如下权限:

<uses-permission android:name="android.permission.INJECT_EVENTS"/>  

Demo源码下载: https://github.com/iTimeTraveler/XYStudy


三、使用Android内部API

在Android系统中,有些内部的API提供注入事件的方法。因为是内部API,在不同版本上可能变化比较大。使用如果想在普通App中使用,可能需要通过反射机制来调用。

在Android API 16之前,WindownManager有相应的方法提供注入事件的方法,如下:

IBinder wmbinder = ServiceManager.getService("window");  
IWindowManager wm = IWindowManager.Stub.asInterface(wmbinder); //pointer  
wm.injectPointerEvent(myMotionEvent, false); //key  
wm.injectKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_A), false);  
wm.injectKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_A), false); //trackball  
wm.injectTrackballEvent(myMotionEvent, false);  

在API 15之后,引入了InputManager,把上面的哪些injectXXXEvent()方法从WindowManager中移除了。使用方法类似:

IBinder imBinder = ServiceManager.getService("input");  
IInputManager im = IInputManager.Stub.asInterface(imBinder);

//inject key event
final KeyEvent keyEvent = new KeyEvent(downTime, eventTime, action,  
    code, repeatCount, metaState, deviceId, scancode, 
    flags | KeyEvent.FLAG_FROM_SYSTEM |KeyEvent.FLAG_KEEP_TOUCH_MODE | KeyEvent.FLAG_SOFT_KEYBOARD, 
    source);
event.setSource(InputDevice.SOURCE_ANY)  
im.injectInputEvent(keyEvent, InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);

//inject pointer event
motionEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN);  
im.injectInputEvent(motionEvent, InputManager.INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH);  

从API 16开始,InputManager就成了一个公开的类了,可以通过如下方法获得InputManager实例:

InputManager im = (InputManager) getSystemService(Context.INPUT_SERVICE);  

注意,使用injectEvent()同样需要申明android:name=”android.permission.INJECT_EVENTS”权限。


四、可以考虑使用Monkey测试框架

这种方案就是希望能够模拟Android Monkey的测试方法,不过博主并没有来得及对这方面进行深入的研究,可以参考这篇文章Android Monkey源码解析



【参考资料】:
1、Android模拟产生事件
2、Android 模拟键盘鼠标事件(Socket+Instrumentation实现)
3、Android Monkey源码解析

4
0
查看评论

Android在任何地方模拟点击屏幕

要求:在Android上按像素位置进行模拟屏幕点击,无论前台程序是什么(类似于按键精灵)。解决方案:使用安卓中的linux命令行来进行模拟(可以完成目标但是不优雅)。前提知识: ADB中可以使用”adb shell tap x y”来模拟点击 Android代码中可以使用ProcessBuilder...
  • hai29785
  • hai29785
  • 2016-10-09 18:16
  • 8134

Android模拟点击屏幕,实现按键精灵点击屏幕功能

我在实现安卓模拟点击屏幕固定位置时尝试了很多方法,碰了不少壁,现在我将我实现的方法分享给大家,以及我尝试过的方法也分享给大家,让大家在开发的路上少走些弯路。 首先我尝试用安卓辅助功能AccessibilityService类实现模拟屏幕点击,但是这个类只能找到页面也控件,然后对控件进行模拟点击,不能...
  • yuanhengzhw
  • yuanhengzhw
  • 2017-04-22 14:57
  • 14222

Android通过代码模拟物理、屏幕点击事件

本文讲的是通过使用代码,可以控制手机的
  • mad1989
  • mad1989
  • 2014-07-25 11:57
  • 100148

Android模拟屏幕点击,滑动等事件

模拟事件全部是通过input命令来实现的,首先看一下input命令的使用:  usage: input ...        input text        input keyevent...
  • cfc1243570631
  • cfc1243570631
  • 2017-03-02 10:00
  • 829

Android代码模拟物理、屏幕点击事件

一、应用中模拟物理和屏幕点击事件例如,模拟对某个view的点击事件private void simulateClick(View view, float x, float y) { long downTime = SystemClock.uptimeMillis(); final M...
  • hp910315
  • hp910315
  • 2016-08-03 19:50
  • 7552

谈Android模拟点击的价值和实现

 “Action!”,欢迎收看这期大型扯淡实用类技术节目,《小明讲故事》,大家好我是小明!今天的主题是如果孙膑、诸葛亮和曾国藩是程序员,会怎么实现Android模拟自动点击。此处可以有Android手机广告,没有赞助商提供,我们继续。很难想象那三位历史大佬是程序员吧?且不说他们,我们撸清下An...
  • dj0379
  • dj0379
  • 2016-07-26 16:39
  • 2726

Android开发——Accessibility机制实现模拟点击(微信自动抢红包实现)

1.何为Accessibility机制? 许多Android使用者因为各种情况导致他们要以不同的方式与手机交互。对于那些由于视力、听力或其它身体原因导致不能方便使用Android智能手机的用户,Android提供了Accessibility功能和服务帮助这些用户更加简单地操作设备,包括文字转语音...
  • SEU_Calvin
  • SEU_Calvin
  • 2016-07-14 20:46
  • 25753

Android系统上实现类似按键精灵的效果(模拟触屏点击事件)

参考以下博客: http://blog.csdn.net/mad1989/article/details/38109689/ http://blog.csdn.net/liu_zhen_wei/article/details/12559277 http://blog.csdn.net/s...
  • u010347927
  • u010347927
  • 2017-04-19 11:22
  • 2706

Android adb 模拟滑动 按键 点击事件

模拟事件全部是通过input命令来实现的,首先看一下input命令的使用:  usage: input ...        input text        input keyevent &...
  • huiguixian
  • huiguixian
  • 2013-09-23 11:55
  • 57574

Android 模拟屏幕点击和物理按键方式

在Android 中,有些特定的功能或者在调试的时候需要模拟屏幕点击功能和物理按键等。在实现上有2种方式:首先是模拟屏幕点击的实现方式有两种:模拟屏幕点击 本进程内实现,就是只有在自己的app上面实现。 跨进程实现,就是模拟点击手机屏幕的某个坐标。 不跨进程实现方式:假如我们需要模拟点击某个按钮,这...
  • u012943767
  • u012943767
  • 2016-02-01 16:59
  • 2963
    个人资料
    • 访问:207632次
    • 积分:2964
    • 等级:
    • 排名:第14086名
    • 原创:86篇
    • 转载:13篇
    • 译文:6篇
    • 评论:59条
    我的Github
    博客专栏
    最新评论