直都是在这上面找资料,无耻的我真的不好意思不再分享了。
之前分配到的任务找资料一直也是找不到,运气好的遇到个提边角料的。但是都没有实质可以用的。发文档的也都是东贴贴别人的,西找找别人的。基本都是漫天胡扯。
好了,废话不多说。直接进入今天的主题吧。
模拟点击
模拟点击和截屏其实在应用本身中实现其实很简单。但是跨进程就相对比较麻烦了。比如,你写一个程序,自动启动微信,点微信界面里的某几个按钮。
如果你也是在找技术文档,那么你看到的什么input方法啦,模拟eventMotion方法之类的就不要去测试了,都不能跨进程。
正解是:getevent/sendevent(都需要应用于root的手机)
其实说白了,android里的各种事件,都是由/dev/input/event*管着的。管屏幕点击的event,一般是eventname中含有touch或者screen之类的event
例如我的手机(手机连在电脑上,进入命令行,获得adb的操作。命令是adb shell。如果发现不起作用,就把adb的环境变量配置一下,就是你的ndk根目录,配到path中就可以了。)。,例如我的手机,“#”代表我的手机是完全root的手机。
之后getevent -p你就会发现列出了很多设备。其中name中含有touch或者screen的应该就是管理手机触摸事件的event,不同的手机管理触摸事件的event可能不太相同。例如我的手机是event3。。其中给你还可以看到一些它给出的操作用例。
下面就来说这个怎么用吧。首先,你要给你所需要的那个event授予权限。授权的时候再cmd里你只需要用chmod 777 /dev/input/event3就可以了。但是在android程序代码里就不能这样了,你修改权限的时候是需要先获得root权限的。
具体用法:
调用下面的方法就可以了。RootCmd("chmod 777 /dev/input/event3");
- public static boolean RootCmd(String cmd){
- Process process = null;
- DataOutputStream os = null;
- try{
- process = Runtime.getRuntime().exec("su") ;
- os = new DataOutputStream(process.getOutputStream());
- os.writeBytes(cmd+ "\n");
- os.writeBytes("exit\n");
- os.flush();
- process.waitFor();
- } catch (Exception e) {
- return false;
- } finally {
- try {
- if (os != null) {
- os.close();
- }
- process.destroy();
- } catch (Exception e) {
- }
- }
- return true;
- }
授权完毕后就可以模拟点击了。
该方法是我通过分析getevent的事件得到的(之后会给出getevent的模拟过程)
- private static String deviceTouchEvent = "event1";
- private static final String TAG="Ctrl_System_Action";
- // private static boolean isTouch
- public static void setMouseClick(int x, int y) {
- try {
- Log.i("", "ActivityManager test User click");
- /**
- * sendevent /dev/input/event3 3 57 0
- * sendevent /dev/input/event3 3 48 1
- * sendevent /dev/input/event3 3 53 379
- * sendevent/dev/input/event3 3 54 483
- * sendevent /dev/input/event3 0 2 0
- * sendevent /dev/input/event3 0 0 0
- * sendevent /dev/input/event3 3 48 0
- * sendevent /dev/input/event3 0 2 0
- * sendevent /dev/input/event3 0 0 0
- */
- Log.i("", "ActivityManager test User temp click x="+x+",y="+y);
- // 获取可touch设备名称
- String eventFirst = "/dev/input/";
- String temp = "";
- // 默认触摸event为event1
- String myUserEventName = "event1";
- String tempEventName = "";
- // 获取root权限
- if (!isRoot) {
- RootCmd("chmod 777 /dev/input/event3");
- isRoot = true;
- }
- if(!isGetEventName){
- // 获取所有设备信息
- InputStream is = Runtime.getRuntime().exec("getevent -p")
- .getInputStream();
- InputStreamReader isReader = new InputStreamReader(is);
- BufferedReader bufferReader = new BufferedReader(isReader);
- // 鉴别设备
- while ((temp = bufferReader.readLine()) != null) {
- Log.i("", "ActivityManager test User getEventString temp = "
- + temp);
- // 先将 event*存下来
- if (temp.indexOf(eventFirst) >= 0) {
- if ((temp.indexOf(eventFirst) + eventFirst.length()) < temp
- .length()) {
- tempEventName = temp.substring(temp.indexOf(eventFirst)
- + eventFirst.length());
- }
- Log.i("","ActivityManager test User getEventString EventName = "
- + tempEventName);
- }
- // 判断设备是否为屏幕设备,如果是就将event保存下来
- if (temp.indexOf("name:") >= 0
- && (temp.indexOf("touch") >= 0 || temp
- .indexOf("screen") >= 0)) {
- myUserEventName = tempEventName;
- deviceTouchEvent = myUserEventName;
- Log.i("",
- "ActivityManager test User getEventString TrueEventName = "
- + tempEventName);
- break;
- }
- }
- isGetEventName = true;
- }
- Runtime.getRuntime().exec("sendevent /dev/input/"+deviceTouchEvent+" 3 57 0");
- Runtime.getRuntime().exec("sendevent /dev/input/"+deviceTouchEvent+" 3 48 1");
- Runtime.getRuntime().exec("sendevent /dev/input/"+deviceTouchEvent+" 3 53 "+x);
- Runtime.getRuntime().exec("sendevent /dev/input/"+deviceTouchEvent+" 3 54 "+y);
- Runtime.getRuntime().exec("sendevent /dev/input/"+deviceTouchEvent+" 0 2 0");
- Runtime.getRuntime().exec("sendevent /dev/input/"+deviceTouchEvent+" 0 0 0");
- Runtime.getRuntime().exec("sendevent /dev/input/"+deviceTouchEvent+" 3 48 0");
- Runtime.getRuntime().exec("sendevent /dev/input/"+deviceTouchEvent+" 0 2 0");
- Runtime.getRuntime().exec("sendevent /dev/input/"+deviceTouchEvent+" 0 0 0");
- } catch (IOException e) {
- // TODO Auto-generated catch block
- Log.i("", "ActivityManager test User click e=" + e.toString());
- e.printStackTrace();
- }
- }
上述代码中找出event的方法可以忽略,主要在Runtim.getRunTim().exec那儿。完成一次点击,需要将上述的9条adb shell命令全部执行一次。这些命令你也可以再cmd里手动输入测试。只不过手动比较慢,点击可能会变成长按。
下面就给大家讲getevent的具体用法:
在cmd里输入命令getevent,这个时候你再去点击屏幕的时候,就会把你点击的点给记录下来。
如图,我点击的是x=1b3,y=2aa的点。
看出来了吧,系统记录的是16进制的。你只需要转换一下就可以了。以第一条为例,转换完的数据是 3 57 0;
截屏;
截屏相信能够支持的也是很多,这里就介绍一个个人感觉比较好的吧。
该方法只适用于4.0以后的版本,4.0以前的版本跨进程截屏是需要JNI方法的。
直接调用我上面的RootCmd方法,输入截屏命令就可以了。
RootCmd("screencap -p "+filePath);
同模拟点击不同,模拟点击只需要获取一次root权限即可,而截屏,每次调用是都需要root的。所以直接掉封装好的RootCmd方法就可以了。
4.3貌似还有screenshot方法。这个没怎么试过。2.3的手机就别想这个方法了,截不出来的,倒是会生成一个文件,但是是一个有大小没图像的东东。目前没找到原因。