论文写完,感觉头脑好久没被灵感刺激了,前些天室友介绍了个小游戏,我突然来了灵感可以写的简单的android 程序实现自动运行。主要的过会为三步:
1,Android 屏幕的获取。因为安全的原因,过程比较麻烦,我目前采用的是开启用户调试模式,利用adb脚本反复循环截图。
2,图像分析。这部分代码中有体现,过程比较简单。
3,模拟Click。代码中已经体,,我采用了一种最简单的方法,代码将在下面做详细分析。
先上个图,一口气跑到183分:
分析图片的代码如下,具体过程为:先获取图像->找到纯黑色的区域->分析黑色的间隔->根据间隔计算时间. 其中根据图像获取的一行数据如右侧图,1为黑色区域,0为非黑色区域,
根据1、0便可以计算宽度了.
1 package com.hennsun.decode; 2 3 import android.graphics.Bitmap; 4 import android.util.Log; 5 public class DecodeImage { 6 7 /* 8 * -16777216 表示ARGB的纯黑色 9 * */ 10 public static byte[] getLightValue(Bitmap image){ 11 int wight = image.getWidth(); 12 int hight = image.getHeight(); 13 int loc = (int)(hight*8/9.5); 14 byte[] dataA = new byte[wight]; 15 for(int i = 0;i<wight;i++){ 16 if(image.getPixel(i, loc) == -16777216) 17 dataA[i] = 1; 18 } 19 return dataA; 20 } 21 22 23 /** 24 * 得到间隔宽度 25 * @param light 26 * @return 27 */ 28 public static int decodeGap(byte[] light){ 29 int start = 0,end1 =0,end2 = light.length ; 30 for(int i = 0;i<light.length-1;i++){ 31 if(light[i+1]<light[i]){ 32 start = i+1; 33 Log.d("Plug", "start is " + Integer.toString(start)); 34 break; 35 } 36 } 37 for(int i = start;i<light.length-1;i++){ 38 if(light[i+1]>light[i]){ 39 end1 = i; 40 Log.d("Plug", "end1 is " + Integer.toString(end1)); 41 break; 42 } 43 } 44 for(int i = end1+1 ;i<light.length-1;i++){ 45 if(light[i+1]<light[i]){ 46 end2 = i; 47 Log.d("Plug", "end2 is " + Integer.toString(end2)); 48 break; 49 } 50 } 51 if(start == end2+1) 52 return 0; 53 else 54 return (end1+end2)/2 - start; 55 } 56 57 /** 58 * 获得点击的时间 59 * @param image 游戏的界面 60 * @param index 为 像素值/ms 61 * @return 62 */ 63 public static float getTime(Bitmap image,float index){ 64 float time = 0; 65 int gap = 0; 66 byte[] gray = getLightValue(image); 67 gap = decodeGap(gray); //return pixe counts. 68 time = gap/index; //这里采用可调整系数。 69 Log.d("Plug","the width of the gap is "+Float.toString((float) (5.35*gap/720))+"cm"); 70 return time; 71 72 } 73 74 }
关于屏幕的截图,我可以使用adb方式,脚本如下。当然方式比较的多,我选择了相对比较简单的。
:abc adb shell screencap -p /sdcard/Demo/screen.bmp ping 127.0.0.1 -n 10>null goto abc
或下面这种方式都可以实现截屏,我已经验证完全没有问题,但是对就处理流程就有点不同了.
1 package com.hennsun.runtime; 2 3 import java.io.BufferedOutputStream; 4 import java.io.PrintStream; 5 6 import android.util.Log; 7 8 9 public class CaptureScreen { 10 /** 11 * http://my.oschina.net/u/2241960/blog/330485 12 * @param path 图片保存路径 13 */ 14 public static void screenshot(String path){ 15 Process process = null; 16 Log.d("Plug","start to capture screen"); 17 try{ 18 process = Runtime.getRuntime().exec("su"); 19 PrintStream outputStream = null; 20 try { 21 outputStream = new PrintStream(new BufferedOutputStream(process.getOutputStream(), 8192)); 22 outputStream.println("screencap -p " + path); 23 outputStream.flush(); 24 }catch(Exception e){ 25 e.printStackTrace(); 26 } finally { 27 if (outputStream != null) { 28 outputStream.close(); 29 } 30 } 31 process.waitFor(); 32 }catch(Exception e){ 33 e.printStackTrace(); 34 }finally { 35 if(process != null){ 36 process.destroy(); 37 } 38 } 39 } 40 }
模拟Touch,我是从下面的参考的部分获取的代码,根据时间间隔便可以操作Touch事件了,不过需要软件Root权限,代码如下:
1 /** 2 * simulate Click 3 * @param time 4 */ 5 private void simulateClick(float time){ 6 try{ 7 Process process = Runtime.getRuntime().exec("su"); 8 DataOutputStream os = new DataOutputStream(process.getOutputStream()); 9 //String cmd = "/system/bin/input tap 100 200 "; 10 //time 为 ms 11 String timeS = String.valueOf((int)time); 12 Log.d("Plug", "the necessary time is "+timeS); 13 String cmd = "/system/bin/input swipe 100 200 100 200 "+timeS+" "; 14 os.writeBytes(cmd); 15 os.writeBytes("exit "); 16 os.flush(); 17 os.close(); 18 process.waitFor(); 19 }catch(Exception e){ 20 21 } 22 }
以上代码仅做学习交流使用,本文原创,且勿转载!!
视频展示:
Youtube展示链接 https://www.youtube.com/watch?v=sF0PuKGJFUI&feature=youtu.be
这是国外另外一个团队做了,应该是印度人,他做的比较麻烦.
https://www.youtube.com/watch?v=dJW59UliLhc
需要源码的可以访问我的 个人主页 http://www.shareideas.net/
参考:
http://w3facility.org/question/how-to-simulate-touch-from-background-service-with-sendevent-or-other-way/
http://stackoverflow.com/questions/11142843/how-can-i-use-adb-to-send-a-longpress-key-event
https://grymoire.wordpress.com/2014/09/17/remote-input-shell-scripts-for-your-android-device/