2013-02-18 10 views
27

Czy można symulować dotyk z aplikacji w tle (lub usługi) lub uruchomić skrypt sh (symulujący dotyk)?Jak symulować dotyk z usługi w tle za pomocą sendevent lub w inny sposób?

Jest to potrzebne do testowania systemu Android bez USB lub innego połączenia z komputerem, dlatego nie mogę (lub nie wiem jak) korzystać z Monkey lub innych narzędzi autotestu.

Dodany info: znalazłem drogę do wykonywania poleceń powłoki z korzeni (przetestowanych urządzeń zakorzenione):

Unable to execute sendevent shell command through the android code (tworzenie symulacji dotykowego). Writing file on system partition (uruchom komendy z uprawnieniami root'a)

Dostaję także zdarzenia symulujące dotyk.

W rezultacie mam:

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

nie mam żadnych wyjątków, ale nie dotykać symuluje.

Czy ktoś może pomóc rozwiązać ten problem?

Jeśli jest inny sposób na zrobienie tego z Androidem ndk lub demonem na C, proszę, powiedz mi o tym.

Dzięki.

+0

Jeśli w tej samej sieci lokalnej można używać małp, funkcja adb będzie działać również bezprzewodowo. – L7ColWinters

+0

Dzięki za odpowiedź. Wiem o tym, ale nie powinno być żadnego połączenia (WiFi i BT powinny być wyłączone). – v1k

+0

Witam, jak w końcu to osiągnąć? Podążyłem za wszystkimi twoimi krokami, ale żadnych dobrych wiadomości, przejrzyj moje pytanie, które opublikowałem [tutaj] (http://stackoverflow.com/questions/42745005/android-self-signed-apk) –

Odpowiedz

28

Nie mogę wykonać polecenia "sendevent", ale znalazłem inną drogę dla siebie, mam nadzieję, że będzie pomocne dla kogoś.

Do symulacji dotyku użyłem sendPointerSync() z android.app.Instrumentation, który działa tylko z uprawnieniami "android.permission.INJECT_EVENTS". Do użytku powinieneś skompilować swoją aplikację jako aplikację systemową. Aby to zrobić należy wykonać następujące kroki:

  1. Pobieranie plików z Android źródło:

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

    root-of-android-source-drzewa/build/target/product/bezpieczeństwo/platform.x509.pem

    root-of-android-source-drzewa/budować/target/product/security/platform.pk8

  2. podpisać aplikację za pomocą pobierania plików:

    Command "java -jar signapk.jar platform.x509.pem platform.pk8 YourApp-unsigned.apk "YourApp-signed.apk.

  3. adb zainstalować YourApp-signed.apk
    • uruchomić aplikację
    • użyć "adb shell PS", aby potwierdzić, że aplikacja działa jako system.

Kod z dotykowym symulowanie (nowy wątek jest niezbędne do symulacji):

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

manifeście:

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

Korzystanie z zasobów:

+1

Cześć, czy to działa z tła usługa? – Dania

+0

Cześć, tak, powinno. Ale nie zapomnij o tworzeniu wątku. – v1k

+0

Świetnie, dzięki. Czy możesz mi powiedzieć, jaka była wersja Androida, na której testowałeś kod? Instrumentacja działa dobrze w wersjach sprzed Lollipop. Uważam, że Lollipop potrzebuje dodatkowej pracy, aby oprzyrządowanie działało, czy napotkasz ten problem? Czy znasz jakieś możliwe rozwiązanie? – Dania

24

miałem do wdrożenia rozwiązania, kiedy znalazłem łatwiejszy jedno - Delegowanie w nadzieję, że będzie pomocny dla kogoś. Ponieważ masz już zrootowane urządzenie, nie musisz logować się jako aplikacja systemowa.

Aby symulować dotyk w pozycji (100,200), wszystko co jest potrzebne, aby wywołać wejście z poziomu usługi, używając Runtime.exec następująco:

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(); 
+1

To znacznie czystsze rozwiązanie. Niestety nie ma zdarzeń takich jak touch_down, touch_up czy move_to, które są mi bardzo potrzebne. :( –

+0

Dzięki, działało na domyślnej pamięci ROM mojej galaxy s4 5.0.1, ale działa rzadko na niektórych urządzeniach, takich jak Galaxy S6 6.0.1 rooted.To jest tak zmęczone! Dlaczego? –

3

Można użyć „swipe” wkład. Patrząc na Input.java source code można zobaczyć potrzebne parametry, aby wykonać przesunięcie.

Oto gist I made for simulating a swipe do odtwarzania za pomocą kliknięć zamiast przeciągnięć, aby to przetestować. Do korzystania z tej implementacji potrzebny jest jednak dostęp superużytkownika.

+6

Czy możesz wprowadzić edycję, aby dołączyć przykładowy fragment kodu demonstrujący to rozwiązanie jest na granicy bycia "tylko link" odpowiedź: – bardzusny

+0

kod źródłowy jest rzeczywiście dość oczywiste i samo-wyjaśniające. do machnięcia: 'com.android.commands.input.Input.main (new String [] { "touchscreen", "swipe", "", "", "", "" [, ""]}) '(" ekran dotykowy "jest opcjonalny w pewnym sensie, ale lepiej prezentowany. zapytaj, czy kod naprawdę działa? i czy potrzebuję jakiejkolwiek deklaracji o pozwoleniu w AndroidManifest.xml lub potrzebuję uprawnień roota? – Valen

+0

^odwołaj się do powyższego: użyj '' blah blah ".split (" ")' dla lepszego wizualnego wyrazić jon – Valen

Powiązane problemy