web-dev-qa-db-fra.com

Comment simuler le toucher à partir du service d'arrière-plan avec sendevent ou d'une autre manière?

Est-il possible de simuler le toucher à partir de l'application (ou du service) d'arrière-plan ou d'exécuter le script sh (qui simule le toucher)?

Il est nécessaire pour tester Android système sans USB ou autre connexion au PC, c'est pourquoi je ne peux pas (ou ne sais pas) utiliser Monkey ou d'autres outils d'autotest.

Ajout d'informations: j'ai trouvé le moyen d'exécuter des commandes Shell avec root (appareils testés enracinés):

Impossible d'exécuter la commande shell sendevent via le Android (créer une simulation tactile). Écriture du fichier sur la partition système (exécuter des commandes avec les autorisations root) )

Je reçois également des événements pour simuler le toucher.

En conséquence, j'ai:

//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();
}

Je n'ai aucune exception, mais ce n'est pas un simulateur tactile.

Quelqu'un peut-il aider à résoudre ce problème?

S'il existe une autre façon de le faire avec Android ndk ou démon sur C, veuillez m'en parler.

Merci.

31
v1k

Je ne peux pas exécuter la commande "sendevent", mais j'ai trouvé un autre moyen pour moi, j'espère que ce sera utile pour quelqu'un.

Pour simuler le toucher, j'ai utilisé sendPointerSync () d'Android.app.Instrumentation, qui ne fonctionne qu'avec l'autorisation "Android.permission.INJECT_EVENTS". Pour l'utiliser, vous devez compiler votre application en tant qu'application système. Pour ce faire, vous devez suivre les étapes suivantes:

  1. Récupérer des fichiers depuis Android source:

    racine-de-l'arborescence des sources Android/out/Host // framework/signapk.jar

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

    racine-de-l'arborescence-source-Android/build/target/product/security/platform.pk8

  2. signez votre application à l'aide de l'obtention de fichiers:

    Commande " Java -jar signapk.jar platform.x509.pem platform.pk8 YourApp-unsigned.apk " YourApp-signed.apk.

  3. adb installez YourApp-signed.apk
    • Exécutez votre application
    • Utilisez "adb Shell ps" pour confirmer que votre application fonctionne en tant que système.

Code avec simulation tactile (un nouveau thread est nécessaire pour la simulation):

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));
       }
   };

Manifeste:

<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" >

Utilisation des ressources:

29
v1k

J'étais sur le point de mettre en œuvre votre solution lorsque j'en ai trouvé une plus simple - publier dans l'espoir qu'elle sera utile à quelqu'un. Étant donné que vous disposez déjà d'un appareil enraciné, vous n'avez pas besoin de vous connecter en tant qu'application système.

Pour simuler un toucher à la position (100 200), il vous suffit d'appeler contribution à partir du service en utilisant Runtime.exec comme suit:

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();
30
simmons

Vous pouvez utiliser l'entrée "glisser". En regardant le code source Input.Java vous pouvez voir les paramètres nécessaires pour faire un glissement.

Voici un Gist que j'ai fait pour simuler un glissement pour jouer au jeu smove avec des clics au lieu de glissements juste pour tester cela. Vous avez cependant besoin d'un accès superutilisateur pour utiliser cette implémentation.

3
MiichaelD