34

是否可以从后台应用程序(或服务)模拟触摸或运行 sh 脚本(模拟触摸)?

在没有 USB 或其他连接到 PC 的情况下测试 android 系统需要它,这就是为什么我不能(或不知道如何)使用 Monkey 或其他自动测试工具。

补充信息:我找到了用 root 运行 shell 命令的方法(测试的设备 root):

无法通过 android 代码执行 sendevent shell 命令(创建触摸模拟)。 在系统分区上写入文件(以 root 权限运行命令)

我也得到了模拟触摸的事件。

结果我有:

//sendevent commands to simulate touch (verify it work from cmd)
String[] touchEvent = { "sendevent /dev/input/event0 0 0 0\n",
                        "sendevent /dev/input/event6 3 53 499\n",
                        "sendevent /dev/input/event6 3 54 680\n",
                        "sendevent /dev/input/event6 3 58 40\n",
                        "sendevent /dev/input/event6 3 48 3\n",
                        "sendevent /dev/input/event6 3 57 0\n",
                        "sendevent /dev/input/event6 0 2 0\n",
                        "sendevent /dev/input/event6 0 0 0\n",
                        "sendevent /dev/input/event6 0 2 0\n",
                        "sendevent /dev/input/event6 0 0 0\n",
                        "sendevent /dev/input/event0 3 0 2\n",
                        "sendevent /dev/input/event0 0 0 0\n"};

try{
    Thread.sleep(2000);
    Process root = Runtime.getRuntime().exec("su");
    DataOutputStream os = new DataOutputStream(root.getOutputStream());             
    for(int i = 0; i < touchEvent.length; i++){
            Log.i(TAG, touchEvent[i]);  
            os.writeBytes(touchEvent[i]);
            os.flush();
    }
    root.waitFor();
} catch (IOException e) {
    Log.e(TAG, "Runtime problems\n");
    e.printStackTrace();
} catch (SecurityException se){
    se.printStackTrace();
} catch (InterruptedException e) {
    e.printStackTrace();
}

我没有任何例外,但它不是触摸模拟。

任何人都可以帮助解决这个问题吗?

如果有另一种方法可以使用 C 上的 android ndk 或守护进程来实现,请告诉我。

谢谢。

4

3 回答 3

32

我无法执行“sendevent”命令,但为自己找到了另一种方法,希望对某人有所帮助。

对于模拟触摸,我使用了来自 android.app.Instrumentation 的 sendPointerSync(),它仅适用于“android.permission.INJECT_EVENTS”权限。为了使用它,您应该将您的应用程序编译为系统应用程序。为此,您应该按照以下步骤操作:

  1. 从android源获取文件:

    root-of-android-source-tree/out/host//framework/signapk.jar

    root-of-android-source-tree/build/target/product/security/platform.x509.pem

    root-of-android-source-tree/build/target/product/security/platform.pk8

  2. 使用获取文件签署您的应用程序:

    命令“ java -jar signapk.jar platform.x509.pem platform.pk8 YourApp-unsigned.apk ” YourApp-signed.apk。

  3. adb install YourApp-signed.apk
    • 运行你的应用
    • 使用“adb shell ps”确认您的应用程序作为系统运行。

触摸模拟代码(模拟需要新线程):

Thread thread = new Thread(){
       @Override
       public void run(){
               Instrumentation m_Instrumentation = new Instrumentation();

               m_Instrumentation.sendPointerSync(MotionEvent.obtain(
                       SystemClock.uptimeMillis(),
                       SystemClock.uptimeMillis(),
                       MotionEvent.ACTION_DOWN,posx, posy, 0));
               m_Instrumentation.sendPointerSync(MotionEvent.obtain(
                       SystemClock.uptimeMillis(),
                       SystemClock.uptimeMillis(),
                       MotionEvent.ACTION_UP,width*4/5,height, 0));
       }
   };

显现:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.yourapp"
    **android:sharedUserId="android.uid.system"**
    android:versionCode="1"
    android:versionName="1.0" >

使用资源:

于 2013-03-22T01:40:41.310 回答
29

当我发现一个更简单的解决方案时,我正要实施您的解决方案 - 希望它对某人有所帮助。由于您已经拥有 root 设备,因此您无需作为系统应用程序进行签名。

要模拟位置 (100,200) 的触摸,您只需使用Runtime.exec从服务内部调用输入,如下所示:

Process process = Runtime.getRuntime().exec("su");
DataOutputStream os = new DataOutputStream(process.getOutputStream());
String cmd = "/system/bin/input tap 100 200\n";
os.writeBytes(cmd);
os.writeBytes("exit\n");
os.flush();
os.close();
process.waitFor();
于 2014-03-11T19:31:34.910 回答
3

您可以使用“滑动”输入。查看Input.java 源代码,您可以看到进行滑动所需的参数。

这是我为模拟滑动以通过点击而不是滑动来玩 smove 游戏而制作的一个要点,只是为了测试这一点。您需要超级用户访问权限才能使用此实现。

于 2015-07-25T07:05:31.650 回答