美文网首页Android Tech安卓开发安卓资源收集
Android跨程序模拟用户操作方法(史上最全)

Android跨程序模拟用户操作方法(史上最全)

作者: 呼儿海雅 | 来源:发表于2017-06-08 21:28 被阅读444次

    对于安卓系统来说,模拟用户操作是一件很危险的事情,因此到目前我所使用过的系统(Android 7以下)均没有开放模拟触控权限。本文总结了目前已知可行的跨进程触控操作方法,基本都需要Root权限或系统签名。

    一、Instrumentation框架

    | 项目 | 描述 |
    | -------|: ------:|
    | 权限要求 | 同进程下无要求 |
    | 权限要求 | 跨进程下需要系统签名 |
    | 可用操作 | 点击、滑动、拖拽、多点触控、按键操作 |
    | 上手难度 | 简单 |

    Instrumentation框架主要是用来控制和测试应用程序的,一般用在写单元测试的时候,可模拟用户所有操作。

    代码如下:

    Instrumentation inst = new Instrumentation();
    inst.sendPointerSync(event);//发送鼠标操作
    inst.sendKeyDownUpSync(keyCode);//发送按键操作```
    
    例子:模拟鼠标滑动
    

    //模拟按下
    MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_DOWN, positionX, positionY, 0);
    //模拟移动
    MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_MOVE, positionX, positionY, 0);
    //模拟抬起
    MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis(), MotionEvent.ACTION_UP, positionX, positionY, 0);

    >    常见触摸操作
    >    public static final int ACTION_DOWN  = 0;    单点触摸动作
    >    public static final int ACTION_UP                     = 1;    单点触摸离开动作
    >    public static final int ACTION_MOVE               = 2;触摸点移动动作
    >    public static final int ACTION_CANCEL           = 3;触摸动作取消
    >    public static final int ACTION_OUTSIDE          = 4;触摸动作超出边界
    >    public static final int ACTION_POINTER_DOWN     = 5;多点触摸动作
    >    public static final int ACTION_POINTER_UP       = 6;多点离开动作
    
    PS:在同进程下,可以使用 *view.onTouchEvent(motionEvent);* 来对控件输入模拟操作
    
    ###系统权限获取方法
    在AndroidManifest.xml文件中增加系统权限 android:sharedUserId="android.uid.system",并对生成的apk包,进行系统签名
    
    ![Paste_Image.png](http:https://img.haomeiwen.com/i6338331/fbc3100a6193c30f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
    系统签名有两种方法
    ####方法一:使用签名文件签名方法
    Android的签名文件存放于系统源码的 build/target/product/security/目录下
        ![](https://img.haomeiwen.com/i6338331/378f87f773ef75ab?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)    该目录下有 media.pk8、media.x509.pem、platform.pk8、platform.x509.pem、shared.pk8、shared.x509.pem、testkey.pk8、testkey.x509.pem等签名文件,不同的签名文件,对应不同的权限。Android默认的签名文件为testkey.pk8、testkey.x509.pem。
    将对应权限的签名文件platform.pk8、platform.x509.pem, 签名工具 signapk.jar, 以及需要签名的apk(假设 old.apk) 放到同一目录下,打开linux终端(windows cmd也可以),进入该目录,进行重新签名:
        java -jar signapk.jar platform.x509.pem platform.pk8 old.apk new.apk
    得到的new.apk就是带系统签名的安装包了。
    
    ![Paste_Image.png](https://img.haomeiwen.com/i6338331/81ea153d2266673b.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
    ####方法二:在系统源码环境下用make来编译(需Linux环境)
    ** 1.修改Android.mk文件**
     Android.mk文件时在Linux下用交叉编译连编译的时候才用到的,eclipse中不会自动生成。我们在Android.mk文件中添加LOCAL_CERTIFICATE := platform这一行。例如:
    >LOCAL_PATH:= $(call my-dir)  
    include $(CLEAR_VARS)  
    LOCAL_SRC_FILES := $(call all-java-files-under, src)  
    LOCAL_PACKAGE_NAME := Settings  
    LOCAL_CERTIFICATE := platform  
    LOCAL_PROGUARD_FLAG_FILES := proguard.flags  
    
     ** 2.把项目放到源码下,用mm命令编译**
    
    
    ***
    #二、ADB命令 input
    | 项目 | 描述 |
    | -------|: ------:|
    | 权限要求 | 需要Root权限|
    | 可用操作 | 点击、直线滑动、拖拽、按键操作、英文输入 |
    | 上手难度 | 简单 |
    *用adb的input命令来模拟简单的输入,用法比较受限*
    
    >usage: input ...
    input text //输入文字(中文不支持)
    input keyevent //keyevent按键
    input [touchscreen|touchpad|touchnavigation] tap <x> <y>//点击屏幕
    input [touchscreen|touchpad|touchnavigation] swipe <x1> <y1> <x2> <y2> //屏幕滑动 
    input rotationevent 0 1->90 2->180 3->270> //顺时针旋转
    
    
    代码如下:
    

    //su命令函数
    public class UtilShell{
    private static DataOutputStream os = null;
    public static final boolean exe(String cmd){
    try {
    if (os == null) {
    Process process = Runtime.getRuntime().exec("su");
    os = new DataOutputStream(process.getOutputStream());
    }
    os.writeBytes(cmd + "\n");
    os.flush();
    return true;
    }catch (IOException ex) {
    Log.w("ROOT", "Can't get root access", ex);
    } catch (SecurityException ex) {
    Log.w("ROOT", "Can't get root access", ex);
    } catch (Exception ex) {
    Log.w("ROOT", "Error executing internal operation", ex);
    }
    return false;
    }
    }

    //模拟点击坐标(222,333)代码
    UtilShell.exe("input touchscreen tap "+222+" "+333);

    >附按键表
    KeyCode             Keyevent Value
    KEYCODE_MENU 1
    KEYCODE_SOFT_RIGHT 2
    KEYCODE_HOME 3
    KEYCODE_BACK 4
    KEYCODE_CALL 5
    KEYCODE_ENDCALL 6
    KEYCODE_0 7
    KEYCODE_1 8
    KEYCODE_2 9
    KEYCODE_3 10
    KEYCODE_4 11
    KEYCODE_5 12
    KEYCODE_6 13
    KEYCODE_7 14
    KEYCODE_8 15
    KEYCODE_9 16
    KEYCODE_STAR 17
    KEYCODE_POUND 18
    KEYCODE_DPAD_UP 19
    KEYCODE_DPAD_DOWN 20
    KEYCODE_DPAD_LEFT 21
    KEYCODE_DPAD_RIGHT 22
    KEYCODE_DPAD_CENTER 23
    KEYCODE_VOLUME_UP 24
    KEYCODE_VOLUME_DOWN 25
    KEYCODE_POWER 26
    KEYCODE_CAMERA 27
    KEYCODE_CLEAR 28
    KEYCODE_A 29
    KEYCODE_B 30
    KEYCODE_C 31
    KEYCODE_D 32
    KEYCODE_E 33
    KEYCODE_F 34
    KEYCODE_G 35
    KEYCODE_H 36
    KEYCODE_I 37
    KEYCODE_J 38
    KEYCODE_K 39
    KEYCODE_L 40
    KEYCODE_M 41
    KEYCODE_N 42
    KEYCODE_O 43
    KEYCODE_P 44
    KEYCODE_Q 45
    KEYCODE_R 46
    KEYCODE_S 47
    KEYCODE_T 48
    KEYCODE_U 49
    KEYCODE_V 50
    KEYCODE_W 51
    KEYCODE_X 52
    KEYCODE_Y 53
    KEYCODE_Z 54
    KEYCODE_COMMA 55
    KEYCODE_PERIOD 56
    KEYCODE_ALT_LEFT 57
    KEYCODE_ALT_RIGHT 58
    KEYCODE_SHIFT_LEFT 59
    KEYCODE_SHIFT_RIGHT 60
    KEYCODE_TAB 61
    KEYCODE_SPACE 62
    KEYCODE_SYM 63
    KEYCODE_EXPLORER 64
    KEYCODE_ENVELOPE 65
    KEYCODE_ENTER 66
    KEYCODE_DEL 67
    KEYCODE_GRAVE 68
    KEYCODE_MINUS 69
    KEYCODE_EQUALS 70
    KEYCODE_LEFT_BRACKET 71
    KEYCODE_RIGHT_BRACKET 72
    KEYCODE_BACKSLASH 73
    KEYCODE_SEMICOLON 74
    KEYCODE_APOSTROPHE 75
    KEYCODE_SLASH 76
    KEYCODE_AT 77
    KEYCODE_NUM 78
    KEYCODE_HEADSETHOOK 79
    KEYCODE_FOCUS 80
    KEYCODE_PLUS 81
    KEYCODE_MENU 82
    KEYCODE_NOTIFICATION 83
    KEYCODE_SEARCH 84
    TAG_LAST_KEYCODE 85
    
    ***
    #三、Shell命令 sendevent
    | 项目 | 描述 |
    | -------|: ------:|
    | 权限要求 | 需要Root权限|
    | 可用操作 | 点击、滑动、拖拽 |
    | 上手难度 | 较难 |
    
    *getevent&sendevent 是Android系统下的一个工具,可以模拟多种按键和触屏操作,产生的是raw event,raw event经过event hub处理产生最终的gesture事件,sendevent用于发送input事件,源码位于Android SDK的system/core/toolbox下(sendevent.c getevent.c)。*
    
    ###用法
    ####1. 使用所有getevent命令,输出所有event设备的基本信息
    **注意:这里的数字都是16进制。**
    >Usage: getevent [-t] [-n] [-s switchmask] [-S] [-v [mask]] [-d] [-p] [-i] [-l] [-q] [-c count] [-r] [device]  
        -t: show time stamps  
        -n: don't print newlines  
        -s: print switch states for given bits  
        -S: print all switch states  
        -v: verbosity mask (errs=1, dev=2, name=4, info=8, vers=16, pos. events=32, props=64)  
        -d: show HID descriptor, if available  
        -p: show possible events (errs, dev, name, pos. events)  
        -i: show all device info and possible events  
        -l: label event types and names in plain text  //将type、code、value以对应的常量名称显示
        -q: quiet (clear verbosity mask)  
        -c: print given number of events then exit   //输出x条信息后退出
        -r: print rate events are received  
    
    ![Paste_Image.png](https://img.haomeiwen.com/i6338331/9735a4341d0cb192.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    
    
    ####2. 使用sendevent命令模拟操作
    **注意:这里的数字都是10进制。**
    >命令用法 sendevent [device] [type] [code] [value]
    *具体定义可从kernel/include/linux/input.h中获得
    提供个链接 http://elixir.free-electrons.com/linux/latest/source/include/uapi/linux/input.h*
    
    >情况1:在某坐标点上点击一次(x坐标为40,y坐标为210)
    adb shell sendevent /dev/input/event0 3 0 40    //鼠标移到x坐标40
    adb shell sendevent /dev/input/event0 3 1 210  //鼠标移到y坐标210
    adb shell sendevent /dev/input/event0 1 330 1 //鼠标按下
    adb shell sendevent /dev/input/event0 0 0 0 //同步(不可缺少)
    adb shell sendevent /dev/input/event0 1 330 0 //鼠标抬起
    adb shell sendevent /dev/input/event0 0 0 0 //同步(不可缺少)
    
    >情况2:模拟滑动轨迹(开始于[100,200],止于[108,300])
    adb shell sendevent /dev/input/event0 3 0 100 //鼠标移到x坐标100
    adb shell sendevent /dev/input/event0 3 1 200 //鼠标移到y坐标200
       
    adb shell sendevent /dev/input/event0 1 330 1 //鼠标按下
    adb shell sendevent /dev/input/event0 0 0 0    //同步
       
    adb shell sendevent /dev/input/event0 3 0 101 //鼠标移到x坐标101
    adb shell sendevent /dev/input/event0 0 0 0    //同步
    ……………………     //需一点一点移动,这里省略
    adb shell sendevent /dev/input/event0 3 0 108 //鼠标移到x坐标108
    adb shell sendevent /dev/input/event0 0 0 0   //同步
       
    adb shell sendevent /dev/input/event0 1 330 0 //鼠标抬起
    adb shell sendevent /dev/input/event0 0 0 0   //同步
    
    代码如下:
    

    //模拟操作与input命令相似
    UtilShell.exe("sendevent /dev/input/event0 0 0 0");

    *此方法基本能满足模拟操作的所有要求,据说有一款叫aPaint的软件对此方法开发有极大帮助*
    ***
    #四、新增虚拟USB鼠标设备
    | 项目 | 描述 |
    | -------|: ------:|
    | 权限要求 | 需要修改系统文件|
    | 可用操作 | 所有鼠标操作 |
    | 上手难度 | 极难 |
    暂无思路,仅供参考!

    相关文章

      网友评论

        本文标题:Android跨程序模拟用户操作方法(史上最全)

        本文链接:https://www.haomeiwen.com/subject/usenfxtx.html