Java 如何使用Google UiAutomator按两次按钮?

Java 如何使用Google UiAutomator按两次按钮?,java,android,automated-tests,avd,android-uiautomator,Java,Android,Automated Tests,Avd,Android Uiautomator,我有下面的脚本,用于在Android中使用UiAutomator在计算器中键入'33'。然而,只有第一个“3”被接受,第二个新闻被完全忽略 import com.android.uiautomator.core.*; import com.android.uiautomator.testrunner.UiAutomatorTestCase; public class MyFirstUiAutomatorTest extends UiAutomatorTestCase { UiObjec

我有下面的脚本,用于在Android中使用UiAutomator在计算器中键入'33'。然而,只有第一个“3”被接受,第二个新闻被完全忽略

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();
    }
}
我尝试在第一次单击后添加睡眠2秒钟,方法是:

        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
。。。但这并没有改变任何事情

我还试着在2'3之间点击另一个按钮,即:

        new UiObject(new UiSelector().text("3")).click();
        new UiObject(new UiSelector().className("android.widget.EditText")).click();
        new UiObject(new UiSelector().text("3")).click();
。。。但这也不起作用

想法

(注意:在AVD中使用Android 4.1.2;在Ubuntu linux 12.04上运行)

编辑,根据Rami的观察,我尝试了以下方法,以重复使用相同的UiObject对象进行相同描述的第二次请求:

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;
}
然而,这对我来说也不起作用:只有第一个“3”出现,而第二个被忽略,即使两次单击明显位于同一位置,因为
rect:
输出位置是相同的。如果我使用自己的桌面鼠标手动单击“3”两次,则两个3都显示正常


我还尝试在两次单击之间添加一个两秒钟的
Thread.sleep()
,但仍然只有一个'3'出现在我面前。

我也有同样的问题,看起来它在寻找另一个具有相同文本的UI元素。我试图自动创建一个警报,但当时间为例如下午4:45时。Uiautomator将单击右键

 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();
    }
这是第一次“4”点击的日志:

07-04 16:54:05.259:I/QueryController(25605):匹配的选择器: UiSelector[TEXT=4][android.view.accessibility。AccessibilityNodeInfo@592f1; boundsInParent:Rect(0,0-202129);boundsInScreen:Rect(56508-258637);packageName:com.android.deskclock;className:android.widget.Button;文本:4;内容描述:null;可检查:false;已检查:false;可聚焦:true; 所选:false;可点击:true;可点击:false;已启用:true; 密码:false;可滚动:false;[ACTION\u FOCUS,ACTION\u SELECT, 操作\u清除\u选择、操作\u单击、操作\u可访问性\u焦点、, 行动(下一步)行动(下一步)(下一步)(下一步)(下一步)(下一步), 动作(上一次)(移动)(粒度)]]

这是第二次“4”点击的日志:

07-04 16:54:07.798:I/QueryController(25605):匹配的选择器: UiSelector[TEXT=4][android.view.accessibility。AccessibilityNodeInfo@5bffd; boundsInParent:Rect(0,0-66,90);boundsInScreen:Rect(191264-257354);packageName:com.android.deskclock;类名: android.widget.TextView;文本:4;内容描述:null;可检查:false;已检查:false;可聚焦:false;聚焦:false; 所选:false;可点击:false;可点击:false;已启用: true;密码:false;可滚动:false;[ACTION\u SELECT, 行动\u清除\u选择,行动\u可访问性\u焦点, 行动(下一步)在行动(下一步)粒度, 动作(上一次)(移动)(粒度)]]


我们可以看到,其中一个正在单击正确的android.widget.Button,第二个单击它查找android.widget.TextView。

我发现了一个解决问题的小技巧。每次运行测试时都要获得边界,这样它就不会以设备为中心,并且可以动态适应

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

  Rect four = obj1.getBounds();

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

尝试按文本和类进行搜索,而不仅仅是按文本进行搜索。 下面是一个这样做的示例方法

Uiobject getByTextAndClass(String text, String className) {
    return new UiObject(new UiSelector().text(text).className(className));
}
然后,如果您正试图调用此方法来使用计算器按钮上的数字3:

getByTextAndClass("3", android.widget.Button.class.getName()).click();
您可以使用UiAutomatorViewer工具:{android sdk}/tools/uiautomator.bat检查不同UIObject的类名和其他属性

这在我的4.2.2设备上运行,但我正在下载4.1.2在那里测试它


我在4.1.2 AVD上试用过,它在我的Windows机器上运行。

这个问题似乎是在UiObject的设置方式中内置的。据我所知,UiObject的一个实例似乎并不指向屏幕上的特定对象。它更像是定义UiObject时UiSelector指向的对象的实例。这里的关键是,每次调用对象时,它都会搜索符合UiSelector要求的新项

证据:

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
因此,我认为Rami的解决方法实际上可能是正确的(通过坐标存储对象的位置并单击该位置的中心)。关于Rami的解决方案,需要注意的重要一点是,保存坐标/矩形一次,然后在需要引用对象时重用坐标/矩形。在同一对象上多次使用obj.getBounds()似乎不起作用


此外,在UiObject实例化期间已经传递的项目的记录似乎存储在应用程序中。运行两次测试以查找UiObject(例如,设置报警页面中的按钮4)并单击它失败的方式与查找UiObject并单击它两次的测试失败的方式相同。这意味着对象查询的数据必须存储在设备上,因为重置UIautomator没有任何区别。

为3按钮创建UiObject并单击两次。下面是代码段

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

这听起来是一个很好的解决办法,但我刚刚尝试过,但它对我不起作用。如果我手动单击“3”按钮两次,则会看到“33”,但如果我让UiAutomator使用
getUiDevice()。单击()
在同一位置单击两次,则仍然会看到单个“3”。这一点,我甚至在两次点击之间添加了一个
Thread.sleep(2000)
。我创建了一个名为
setUpDigit()
的方法,在这里我设置了我的UIobject
UIobject zero=new UIobject(new UiSelector().text(“0”)和我有一个全局值Rzero,它是在相同的方法setUpDigit()中设置的然后我有一个使用全局值Rzero的开关,并单击右按钮
getUiDevice()。单击(Rzero.centerX(),Rzero.centerY())棘手的部分是何时调用setUpDigit()。信息技术
UiObject three = new UiObject(new UiSelector().text("3"));
three.click();
three.click();