UiObject.java revision 46d9444c7a39dc1c9fc60a5dcf4e79749d9b3859
1e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu/* 2e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Copyright (C) 2012 The Android Open Source Project 3e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * 4e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Licensed under the Apache License, Version 2.0 (the "License"); 5e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * you may not use this file except in compliance with the License. 6e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * You may obtain a copy of the License at 7e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * 8e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * http://www.apache.org/licenses/LICENSE-2.0 9e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * 10e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Unless required by applicable law or agreed to in writing, software 11e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * distributed under the License is distributed on an "AS IS" BASIS, 12e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * See the License for the specific language governing permissions and 14e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * limitations under the License. 15e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 16e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 17e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhupackage com.android.uiautomator.core; 18e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 19e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport android.graphics.Rect; 20e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport android.os.SystemClock; 21e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport android.util.Log; 22e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport android.view.KeyEvent; 23e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhuimport android.view.accessibility.AccessibilityNodeInfo; 24e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 25e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu/** 2646d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * A UiObject is a representation of a UI element. It is not in any way directly bound to a 2746d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * UI element as an object reference. A UiObject holds information to help it 2846d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * locate a matching UI element at runtime based on the {@link UiSelector} properties specified in 2946d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * its constructor. Since a UiObject is a representative for a UI element, it can 3046d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * be reused for different views with matching UI elements. 31e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 32e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhupublic class UiObject { 33e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu private static final String LOG_TAG = UiObject.class.getSimpleName(); 34e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu protected static final long WAIT_FOR_SELECTOR_TIMEOUT = 10 * 1000; 35e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu protected static final long WAIT_FOR_SELECTOR_POLL = 1000; 36e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // set a default timeout to 5.5s, since ANR threshold is 5s 37e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu protected static final long WAIT_FOR_WINDOW_TMEOUT = 5500; 38e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu protected static final int SWIPE_MARGIN_LIMIT = 5; 39e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 407f38ef08d07295967b905a61b2356ff6cdf31159Adam Momtaz private final UiSelector mSelector; 41ddc1008f06fd2a875037026490ce1f848a442572Guang Zhu private final UiAutomatorBridge mUiAutomationBridge; 42e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 43e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 443d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Constructs a UiObject to represent a specific UI element matched by the specified 453d50587be8ff021369c90554d814839335b445b0Adam Momtaz * {@link UiSelector} selector properties. 463d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 47e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param selector 48e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 494ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz public UiObject(UiSelector selector) { 50e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu mUiAutomationBridge = UiDevice.getInstance().getAutomatorBridge(); 51e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu mSelector = selector; 52e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 53e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 54e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 553d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Debugging helper. A test can dump the properties of a selector as a string 563d50587be8ff021369c90554d814839335b445b0Adam Momtaz * to its logs if needed. <code>getSelector().toString();</code> 573d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 584ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz * @return {@link UiSelector} 59e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 604ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz public final UiSelector getSelector() { 614ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz return new UiSelector(mSelector); 62e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 63e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 64e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 653d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Retrieves the {@link QueryController} to translate a {@link UiSelector} selector 663d50587be8ff021369c90554d814839335b445b0Adam Momtaz * into an {@link AccessibilityNodeInfo}. 673d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 68e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return {@link QueryController} 69e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 70ddc1008f06fd2a875037026490ce1f848a442572Guang Zhu QueryController getQueryController() { 71e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return mUiAutomationBridge.getQueryController(); 72e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 73e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 74e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 753d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Retrieves the {@link InteractionController} to perform finger actions such as tapping, 763d50587be8ff021369c90554d814839335b445b0Adam Momtaz * swiping or entering text. 773d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 78e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return {@link InteractionController} 79e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 80ddc1008f06fd2a875037026490ce1f848a442572Guang Zhu InteractionController getInteractionController() { 81e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return mUiAutomationBridge.getInteractionController(); 82e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 83e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 84e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 853d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Creates a new UiObject representing a child UI element of the element currently represented 863d50587be8ff021369c90554d814839335b445b0Adam Momtaz * by this UiObject. 873d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 883d50587be8ff021369c90554d814839335b445b0Adam Momtaz * @param selector for UI element to match 893d50587be8ff021369c90554d814839335b445b0Adam Momtaz * @return a new UiObject representing the matched UI element 90e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 914ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz public UiObject getChild(UiSelector selector) throws UiObjectNotFoundException { 924ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz return new UiObject(getSelector().childSelector(selector)); 93e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 94e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 95e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 963d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Creates a new UiObject representing a child UI element from the parent element currently 973d50587be8ff021369c90554d814839335b445b0Adam Momtaz * represented by this object. Essentially this is starting the search from the parent 983d50587be8ff021369c90554d814839335b445b0Adam Momtaz * element and can also be used to find sibling UI elements to the one currently represented 993d50587be8ff021369c90554d814839335b445b0Adam Momtaz * by this UiObject. 1003d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 1013d50587be8ff021369c90554d814839335b445b0Adam Momtaz * @param selector for the UI element to match 1023d50587be8ff021369c90554d814839335b445b0Adam Momtaz * @return a new UiObject representing the matched UI element 103e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 104e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 1054ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz public UiObject getFromParent(UiSelector selector) throws UiObjectNotFoundException { 1064ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz return new UiObject(getSelector().fromParent(selector)); 107e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 108e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 109e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 1103d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Counts the child UI elements immediately under the UI element currently represented by 111e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * this UiObject. 1123d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 113e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return the count of child UI elements. 114e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 115e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 116e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public int getChildCount() throws UiObjectNotFoundException { 117e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT); 118e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 119e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 120e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 121e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return node.getChildCount(); 122e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 123e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 124e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 1253d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Uses the member UiSelector properties to find a matching UI element reported in 1263d50587be8ff021369c90554d814839335b445b0Adam Momtaz * the accessibility hierarchy. 1273d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 1284ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz * @param selector {@link UiSelector} 129e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param timeout in milliseconds 130e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return AccessibilityNodeInfo if found else null 131e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 132e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu protected AccessibilityNodeInfo findAccessibilityNodeInfo(long timeout) { 133e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu AccessibilityNodeInfo node = null; 134e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(UiDevice.getInstance().isInWatcherContext()) { 135e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // we will NOT run watchers or do any sort of polling if the 136e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // reason we're here is because of a watcher is executing. Watchers 137e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // will not have other watchers run for them so they should not block 138e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // while they poll for items to become present. We disable polling for them. 139e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu node = getQueryController().findAccessibilityNodeInfo(getSelector()); 140e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } else { 141e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu long startMills = SystemClock.uptimeMillis(); 142e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu long currentMills = 0; 143e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu while (currentMills <= timeout) { 144e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu node = getQueryController().findAccessibilityNodeInfo(getSelector()); 145e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if (node != null) { 146e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu break; 147e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } else { 148e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu UiDevice.getInstance().runWatchers(); 149e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 150e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu currentMills = SystemClock.uptimeMillis() - startMills; 151e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(timeout > 0) { 152e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu SystemClock.sleep(WAIT_FOR_SELECTOR_POLL); 153e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 154e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 155e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 156e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return node; 157e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 158e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 159e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 1603d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Perform the action on the UI element that is represented by this UiObject. Also see 161e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * {@link #scrollToBeginning(int)}, {@link #scrollToEnd(int)}, {@link #scrollBackward()}, 1623d50587be8ff021369c90554d814839335b445b0Adam Momtaz * {@link #scrollForward()}. 1633d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 164467cca7d25dbbf13c14cfd8c2ad38ab8eaf56bdaAdam Momtaz * @param steps indicates the number of injected move steps into the system. Steps are 165467cca7d25dbbf13c14cfd8c2ad38ab8eaf56bdaAdam Momtaz * injected about 5ms apart. So a 100 steps may take about 1/2 second to complete. 1663d50587be8ff021369c90554d814839335b445b0Adam Momtaz * @return true of successful 167e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 168e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 169e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean swipeUp(int steps) throws UiObjectNotFoundException { 1703d50587be8ff021369c90554d814839335b445b0Adam Momtaz Rect rect = getVisibleBounds(); 171e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(rect.height() <= SWIPE_MARGIN_LIMIT * 2) 172e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return false; // too small to swipe 173e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return getInteractionController().swipe(rect.centerX(), 174e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu rect.bottom - SWIPE_MARGIN_LIMIT, rect.centerX(), rect.top + SWIPE_MARGIN_LIMIT, 175e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu steps); 176e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 177e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 178e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 179e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Perform the action on the UI element that is represented by this object, Also see 180e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * {@link #scrollToBeginning(int)}, {@link #scrollToEnd(int)}, {@link #scrollBackward()}, 181e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * {@link #scrollForward()}. This method will perform the swipe gesture over any 182e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * surface. The targeted UI element does not need to have the attribute 183e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * <code>scrollable</code> set to <code>true</code> for this operation to be performed. 1843d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 1853d50587be8ff021369c90554d814839335b445b0Adam Momtaz * @param steps indicates the number of injected move steps into the system. Steps are 186467cca7d25dbbf13c14cfd8c2ad38ab8eaf56bdaAdam Momtaz * injected about 5ms apart. So a 100 steps may take about 1/2 second to complete. 1873d50587be8ff021369c90554d814839335b445b0Adam Momtaz * @return true if successful 188e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 189e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 190e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean swipeDown(int steps) throws UiObjectNotFoundException { 1913d50587be8ff021369c90554d814839335b445b0Adam Momtaz Rect rect = getVisibleBounds(); 192e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(rect.height() <= SWIPE_MARGIN_LIMIT * 2) 193e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return false; // too small to swipe 194e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return getInteractionController().swipe(rect.centerX(), 195e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu rect.top + SWIPE_MARGIN_LIMIT, rect.centerX(), 196e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu rect.bottom - SWIPE_MARGIN_LIMIT, steps); 197e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 198e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 199e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 200e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Perform the action on the UI element that is represented by this object. Also see 201e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * {@link #scrollToBeginning(int)}, {@link #scrollToEnd(int)}, {@link #scrollBackward()}, 202e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * {@link #scrollForward()}. This method will perform the swipe gesture over any 203e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * surface. The targeted UI element does not need to have the attribute 204e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * <code>scrollable</code> set to <code>true</code> for this operation to be performed. 2053d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 2063d50587be8ff021369c90554d814839335b445b0Adam Momtaz * @param steps indicates the number of injected move steps into the system. Steps are 207467cca7d25dbbf13c14cfd8c2ad38ab8eaf56bdaAdam Momtaz * injected about 5ms apart. So a 100 steps may take about 1/2 second to complete. 2083d50587be8ff021369c90554d814839335b445b0Adam Momtaz * @return true if successful 209e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 210e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 211e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean swipeLeft(int steps) throws UiObjectNotFoundException { 2123d50587be8ff021369c90554d814839335b445b0Adam Momtaz Rect rect = getVisibleBounds(); 213e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(rect.width() <= SWIPE_MARGIN_LIMIT * 2) 214e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return false; // too small to swipe 215e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return getInteractionController().swipe(rect.right - SWIPE_MARGIN_LIMIT, 216e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu rect.centerY(), rect.left + SWIPE_MARGIN_LIMIT, rect.centerY(), steps); 217e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 218e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 219e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 220e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * Perform the action on the UI element that is represented by this object. Also see 221e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * {@link #scrollToBeginning(int)}, {@link #scrollToEnd(int)}, {@link #scrollBackward()}, 222e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * {@link #scrollForward()}. This method will perform the swipe gesture over any 223e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * surface. The targeted UI element does not need to have the attribute 224e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * <code>scrollable</code> set to <code>true</code> for this operation to be performed. 2253d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 2263d50587be8ff021369c90554d814839335b445b0Adam Momtaz * @param steps indicates the number of injected move steps into the system. Steps are 227467cca7d25dbbf13c14cfd8c2ad38ab8eaf56bdaAdam Momtaz * injected about 5ms apart. So a 100 steps may take about 1/2 second to complete. 2283d50587be8ff021369c90554d814839335b445b0Adam Momtaz * @return true if successful 229e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 230e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 231e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean swipeRight(int steps) throws UiObjectNotFoundException { 2323d50587be8ff021369c90554d814839335b445b0Adam Momtaz Rect rect = getVisibleBounds(); 233e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(rect.width() <= SWIPE_MARGIN_LIMIT * 2) 234e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return false; // too small to swipe 235e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return getInteractionController().swipe(rect.left + SWIPE_MARGIN_LIMIT, 236e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu rect.centerY(), rect.right - SWIPE_MARGIN_LIMIT, rect.centerY(), steps); 237e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 238e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 239e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 2403d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Finds the visible bounds of a partially visible UI element 2413d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 242e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param node 2437f38ef08d07295967b905a61b2356ff6cdf31159Adam Momtaz * @return null if node is null, else a Rect containing visible bounds 244e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 245e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu private Rect getVisibleBounds(AccessibilityNodeInfo node) { 246e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if (node == null) { 247e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return null; 248e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 249e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 250e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // targeted node's bounds 2517f38ef08d07295967b905a61b2356ff6cdf31159Adam Momtaz Rect nodeRect = AccessibilityNodeInfoHelper.getVisibleBoundsInScreen(node); 252e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 253e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // is the targeted node within a scrollable container? 254e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu AccessibilityNodeInfo scrollableParentNode = getScrollableParent(node); 255e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(scrollableParentNode == null) { 256e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // nothing to adjust for so return the node's Rect as is 257e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return nodeRect; 258e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 259e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 260e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // Scrollable parent's visible bounds 2617f38ef08d07295967b905a61b2356ff6cdf31159Adam Momtaz Rect parentRect = AccessibilityNodeInfoHelper 2627f38ef08d07295967b905a61b2356ff6cdf31159Adam Momtaz .getVisibleBoundsInScreen(scrollableParentNode); 263e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // adjust for partial clipping of targeted by parent node if required 264e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu nodeRect.intersect(parentRect); 265e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return nodeRect; 266e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 267e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 268e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 2697f38ef08d07295967b905a61b2356ff6cdf31159Adam Momtaz * Walk the hierarchy up to find a scrollable parent. A scrollable parent 2707f38ef08d07295967b905a61b2356ff6cdf31159Adam Momtaz * indicates that this node may be in a content where it is partially 2717f38ef08d07295967b905a61b2356ff6cdf31159Adam Momtaz * visible due to scrolling. its clickable center maybe invisible and 2727f38ef08d07295967b905a61b2356ff6cdf31159Adam Momtaz * adjustments should be made to the click coordinates. 2733d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 274e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @param node 275e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return 276e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 277e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu private AccessibilityNodeInfo getScrollableParent(AccessibilityNodeInfo node) { 278e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu AccessibilityNodeInfo parent = node; 279e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu while(parent != null) { 280e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu parent = parent.getParent(); 281e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if (parent != null && parent.isScrollable()) { 282e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return parent; 283e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 284e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 285e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return null; 286e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 287e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 288e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 2893d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Performs a click at the center of the visible bounds of the UI element represented 29046d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * by this UiObject. 2913d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 292e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true id successful else false 293e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 294e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 295e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean click() throws UiObjectNotFoundException { 296e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT); 297e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 298e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 299e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 300e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu Rect rect = getVisibleBounds(node); 3014ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz return getInteractionController().click(rect.centerX(), rect.centerY()); 302e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 303e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 304e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 3053d50587be8ff021369c90554d814839335b445b0Adam Momtaz * See {@link #clickAndWaitForNewWindow(long)} 306a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz * This method is intended to reliably wait for window transitions that would typically take 307a46ac3504426564954292b13380120e8cc6b1527Adam Momtaz * longer than the usual default timeouts. 3083d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 3093d50587be8ff021369c90554d814839335b445b0Adam Momtaz * @return true if the event was triggered, else false 3103d50587be8ff021369c90554d814839335b445b0Adam Momtaz * @throws UiObjectNotFoundException 3113d50587be8ff021369c90554d814839335b445b0Adam Momtaz */ 312e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean clickAndWaitForNewWindow() throws UiObjectNotFoundException { 313e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return clickAndWaitForNewWindow(WAIT_FOR_WINDOW_TMEOUT); 314e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 315e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 316e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 31746d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * Performs a click at the center of the visible bounds of the UI element represented 31846d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * by this UiObject and waits for window transitions. 31946d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * 3203d50587be8ff021369c90554d814839335b445b0Adam Momtaz * This method differ from {@link UiObject#click()} only in that this method waits for a 32146d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * a new window transition as a result of the click. Some examples of a window transition: 322e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * <li>launching a new activity</li> 323e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * <li>bringing up a pop-up menu</li> 324e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * <li>bringing up a dialog</li> 325e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * 3263d50587be8ff021369c90554d814839335b445b0Adam Momtaz * @param timeout timeout before giving up on waiting for a new window 327e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if the event was triggered, else false 328e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 329e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 330e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean clickAndWaitForNewWindow(long timeout) throws UiObjectNotFoundException { 331e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT); 332e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 333e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 334e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 335e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu Rect rect = getVisibleBounds(node); 3364ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz return getInteractionController().clickAndWaitForNewWindow( 337e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu rect.centerX(), rect.centerY(), timeout); 338e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 339e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 340e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 3413d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Clicks the top and left corner of the UI element 3423d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 343e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true on success 344e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws Exception 345e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 346e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean clickTopLeft() throws UiObjectNotFoundException { 347e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT); 348e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 349e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 350e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 351e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu Rect rect = getVisibleBounds(node); 3524ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz return getInteractionController().click(rect.left + 5, rect.top + 5); 353e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 354e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 355e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 3563d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Long clicks bottom and right corner of the UI element 3573d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 358e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if operation was successful 359e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 360e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 361e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean longClickBottomRight() throws UiObjectNotFoundException { 362e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT); 363e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 364e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 365e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 366e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu Rect rect = getVisibleBounds(node); 367e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return getInteractionController().longTap(rect.right - 5, rect.bottom - 5); 368e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 369e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 370e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 3713d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Clicks the bottom and right corner of the UI element 3723d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 373e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true on success 374e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws Exception 375e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 376e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean clickBottomRight() throws UiObjectNotFoundException { 377e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT); 378e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 379e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 380e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 381e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu Rect rect = getVisibleBounds(node); 3824ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz return getInteractionController().click(rect.right - 5, rect.bottom - 5); 383e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 384e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 385e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 3863d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Long clicks the center of the visible bounds of the UI element 3873d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 388e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if operation was successful 389e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 390e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 391e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean longClick() throws UiObjectNotFoundException { 392e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT); 393e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 394e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 395e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 396e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu Rect rect = getVisibleBounds(node); 397e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return getInteractionController().longTap(rect.centerX(), rect.centerY()); 398e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 399e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 400e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 4013d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Long clicks on the top and left corner of the UI element 4023d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 403e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if operation was successful 404e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 405e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 406e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean longClickTopLeft() throws UiObjectNotFoundException { 407e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT); 408e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 409e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 410e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 411e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu Rect rect = getVisibleBounds(node); 412e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return getInteractionController().longTap(rect.left + 5, rect.top + 5); 413e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 414e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 415e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 4163d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Reads the <code>text</code> property of the UI element 4173d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 418e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return text value of the current node represented by this UiObject 419e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException if no match could be found 420e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 421e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public String getText() throws UiObjectNotFoundException { 422e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT); 423e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 424e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 425e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 426e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu String retVal = safeStringReturn(node.getText()); 427e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu Log.d(LOG_TAG, String.format("getText() = %s", retVal)); 428e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return retVal; 429e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 430e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 431e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 4323d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Reads the <code>content_desc</code> property of the UI element 4333d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 434e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return value of node attribute "content_desc" 435e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 436e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 437e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public String getContentDescription() throws UiObjectNotFoundException { 438e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT); 439e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 440e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 441e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 442e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return safeStringReturn(node.getContentDescription()); 443e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 444e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 445e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 44646d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * Sets the text in an editable field, after clearing the field's content. 44746d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * 44846d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * The {@link UiSelector} selector of this object must reference a UI element that is editable. 44946d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * 45046d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * When you call this method, the method first simulates a {@link #click()} on 45146d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * editable field to set focus. The method then clears the field's contents 45246d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * and injects your specified text into the field. 4533d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 45446d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * If you want to capture the original contents of the field, call {@link #getText()} first. 45546d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * You can then modify the text and use this method to update the field. 45646d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * 45746d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * @param text string to set 458e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if operation is successful 459e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 460e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 461e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean setText(String text) throws UiObjectNotFoundException { 462e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu clearTextField(); 463e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return getInteractionController().sendText(text); 464e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 465e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 466e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 46746d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * Clears the existing text contents in an editable field. 46846d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * 46946d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * The {@link UiSelector} of this object must reference a UI element that is editable. 47046d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * 47146d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * When you call this method, the method first sets focus at the start edge of the field. 47246d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * The method then simulates a long-press to select the existing text, and deletes the 47346d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * selected text. 47446d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * 47546d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * If a "Select-All" option is displayed, the method will automatically attempt to use it 47646d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * to ensure full text selection. 47746d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * 47846d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * Note that it is possible that not all the text in the field is selected; for example, 47946d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * if the text contains separators such as spaces, slashes, at symbol etc. 48046d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * Also, not all editable fields support the long-press functionality. 48146d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * 482e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 483e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 484e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public void clearTextField() throws UiObjectNotFoundException { 485e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // long click left + center 486e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT); 487e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 488e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 489e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 490e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu Rect rect = getVisibleBounds(node); 491e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu getInteractionController().longTap(rect.left + 20, rect.centerY()); 492e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // check if the edit menu is open 4934ab790eccf6d5c27f542056b87d26d38f7caeeb3Adam Momtaz UiObject selectAll = new UiObject(new UiSelector().descriptionContains("Select all")); 494e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(selectAll.waitForExists(50)) 495e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu selectAll.click(); 496e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // wait for the selection 497e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu SystemClock.sleep(250); 498e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu // delete it 499e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu getInteractionController().sendKey(KeyEvent.KEYCODE_DEL, 0); 500e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 501e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 502e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 5033d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Check if the UI element's <code>checked</code> property is currently true 5043d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 505e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if it is else false 506e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 507e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean isChecked() throws UiObjectNotFoundException { 508e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT); 509e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 510e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 511e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 512e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return node.isChecked(); 513e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 514e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 515e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 5163d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Check if the UI element's <code>selected</code> property is currently true 5173d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 518e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if it is else false 519e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 520e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 521e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean isSelected() throws UiObjectNotFoundException { 522e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT); 523e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 524e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 525e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 526e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return node.isSelected(); 527e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 528e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 529e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 5303d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Check if the UI element's <code>checkable</code> property is currently true 5313d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 532e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if it is else false 533e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 534e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 535e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean isCheckable() throws UiObjectNotFoundException { 536e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT); 537e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 538e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 539e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 540e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return node.isCheckable(); 541e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 542e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 543e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 5443d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Check if the UI element's <code>enabled</code> property is currently true 5453d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 546e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if it is else false 547e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 548e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 549e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean isEnabled() throws UiObjectNotFoundException { 550e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT); 551e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 552e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 553e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 554e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return node.isEnabled(); 555e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 556e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 557e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 5583d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Check if the UI element's <code>clickable</code> property is currently true 5593d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 560e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if it is else false 561e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 562e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 563e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean isClickable() throws UiObjectNotFoundException { 564e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT); 565e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 566e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 567e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 568e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return node.isClickable(); 569e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 570e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 571e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 5723d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Check if the UI element's <code>focused</code> property is currently true 5733d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 574e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if it is else false 575e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 576e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 577e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean isFocused() throws UiObjectNotFoundException { 578e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT); 579e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 580e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 581e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 582e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return node.isFocused(); 583e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 584e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 585e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 5863d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Check if the UI element's <code>focusable</code> property is currently true 5873d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 588e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if it is else false 589e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 590e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 591e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean isFocusable() throws UiObjectNotFoundException { 592e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT); 593e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 594e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 595e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 596e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return node.isFocusable(); 597e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 598e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 599e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 6003d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Check if the UI element's <code>scrollable</code> property is currently true 6013d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 602e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if it is else false 603e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 604e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 605e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean isScrollable() throws UiObjectNotFoundException { 606e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT); 607e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 608e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 609e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 610e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return node.isScrollable(); 611e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 612e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 613e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 6143d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Check if the UI element's <code>long-clickable</code> property is currently true 6153d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 616e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if it is else false 617e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 618e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 619e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean isLongClickable() throws UiObjectNotFoundException { 620e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT); 621e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 622e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 623e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 624e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return node.isLongClickable(); 625e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 626e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 627e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 6283d50587be8ff021369c90554d814839335b445b0Adam Momtaz * Reads the UI element's <code>package</code> property 6293d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 6303d50587be8ff021369c90554d814839335b445b0Adam Momtaz * @return true if it is else false 631e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 632e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 633e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public String getPackageName() throws UiObjectNotFoundException { 634e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT); 635e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 636e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 637e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 638e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return safeStringReturn(node.getPackageName()); 639e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 640e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 641e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 64246d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * Returns the visible bounds of the UI element. 64346d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * 64446d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * If a portion of the UI element is visible, only the bounds of the visible portion are 64546d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * reported. 6463d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 647e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return Rect 648e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @throws UiObjectNotFoundException 64946d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * @see {@link #getBound()} 650e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 6513d50587be8ff021369c90554d814839335b445b0Adam Momtaz public Rect getVisibleBounds() throws UiObjectNotFoundException { 652e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT); 653e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(node == null) { 654e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu throw new UiObjectNotFoundException(getSelector().toString()); 655e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 656e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return getVisibleBounds(node); 657e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 658e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 659e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 66046d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * Returns the UI element's <code>bounds</code> property. See {@link #getVisibleBounds()} 6613d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 6623d50587be8ff021369c90554d814839335b445b0Adam Momtaz * @return Rect 6633d50587be8ff021369c90554d814839335b445b0Adam Momtaz * @throws UiObjectNotFoundException 6643d50587be8ff021369c90554d814839335b445b0Adam Momtaz */ 6653d50587be8ff021369c90554d814839335b445b0Adam Momtaz public Rect getBounds() throws UiObjectNotFoundException { 6663d50587be8ff021369c90554d814839335b445b0Adam Momtaz AccessibilityNodeInfo node = findAccessibilityNodeInfo(WAIT_FOR_SELECTOR_TIMEOUT); 6673d50587be8ff021369c90554d814839335b445b0Adam Momtaz if(node == null) { 6683d50587be8ff021369c90554d814839335b445b0Adam Momtaz throw new UiObjectNotFoundException(getSelector().toString()); 6693d50587be8ff021369c90554d814839335b445b0Adam Momtaz } 6703d50587be8ff021369c90554d814839335b445b0Adam Momtaz Rect nodeRect = new Rect(); 6713d50587be8ff021369c90554d814839335b445b0Adam Momtaz node.getBoundsInScreen(nodeRect); 6723d50587be8ff021369c90554d814839335b445b0Adam Momtaz 6733d50587be8ff021369c90554d814839335b445b0Adam Momtaz return nodeRect; 6743d50587be8ff021369c90554d814839335b445b0Adam Momtaz } 6753d50587be8ff021369c90554d814839335b445b0Adam Momtaz 6763d50587be8ff021369c90554d814839335b445b0Adam Momtaz /** 67746d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * Waits a specified length of time for a UI element to become visible. 67846d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * 67946d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * This method waits until the UI element becomes visible on the display, or 68046d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * until the timeout has elapsed. You can use this method in situations where 68146d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * the content that you want to select is not immediately displayed. 6823d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 68346d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * @param timeout the amount of time to wait (in milliseconds) 68446d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * @return true if the UI element is displayed, else false if timeout elapsed while waiting 685e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 686e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean waitForExists(long timeout) { 687e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(findAccessibilityNodeInfo(timeout) != null) { 688e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return true; 689e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 690e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return false; 691e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 692e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 693e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 69446d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * Waits a specified length of time for a UI element to become undetectable. 6953d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 69646d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * This method waits until a UI element is no longer matchable, or until the 69746d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * timeout has elapsed. 69846d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * 69946d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * A UI element becomes undetectable when the {@link UiSelector} of the object is 70046d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * unable to find a match because the element has either changed its state or is no 70146d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * longer displayed. 70246d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * 70346d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * You can use this method when attempting to wait for some long operation 70446d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * to compete, such as downloading a large file or connecting to a remote server. 70546d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * 70646d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * @param timeout time to wait (in milliseconds) 70746d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * @return true if the element is gone before timeout elapsed, else false if timeout elapsed 70846d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * but a matching element is still found. 709e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 710e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean waitUntilGone(long timeout) { 711e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu long startMills = SystemClock.uptimeMillis(); 712e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu long currentMills = 0; 713e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu while (currentMills <= timeout) { 714e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(findAccessibilityNodeInfo(0) == null) 715e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return true; 716e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu currentMills = SystemClock.uptimeMillis() - startMills; 717e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(timeout > 0) 718e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu SystemClock.sleep(WAIT_FOR_SELECTOR_POLL); 719e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 720e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return false; 721e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 722e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 723e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu /** 72446d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * Check if UI element exists. 72546d9444c7a39dc1c9fc60a5dcf4e79749d9b3859Adam Momtaz * 726e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * This methods performs a {@link #waitForExists(long)} with zero timeout. This 727e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * basically returns immediately whether the UI element represented by this UiObject 728e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * exists or not. If you need to wait longer for this UI element, then see 729e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * {@link #waitForExists(long)}. 7303d50587be8ff021369c90554d814839335b445b0Adam Momtaz * 731e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu * @return true if the UI element represented by this UiObject does exist 732e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu */ 733e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu public boolean exists() { 734e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return waitForExists(0); 735e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 736e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu 737e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu private String safeStringReturn(CharSequence cs) { 738e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu if(cs == null) 739e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return ""; 740e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu return cs.toString(); 741e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu } 742e54d649fb83a0a44516e5c25a9ac1992c8950e59Guang Zhu} 743