ShareIdeas

本博客不再更新,欢迎访问我的github,https://github.com/sunke-github/

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

  论文写完,感觉头脑好久没被灵感刺激了,前些天室友介绍了个小游戏,我突然来了灵感可以写的简单的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\n";  
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+"\n";
14             os.writeBytes(cmd); 
15             os.writeBytes("exit\n");
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/

posted on 2015-03-30 12:22  ShareIdeas  阅读(1775)  评论(0编辑  收藏  举报