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