一直都是在这上面找资料,无耻的我真的不好意思不再分享了。
之前分配到的任务找资料一直也是找不到,运气好的遇到个提边角料的。但是都没有实质可以用的。发文档的也都是东贴贴别人的,西找找别人的。基本都是漫天胡扯。
好了,废话不多说。直接进入今天的主题吧。
模拟点击
模拟点击和截屏其实在应用本身中实现其实很简单。但是跨进程就相对比较麻烦了。比如,你写一个程序,自动启动微信,点微信界面里的某几个按钮。
如果你也是在找技术文档,那么你看到的什么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的手机就别想这个方法了,截不出来的,倒是会生成一个文件,但是是一个有大小没图像的东东。目前没找到原因。