UiAutomator — Add Widget to Home Screen

我只是一个虾纸丫 提交于 2020-06-25 21:03:12

问题


I have a fair amount of experience with Google's uiautomator; however, I seem to be stumped when it comes to adding a widget to the phone's home screen. For now lets keep it simple and assume the screen the widget is being added to is empty. The thought process would be to open the app drawer > click the widgets tab > locate the widget to be added > long click and drag the widget to the home screen. It seems like widgets are not "long clickable" though. Any thoughts/suggestions/solutions will be appreciated. The code I have implemented is below.

@Override
protected void setUp() throws UiObjectNotFoundException {
    getUiDevice().pressHome();

    new UiObject(new UiSelector().className(TEXT_VIEW).description("Apps")).clickAndWaitForNewWindow();
    new UiObject(new UiSelector().className(TEXT_VIEW).text("Widgets")).click();

    UiScrollable widgets = new UiScrollable(new UiSelector().scrollable(true));
    widgets.setAsHorizontalList();
    widgets.flingToEnd(MAX_SWIPES);

    UiObject widget = widgets.getChildByText(
            new UiSelector().className(TEXT_VIEW).resourceId("com.android.launcher:id/widget_name"),
            WIDGET_NAME
    );

    // Returns true
    System.out.println("exists(): " + widget.exists());
    // Returns false...
    System.out.println("longClickable(): " + widget.isLongClickable());

    widget.longClick();

    // Also tried...
    int startX = sonosWidget.getVisibleBounds().centerX();
    int startY = sonosWidget.getVisibleBounds().centerY();
    getUiDevice().drag(startX, startY, 0, 0, 3);
}

回答1:


Using Anders idea, I managed to long press the widget and drag it to somewhere on the home but then I see my configuration activity briefly before going back to the widgets list :( (Kolin code)

@Before fun setWidgetOnHome() {
    mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
    val screenSize = Point(mDevice.displayWidth, mDevice.displayHeight)
    val screenCenter = Point(screenSize.x / 2, screenSize.y / 2)

    mDevice.pressHome()

    val launcherPackage = mDevice.launcherPackageName!!
    mDevice.wait(Until.hasObject(By.pkg(launcherPackage).depth(0)), LAUNCH_TIMEOUT)

    // attempt long press
    mDevice.swipe(arrayOf(screenCenter, screenCenter), 150)
    pauseTest(2000)

    mDevice.findObject(By.text("Widgets")).click()
    mDevice.waitForIdle()

    val y = screenSize.y / 2

    var widget = mDevice.findObject(By.text("Efficio"))
    var additionalSwipe = 1
    while (widget == null || additionalSwipe > 0) {
        mDevice.swipe(screenCenter.x, y, screenCenter.x, 0, 150)
        mDevice.waitForIdle()
        if (widget == null) {
            widget = mDevice.findObject(By.text("Efficio"))
        } else {
            additionalSwipe--
        }
    }
    val b = widget.visibleBounds
    val c = Point(b.left + 150, b.bottom + 150)
    val dest = Point(c.x + 250, c.y + 250)
    mDevice.swipe(arrayOf(c, c, dest), 150)
}

I believe something is happening but what? :-/ it's like a back was clicked




回答2:


Long click in uiautomator Android can also be performed by using :

   public boolean drag (int startX, int startY, int endX, int endY, int steps)

Performs a swipe from one coordinate to another coordinate. You can control the smoothness and speed of the swipe by specifying the number of steps. Each step execution is throttled to 5 milliseconds per step, so for a 100 steps, the swipe will take around 0.5 seconds to complete.

Parameters:

startX :: X-axis value for the starting coordinate

startY :: Y-axis value for the starting coordinate

endX :: X-axis value for the ending coordinate

endY :: Y-axis value for the ending coordinate

Steps :: is the number of steps for the swipe action.

Returns :

true if swipe is performed, false if the operation fails or the coordinates are invalid.

Since :

Android API Level 18

So give (startX,startY) = (endX,endY) . This would act equivalent to a long-click.




回答3:


Thanks to the code posted by @geob-o-matic.

I had to add some modifications in order to work:

  • with horizontal and vertical scrolling widget selectors (changed by const variable)
  • with Configuration Activity

Extra explanations inline in code, you may have to change some values in your case so get through comments.

const val TIMEOUT: Long = 5000

// WIDGET_SELECTION_AT_X: USE here true or depending 
//  if you have to scroll at the X or Y axis when 
//  navigating through widget selection screen.
const val WIDGET_SELECTION_AT_X: Boolean = true
const val WIDGET_NAME: String = "MyAppWigdetName"

@RunWith(AndroidJUnit4::class)
class WidgetAutomatorTest {

    private val mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())

    @Before
    fun setWidgetOnHome() {
        val screenSize = Point(mDevice.displayWidth, mDevice.displayHeight)
        val screenCenter = Point(screenSize.x / 2, screenSize.y / 2)
        // showWidgets: This a point on screen between the bottom icons 
        // and the widgets, its a point that has no objects on a Galaxy S5 
        // device with stock Launcher. Most probably you have to modify it in
        // your device or use an empty homescreen and just long press at 
        // the center of it.
        val showWidgets = Point(825, 1500)

        mDevice.pressHome()

        val launcherPackage = mDevice.launcherPackageName!!
        mDevice.wait(Until.hasObject(By.pkg(launcherPackage).depth(0)), TIMEOUT)

        // attempt long press
        // Here you can use the screenCenter if you don't have any widget standing/living there!
        // ie. mDevice.swipe(arrayOf(showWidgets, screenCenter), 150)
        mDevice.swipe(arrayOf(showWidgets, showWidgets), 150)

        // Navigate to the system's widget selector, localaize if needed.
        mDevice.findObject(By.text("Widgets")).click()

        var diment = screenSize.y / 2
        if (WIDGET_SELECTION_AT_X) {
            diment = screenSize.x / 2
        }

        var widget = findMyWidget(WIDGET_NAME)
        while (widget == null) {
            if (WIDGET_SELECTION_AT_X) {
                // Swipe left to right
                mDevice.swipe(diment, screenCenter.y, 0, screenCenter.y, 150)
            } else {
                // Swipe top to bottom
                mDevice.swipe(screenCenter.x, diment, screenCenter.x, 0, 150)
            }

            widget = findMyWidget(WIDGET_NAME)
        }
        // Throw the selected widget on screen
        val b = widget.visibleBounds
        val c = Point(b.left + 150, b.bottom + 150)
        val dest = Point(c.x + 250, c.y + 250)
        mDevice.swipe(arrayOf(c, c, dest), 150)
    }

    private fun findMyWidget(withName: String): UiObject2? {
        return mDevice.findObject(By.text(withName))
    }

    @Test
    fun addWidget() {
        // Press the button on the Widget Configuration Activity
        val okButton = mDevice.findObject(UiSelector()
                .text("Add widget") 
                .className("android.widget.Button"))
        okButton.click()

        // Find the just added widget
        val widget = mDevice.findObject(By.descContains(WIDGET_NAME))
        // Click outside the widget in order to added in the screen
        mDevice.click(widget.visibleBounds.left - 150, widget.visibleBounds.top - 150)

    }
}

Note. The provided example works perfect in Galaxy S5, Android 6.0.1, 1080x1920.




回答4:


you can use dragTo ( same UI object , steps )

*steps should be > 100 to make sure the click is long enough



来源:https://stackoverflow.com/questions/18191745/uiautomator-add-widget-to-home-screen

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!