问题
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