• Stick hero "攻略", android 代码编写与分析(后台截屏, 后台模拟点击)


      论文写完,感觉头脑好久没被灵感刺激了,前些天室友介绍了个小游戏,我突然来了灵感可以写的简单的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/

  • 相关阅读:
    c++ 从vector扩容看noexcept应用场景
    c++11-17 模板核心知识(十一)—— 编写泛型库需要的基本技术
    动态链接的PLT与GOT
    c++11-17 模板核心知识(十)—— 区分万能引用(universal references)和右值引用
    Golang性能分析与优化
    c++11-17 模板核心知识(九)—— 理解decltype与decltype(auto)
    [LuoguP4808][CCC 2018]平衡树(数论分块+记忆化搜索)(有复杂度证明)
    [NOI2016]区间(线段树+尺取法)
    [BZOJ4316]小C的独立集(仙人掌+树形DP)
    [CTSC2002]灭鼠行动(模拟)
  • 原文地址:https://www.cnblogs.com/dreamfactory/p/4377678.html
Copyright © 2020-2023  润新知