2013-07-01 5 views
5

Ich habe das folgende Skript für die Eingabe von "33" in den Rechner, in Android, mit UiAutomator. Jedoch wird nur die erste "3" akzeptiert, die zweite wird vollständig ignoriert.Wie drücken Sie eine Taste zweimal mit Google UiAutomator?

import com.android.uiautomator.core.*; 
import com.android.uiautomator.testrunner.UiAutomatorTestCase; 

public class MyFirstUiAutomatorTest extends UiAutomatorTestCase { 
    UiObject getByDescription(String description) { 
     return new UiObject(new UiSelector().description(description)); 
    } 

    UiObject getByText(String description) { 
     return new UiObject(new UiSelector().text(description)); 
    } 

    UiObject scrollableGetByText(String text) throws UiObjectNotFoundException { 
      UiScrollable uiScrollable = new UiScrollable(new UiSelector().scrollable(true)); 
      uiScrollable.setAsHorizontalList(); 
      return uiScrollable.getChildByText(new UiSelector().className(
        android.widget.TextView.class.getName()), 
        text);  
    } 

    public void testStuff() throws UiObjectNotFoundException { 
     getUiDevice().pressHome(); 
     getByDescription("Apps").clickAndWaitForNewWindow(); 
     getByText("Apps").click(); 
     scrollableGetByText("Calculator").clickAndWaitForNewWindow(); 

     // pressing '+' and '=' effectively clears the previous input 
     getByText("+").click(); 
     getByText("=").click(); 
     getByText("3").click(); 
     // this second '3' is ignored 
     getByText("3").click(); 
    } 
} 

Ich habe versucht, für 2 Sekunden nach dem ersten Klick in einen Schlaf hinzufügen, indem Sie:

 try { 
      Thread.sleep(2000); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 

... aber das hat nichts ändern.

Ich habe auch versucht, auf einer anderen Schaltfläche klicken, zwischen den 2 ‚3 ist, das heißt:

 new UiObject(new UiSelector().text("3")).click(); 
     new UiObject(new UiSelector().className("android.widget.EditText")).click(); 
     new UiObject(new UiSelector().text("3")).click(); 

... aber das entweder nicht funktioniert hat.

Ideen?

(Anmerkung: mit Android 4.1.2, in einem AVD, läuft auf Ubuntu Linux 12.04)

bearbeiten, folgende Rami Beobachtungen habe ich versucht, die folgenden, für die die gleiche UIObject-Objekt für eine zweite Anforderung wiederzuverwenden gleiche Beschreibung:

HashMap<String,UiObject> objectByText = new HashMap<String,UiObject>(); 
UiObject getByText(String description) { 
    if(objectByText.containsKey(description)) { 
     System.out.println("" + objectByText.get(description)); 
     return objectByText.get(description); 
    } 
    System.out.println("Created new object for [" + description + "]"); 
    UiObject object = new UiObject(new UiSelector().text(description)); 
    objectByText.put(description, object); 
    System.out.println("" + object); 
    return object; 
} 

... aber es hat nicht funktioniert, obwohl es klar ist die gleiche UIObject- jedes Mal wiederverwendet, weil es sagt nur ‚Erstellt neues Objekt für [3]‘ einmal.

Dann habe ich versucht, die UiDevice.click() ‚Trick‘, um eine Funktion ‚Klick‘ wie folgt zu erstellen, wieder Beobachtungen folgende Rami:

void click(UiObject target) throws UiObjectNotFoundException { 
    Rect rect = target.getBounds(); 
    System.out.println("rect: " + rect); 
    getUiDevice().click(rect.centerX(), rect.centerY()); 
} 

Dies ist jedoch für mich funktioniert nicht : nur die erste "3" wird angezeigt, und die zweite wird ignoriert, obwohl beide Klicks eindeutig an der gleichen Stelle sind, da die Ausgabestellen rect: identisch sind. Wenn ich zweimal manuell auf "3" klicke, benutze ich meine eigene Desktop-Maus, dann erscheinen beide 3s ok.

Ich habe auch versucht, eine zwei Sekunden Thread.sleep() zwischen den Klicks, und immer noch nur eine einzige "3" erschien für mich.

Antwort

1

Ich habe das gleiche Problem, sieht aus wie seine Suche nach einem anderen UI-Element, das den gleichen Text haben. Ich versuche, die Erstellung eines Alarms zu automatisieren, aber wenn die Zeit um 16:45 Uhr ist. Uiautomator wird den rechten Button anklicken.

clickByText("4"); 
clickByText("4"); 
clickByText("5"); 
clickByText("PM"); 
clickByText("OK"); 

private void clickByText(String text) throws UiObjectNotFoundException { 
      UiObject obj = new UiObject(new UiSelector().text(text)); 
      obj.click(); 
    } 

ist hier das Protokoll für die erste "4" klicken:

07-04 16: 54: 05,259: I/QueryController (25605): Matched-Selektor: UiSelector [ TEXT = 4] < < == >> [[email protected]; boundsInParent: Rect (0, 0 - 202, 129); GrenzenInScreen: Rect (56, 508 - 258, 637); Paketname: com.android.deskclock; Klassenname: android.widget.Taste; Text: 4; contentDescription: null; überprüfbar: falsch; überprüft: falsch; fokussierbar: wahr; konzentriert: falsch; ausgewählt: falsch; anklickbar: wahr; longClickable: false; aktiviert: wahr; Passwort: falsch; scrollbar: falsch; [ACTION_FOCUS, ACTION_SELECT, ACTION_CLEAR_SELECTION, ACTION_CLICK, ACTION_ACCESSIBILITY_FOCUS, ACTION_NEXT_AT_MOVEMENT_GRANULARITY, ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY]]

Hier ist das Protokoll für die zweite "4" klicken:

07-04 16: 54: 07.798: I/QueryController (25605): Angepasster Selektor: UiSelector [TEXT = 4] < < == >> [android.view.accessibility.Access iblityNodeInfo @ 5bffd; boundsInParent: Rect (0, 0 - 66, 90); GrenzenInScreen: Rect (191, 264 - 257, 354); Paketname: com.android.deskclock; Klassenname: android.widget.TextView; Text: 4; contentDescription: null; überprüfbar: falsch; überprüft: falsch; fokussierbar: falsch; konzentriert: falsch; ausgewählt: falsch; klickbar: falsch; longClickable: false; aktiviert: wahr; Passwort: falsch; scrollbar: falsch; [ACTION_SELECT, ACTION_CLEAR_SELECTION, ACTION_ACCESSIBILITY_FOCUS, ACTION_NEXT_AT_MOVEMENT_GRANULARITY, ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY]]

Wir können, dass man sehen wird, das Recht android.widget.Button klicken und die zweite klicken Sie auf den für android.widget.TextView suchen.

2

Ich fand einen kleinen Hack, um das Problem für jetzt zu umgehen. Holen Sie die Grenzen jedes Mal, wenn Sie den Test ausführen, so dass es nicht gerätespezifisch ist und sich im laufenden Betrieb anpassen wird.

UiObject obj1 = new UiObject(new UiSelector().text("4")); 

    Rect four = obj1.getBounds(); 

    getUiDevice().click(four.centerX(), four.centerY()); 
+0

Dieses wie eine große Abhilfe klingt, aber ich habe gerade versucht es jetzt, und es für mich nicht funktioniert. Wenn ich den '3' Button zweimal manuell drücke, dann sehe ich '33', aber wenn ich UiAutomator dazu bringe, 'getUiDevice() zu benutzen, klicke()' um zweimal am gleichen Ort zu klicken, dann sehe ich immernoch einen ' 3'. Dies, sogar ich füge ein 'Thread.sleep (2000)' zwischen den zwei Klicken hinzu. –

+0

Ich habe eine Methode namens 'setUpDigit()' erstellt, in der ich mein UIObject 'UiObject zero = neues UiObject (new UiSelector(). Text (" 0 "));' setze und einen globalen Wert Rzero habe die gleiche Methode setUpDigit() 'Rzero = zero.getBounds();' Dann habe ich einen Schalter, der den globalen Wert Rzero verwenden wird und klicken Sie auf die rechte Schaltfläche 'getUiDevice(). Klicken Sie auf (Rzero.centerX(), Rzero.centerY()); 'Der schwierige Teil ist, wenn Sie setUpDigit() aufrufen. Sie müssen angerufen werden, wenn Sie den Taschenrechner oder für mich die Alarmanlage auf dem Bildschirm haben. –

4

Anstatt nur mit Text zu suchen, versuchen Sie, nach dem Text und der Klasse zu suchen. Hier ist eine Beispielmethode dafür.

Uiobject getByTextAndClass(String text, String className) { 
    return new UiObject(new UiSelector().text(text).className(className)); 
} 

Und dann, wenn Sie versuchen, mit der Nummer 3 auf sie diese Methode für die Rechner-Taste aufzurufen:

getByTextAndClass("3", android.widget.Button.class.getName()).click(); 

Sie das UiAutomatorViewer Tool verwenden können: {android-sdk}/tools/uiautomator .bat, um die Klassennamen und andere Attribute verschiedener UiObjects zu überprüfen.

Dies funktioniert auf meinen 4.2.2-Geräten, aber ich lade 4.1.2, um es auch dort zu testen.

Ich habe es auf einem 4.1.2 AVD versucht und es funktioniert auf meinem Windows-Rechner.

2

Dieses Problem scheint in die Art und Weise integriert zu sein, wie UiObject eingerichtet wird. Soweit ich das beurteilen kann, scheint sich eine Instanz von UiObject nicht auf ein bestimmtes Objekt auf dem Bildschirm zu beziehen. Es ist eher eine Instanz dessen, auf was der UiSelector bei der Definition des UiObject hingewiesen hat. Der Schlüssel hierbei ist, dass jedes Mal, wenn das Objekt aufgerufen wird, nach einem neuen Element gesucht wird, das den Anforderungen von UiSelector entspricht.

Beweis:

UiObject ok = new UiObject(new UiSelector().text("OK")); 
ok.click(); 
// clicks a button with the text ok on the page 
// Navigate to some different page with a button with the text ok 
ok.click(); 
// this ok button on a completely different page is still clicked 

Deshalb glaube ich, Rami Abhilfe könnte in der Tat durch die richtige Art und Weise es (speichern Sie die Lage des Objekts durch seine Koordinaten und klicken Sie auf den Mittelpunkt dieser Stelle) zu tun. Wichtiger Hinweis zu Ramis Problemumgehung: Speichern Sie die Koordinaten/das Rechteck einmal und verwenden Sie dann die Koordinaten/das Rechteck, wenn Sie auf das Objekt verweisen möchten. Die mehrfache Verwendung von obj.getBounds() für dasselbe Objekt scheint nicht zu funktionieren.

Auch Datensätze der Elemente, die während einer UiObject-Instanziierung bereits übergeben wurden, scheinen in der App gespeichert zu sein. Wenn Sie einen Test zweimal ausführen, der ein UiObject findet (z. B. die Schaltfläche 4 auf der Alarmseite), klicken Sie auf die gleiche Weise wie bei einem Test, der ein UiObject findet und zweimal darauf klickt. Dies bedeutet, dass Daten von Objektabfragen auf dem Gerät gespeichert werden müssen, da das Zurücksetzen des UI-Automaten keinen Unterschied macht.

0

eine UIObject- erstellen für 3-Taste und klicken Sie auf twice.below ist das Snippet

UiObject three = new UiObject(new UiSelector().text("3")); 
three.click(); 
three.click();