java.lang.Object
↳androidx.test.uiautomator.UiSelector
Gradle dependencies
compile group: 'androidx.test.uiautomator', name: 'uiautomator', version: '2.4.0-alpha01'
- groupId: androidx.test.uiautomator
- artifactId: uiautomator
- version: 2.4.0-alpha01
Artifact androidx.test.uiautomator:uiautomator:2.4.0-alpha01 it located at Google repository (https://maven.google.com/)
Androidx artifact mapping:
androidx.test.uiautomator:uiautomator com.android.support.test.uiautomator:uiautomator
Androidx class mapping:
androidx.test.uiautomator.UiSelector android.support.test.uiautomator.UiSelector
Overview
Specifies the elements in the layout hierarchy for tests to target, filtered
by properties such as text value, content-description, class name, and state
information. You can also target an element by its location in a layout
hierarchy.
Summary
Methods |
---|
public UiSelector | checkable(boolean val)
Set the search criteria to match widgets that are checkable. |
public UiSelector | checked(boolean val)
Set the search criteria to match widgets that
are currently checked (usually for checkboxes). |
public UiSelector | childSelector(UiSelector selector)
Adds a child UiSelector criteria to this selector. |
public UiSelector | className(java.lang.Class<java.lang.Object> type)
Set the search criteria to match the class property
for a widget (for example, "android.widget.Button"). |
public UiSelector | className(java.lang.String className)
Set the search criteria to match the class property
for a widget (for example, "android.widget.Button"). |
public UiSelector | classNameMatches(java.lang.String regex)
Set the search criteria to match the class property
for a widget, using a regular expression. |
public UiSelector | clickable(boolean val)
Set the search criteria to match widgets that are clickable. |
protected UiSelector | cloneSelector()
|
public UiSelector | description(java.lang.String desc)
Set the search criteria to match the content-description
property for a widget. |
public UiSelector | descriptionContains(java.lang.String desc)
Set the search criteria to match the content-description
property for a widget. |
public UiSelector | descriptionMatches(java.lang.String regex)
Set the search criteria to match the content-description
property for a widget. |
public UiSelector | descriptionStartsWith(java.lang.String desc)
Set the search criteria to match the content-description
property for a widget. |
public UiSelector | enabled(boolean val)
Set the search criteria to match widgets that are enabled. |
public UiSelector | focusable(boolean val)
Set the search criteria to match widgets that are focusable. |
public UiSelector | focused(boolean val)
Set the search criteria to match widgets that have focus. |
public UiSelector | fromParent(UiSelector selector)
Adds a child UiSelector criteria to this selector which is used to
start search from the parent widget. |
public UiSelector | index(int index)
Set the search criteria to match the widget by its node
index in the layout hierarchy. |
public UiSelector | instance(int instance)
Set the search criteria to match the
widget by its instance number. |
public UiSelector | longClickable(boolean val)
Set the search criteria to match widgets that are long-clickable. |
public UiSelector | packageName(java.lang.String name)
Set the search criteria to match the package name
of the application that contains the widget. |
public UiSelector | packageNameMatches(java.lang.String regex)
Set the search criteria to match the package name
of the application that contains the widget. |
public UiSelector | resourceId(java.lang.String id)
Set the search criteria to match the given resource ID. |
public UiSelector | resourceIdMatches(java.lang.String regex)
Set the search criteria to match the resource ID
of the widget, using a regular expression. |
public UiSelector | scrollable(boolean val)
Set the search criteria to match widgets that are scrollable. |
public UiSelector | selected(boolean val)
Set the search criteria to match widgets that
are currently selected. |
public UiSelector | text(java.lang.String text)
Set the search criteria to match the visible text displayed
in a widget (for example, the text label to launch an app). |
public UiSelector | textContains(java.lang.String text)
Set the search criteria to match the visible text in a widget
where the visible text must contain the string in your input argument. |
public UiSelector | textMatches(java.lang.String regex)
Set the search criteria to match the visible text displayed in a layout
element, using a regular expression. |
public UiSelector | textStartsWith(java.lang.String text)
Set the search criteria to match visible text in a widget that is
prefixed by the text parameter. |
public java.lang.String | toString()
|
from java.lang.Object | clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait |
Constructors
Methods
Set the search criteria to match the visible text displayed
in a widget (for example, the text label to launch an app).
The text for the element must match exactly with the string in your input
argument. Matching is case-sensitive.
Parameters:
text: Value to match
Returns:
UiSelector with the specified search criteria
public
UiSelector textMatches(java.lang.String regex)
Set the search criteria to match the visible text displayed in a layout
element, using a regular expression.
The text in the widget must match exactly with the string in your
input argument.
Parameters:
regex: a regular expression
Returns:
UiSelector with the specified search criteria
public
UiSelector textStartsWith(java.lang.String text)
Set the search criteria to match visible text in a widget that is
prefixed by the text parameter.
The matching is case-insensitive.
Parameters:
text: Value to match
Returns:
UiSelector with the specified search criteria
public
UiSelector textContains(java.lang.String text)
Set the search criteria to match the visible text in a widget
where the visible text must contain the string in your input argument.
The matching is case-sensitive.
Parameters:
text: Value to match
Returns:
UiSelector with the specified search criteria
public
UiSelector className(java.lang.String className)
Set the search criteria to match the class property
for a widget (for example, "android.widget.Button").
Parameters:
className: Value to match
Returns:
UiSelector with the specified search criteria
public
UiSelector classNameMatches(java.lang.String regex)
Set the search criteria to match the class property
for a widget, using a regular expression.
Parameters:
regex: a regular expression
Returns:
UiSelector with the specified search criteria
public
UiSelector className(java.lang.Class<java.lang.Object> type)
Set the search criteria to match the class property
for a widget (for example, "android.widget.Button").
Parameters:
type: type
Returns:
UiSelector with the specified search criteria
public
UiSelector description(java.lang.String desc)
Set the search criteria to match the content-description
property for a widget.
The content-description is typically used
by the Android Accessibility framework to
provide an audio prompt for the widget when
the widget is selected. The content-description
for the widget must match exactly
with the string in your input argument.
Matching is case-sensitive.
Parameters:
desc: Value to match
Returns:
UiSelector with the specified search criteria
public
UiSelector descriptionMatches(java.lang.String regex)
Set the search criteria to match the content-description
property for a widget.
The content-description is typically used
by the Android Accessibility framework to
provide an audio prompt for the widget when
the widget is selected. The content-description
for the widget must match exactly
with the string in your input argument.
Parameters:
regex: a regular expression
Returns:
UiSelector with the specified search criteria
public
UiSelector descriptionStartsWith(java.lang.String desc)
Set the search criteria to match the content-description
property for a widget.
The content-description is typically used
by the Android Accessibility framework to
provide an audio prompt for the widget when
the widget is selected. The content-description
for the widget must start
with the string in your input argument.
Matching is case-insensitive.
Parameters:
desc: Value to match
Returns:
UiSelector with the specified search criteria
public
UiSelector descriptionContains(java.lang.String desc)
Set the search criteria to match the content-description
property for a widget.
The content-description is typically used
by the Android Accessibility framework to
provide an audio prompt for the widget when
the widget is selected. The content-description
for the widget must contain
the string in your input argument.
Matching is case-insensitive.
Parameters:
desc: Value to match
Returns:
UiSelector with the specified search criteria
Set the search criteria to match the given resource ID.
Parameters:
id: Value to match
Returns:
UiSelector with the specified search criteria
public
UiSelector resourceIdMatches(java.lang.String regex)
Set the search criteria to match the resource ID
of the widget, using a regular expression.
Parameters:
regex: a regular expression
Returns:
UiSelector with the specified search criteria
Set the search criteria to match the widget by its node
index in the layout hierarchy.
The index value must be 0 or greater.
Using the index can be unreliable and should only
be used as a last resort for matching. Instead,
consider using the UiSelector.instance(int) method.
Parameters:
index: Value to match
Returns:
UiSelector with the specified search criteria
Set the search criteria to match the
widget by its instance number.
The instance value must be 0 or greater, where
the first instance is 0.
For example, to simulate a user click on
the third image that is enabled in a UI screen, you
could specify a a search criteria where the instance is
2, the UiSelector.className(String) matches the image
widget class, and UiSelector.enabled(boolean) is true.
The code would look like this:
new UiSelector().className("android.widget.ImageView")
.enabled(true).instance(2);
Parameters:
instance: Value to match
Returns:
UiSelector with the specified search criteria
Set the search criteria to match widgets that are enabled.
Typically, using this search criteria alone is not useful.
You should also include additional criteria, such as text,
content-description, or the class name for a widget.
If no other search criteria is specified, and there is more
than one matching widget, the first widget in the tree
is selected.
Parameters:
val: Value to match
Returns:
UiSelector with the specified search criteria
Set the search criteria to match widgets that have focus.
Typically, using this search criteria alone is not useful.
You should also include additional criteria, such as text,
content-description, or the class name for a widget.
If no other search criteria is specified, and there is more
than one matching widget, the first widget in the tree
is selected.
Parameters:
val: Value to match
Returns:
UiSelector with the specified search criteria
Set the search criteria to match widgets that are focusable.
Typically, using this search criteria alone is not useful.
You should also include additional criteria, such as text,
content-description, or the class name for a widget.
If no other search criteria is specified, and there is more
than one matching widget, the first widget in the tree
is selected.
Parameters:
val: Value to match
Returns:
UiSelector with the specified search criteria
Set the search criteria to match widgets that are scrollable.
Typically, using this search criteria alone is not useful.
You should also include additional criteria, such as text,
content-description, or the class name for a widget.
If no other search criteria is specified, and there is more
than one matching widget, the first widget in the tree
is selected.
Parameters:
val: Value to match
Returns:
UiSelector with the specified search criteria
Set the search criteria to match widgets that
are currently selected.
Typically, using this search criteria alone is not useful.
You should also include additional criteria, such as text,
content-description, or the class name for a widget.
If no other search criteria is specified, and there is more
than one matching widget, the first widget in the tree
is selected.
Parameters:
val: Value to match
Returns:
UiSelector with the specified search criteria
Set the search criteria to match widgets that
are currently checked (usually for checkboxes).
Typically, using this search criteria alone is not useful.
You should also include additional criteria, such as text,
content-description, or the class name for a widget.
If no other search criteria is specified, and there is more
than one matching widget, the first widget in the tree
is selected.
Parameters:
val: Value to match
Returns:
UiSelector with the specified search criteria
Set the search criteria to match widgets that are clickable.
Typically, using this search criteria alone is not useful.
You should also include additional criteria, such as text,
content-description, or the class name for a widget.
If no other search criteria is specified, and there is more
than one matching widget, the first widget in the tree
is selected.
Parameters:
val: Value to match
Returns:
UiSelector with the specified search criteria
Set the search criteria to match widgets that are checkable.
Typically, using this search criteria alone is not useful.
You should also include additional criteria, such as text,
content-description, or the class name for a widget.
If no other search criteria is specified, and there is more
than one matching widget, the first widget in the tree
is selected.
Parameters:
val: Value to match
Returns:
UiSelector with the specified search criteria
Set the search criteria to match widgets that are long-clickable.
Typically, using this search criteria alone is not useful.
You should also include additional criteria, such as text,
content-description, or the class name for a widget.
If no other search criteria is specified, and there is more
than one matching widget, the first widget in the tree
is selected.
Parameters:
val: Value to match
Returns:
UiSelector with the specified search criteria
Adds a child UiSelector criteria to this selector.
Use this selector to narrow the search scope to
child widgets under a specific parent widget.
Parameters:
selector:
Returns:
UiSelector with this added search criterion
Adds a child UiSelector criteria to this selector which is used to
start search from the parent widget.
Use this selector to narrow the search scope to
sibling widgets as well all child widgets under a parent.
Parameters:
selector:
Returns:
UiSelector with this added search criterion
public
UiSelector packageName(java.lang.String name)
Set the search criteria to match the package name
of the application that contains the widget.
Parameters:
name: Value to match
Returns:
UiSelector with the specified search criteria
public
UiSelector packageNameMatches(java.lang.String regex)
Set the search criteria to match the package name
of the application that contains the widget.
Parameters:
regex: a regular expression
Returns:
UiSelector with the specified search criteria
public java.lang.String
toString()
Source
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.test.uiautomator;
import static java.util.Objects.requireNonNull;
import android.util.SparseArray;
import android.view.accessibility.AccessibilityNodeInfo;
import androidx.annotation.NonNull;
import java.util.regex.Pattern;
/**
* Specifies the elements in the layout hierarchy for tests to target, filtered
* by properties such as text value, content-description, class name, and state
* information. You can also target an element by its location in a layout
* hierarchy.
*/
public class UiSelector {
static final int SELECTOR_NIL = 0;
static final int SELECTOR_TEXT = 1;
static final int SELECTOR_START_TEXT = 2;
static final int SELECTOR_CONTAINS_TEXT = 3;
static final int SELECTOR_CLASS = 4;
static final int SELECTOR_DESCRIPTION = 5;
static final int SELECTOR_START_DESCRIPTION = 6;
static final int SELECTOR_CONTAINS_DESCRIPTION = 7;
static final int SELECTOR_INDEX = 8;
static final int SELECTOR_INSTANCE = 9;
static final int SELECTOR_ENABLED = 10;
static final int SELECTOR_FOCUSED = 11;
static final int SELECTOR_FOCUSABLE = 12;
static final int SELECTOR_SCROLLABLE = 13;
static final int SELECTOR_CLICKABLE = 14;
static final int SELECTOR_CHECKED = 15;
static final int SELECTOR_SELECTED = 16;
static final int SELECTOR_ID = 17;
static final int SELECTOR_PACKAGE_NAME = 18;
static final int SELECTOR_CHILD = 19;
static final int SELECTOR_CONTAINER = 20;
static final int SELECTOR_PATTERN = 21;
static final int SELECTOR_PARENT = 22;
static final int SELECTOR_COUNT = 23;
static final int SELECTOR_LONG_CLICKABLE = 24;
static final int SELECTOR_TEXT_REGEX = 25;
static final int SELECTOR_CLASS_REGEX = 26;
static final int SELECTOR_DESCRIPTION_REGEX = 27;
static final int SELECTOR_PACKAGE_NAME_REGEX = 28;
static final int SELECTOR_RESOURCE_ID = 29;
static final int SELECTOR_CHECKABLE = 30;
static final int SELECTOR_RESOURCE_ID_REGEX = 31;
private SparseArray<Object> mSelectorAttributes = new SparseArray<>();
public UiSelector() {
}
UiSelector(UiSelector selector) {
mSelectorAttributes = selector.cloneSelector().mSelectorAttributes;
}
@NonNull
protected UiSelector cloneSelector() {
UiSelector ret = new UiSelector();
ret.mSelectorAttributes = mSelectorAttributes.clone();
if (hasChildSelector())
ret.mSelectorAttributes.put(SELECTOR_CHILD, new UiSelector(getChildSelector()));
if (hasParentSelector())
ret.mSelectorAttributes.put(SELECTOR_PARENT, new UiSelector(getParentSelector()));
if (hasPatternSelector())
ret.mSelectorAttributes.put(SELECTOR_PATTERN, new UiSelector(getPatternSelector()));
return ret;
}
static UiSelector patternBuilder(UiSelector selector) {
if (!selector.hasPatternSelector()) {
return new UiSelector().patternSelector(selector);
}
return selector;
}
static UiSelector patternBuilder(UiSelector container, UiSelector pattern) {
return new UiSelector(
new UiSelector().containerSelector(container).patternSelector(pattern));
}
/**
* Set the search criteria to match the visible text displayed
* in a widget (for example, the text label to launch an app).
*
* The text for the element must match exactly with the string in your input
* argument. Matching is case-sensitive.
*
* @param text Value to match
* @return UiSelector with the specified search criteria
*/
@NonNull
public UiSelector text(@NonNull String text) {
requireNonNull(text, "text cannot be null");
return buildSelector(SELECTOR_TEXT, text);
}
/**
* Set the search criteria to match the visible text displayed in a layout
* element, using a regular expression.
*
* The text in the widget must match exactly with the string in your
* input argument.
*
* @param regex a regular expression
* @return UiSelector with the specified search criteria
*/
@NonNull
public UiSelector textMatches(@NonNull String regex) {
requireNonNull(regex, "regex cannot be null");
return buildSelector(SELECTOR_TEXT_REGEX, Pattern.compile(regex, Pattern.DOTALL));
}
/**
* Set the search criteria to match visible text in a widget that is
* prefixed by the text parameter.
*
* The matching is case-insensitive.
*
* @param text Value to match
* @return UiSelector with the specified search criteria
*/
@NonNull
public UiSelector textStartsWith(@NonNull String text) {
requireNonNull(text, "text cannot be null");
return buildSelector(SELECTOR_START_TEXT, text);
}
/**
* Set the search criteria to match the visible text in a widget
* where the visible text must contain the string in your input argument.
*
* The matching is case-sensitive.
*
* @param text Value to match
* @return UiSelector with the specified search criteria
*/
@NonNull
public UiSelector textContains(@NonNull String text) {
requireNonNull(text, "text cannot be null");
return buildSelector(SELECTOR_CONTAINS_TEXT, text);
}
/**
* Set the search criteria to match the class property
* for a widget (for example, "android.widget.Button").
*
* @param className Value to match
* @return UiSelector with the specified search criteria
*/
@NonNull
public UiSelector className(@NonNull String className) {
requireNonNull(className, "className cannot be null");
return buildSelector(SELECTOR_CLASS, className);
}
/**
* Set the search criteria to match the class property
* for a widget, using a regular expression.
*
* @param regex a regular expression
* @return UiSelector with the specified search criteria
*/
@NonNull
public UiSelector classNameMatches(@NonNull String regex) {
requireNonNull(regex, "regex cannot be null");
return buildSelector(SELECTOR_CLASS_REGEX, Pattern.compile(regex));
}
/**
* Set the search criteria to match the class property
* for a widget (for example, "android.widget.Button").
*
* @param type type
* @return UiSelector with the specified search criteria
*/
@NonNull
public <T> UiSelector className(@NonNull Class<T> type) {
requireNonNull(type, "type cannot be null");
return buildSelector(SELECTOR_CLASS, type.getName());
}
/**
* Set the search criteria to match the content-description
* property for a widget.
*
* The content-description is typically used
* by the Android Accessibility framework to
* provide an audio prompt for the widget when
* the widget is selected. The content-description
* for the widget must match exactly
* with the string in your input argument.
*
* Matching is case-sensitive.
*
* @param desc Value to match
* @return UiSelector with the specified search criteria
*/
@NonNull
public UiSelector description(@NonNull String desc) {
requireNonNull(desc, "desc cannot be null");
return buildSelector(SELECTOR_DESCRIPTION, desc);
}
/**
* Set the search criteria to match the content-description
* property for a widget.
*
* The content-description is typically used
* by the Android Accessibility framework to
* provide an audio prompt for the widget when
* the widget is selected. The content-description
* for the widget must match exactly
* with the string in your input argument.
*
* @param regex a regular expression
* @return UiSelector with the specified search criteria
*/
@NonNull
public UiSelector descriptionMatches(@NonNull String regex) {
requireNonNull(regex, "regex cannot be null");
return buildSelector(SELECTOR_DESCRIPTION_REGEX, Pattern.compile(regex, Pattern.DOTALL));
}
/**
* Set the search criteria to match the content-description
* property for a widget.
*
* The content-description is typically used
* by the Android Accessibility framework to
* provide an audio prompt for the widget when
* the widget is selected. The content-description
* for the widget must start
* with the string in your input argument.
*
* Matching is case-insensitive.
*
* @param desc Value to match
* @return UiSelector with the specified search criteria
*/
@NonNull
public UiSelector descriptionStartsWith(@NonNull String desc) {
requireNonNull(desc, "desc cannot be null");
return buildSelector(SELECTOR_START_DESCRIPTION, desc);
}
/**
* Set the search criteria to match the content-description
* property for a widget.
*
* The content-description is typically used
* by the Android Accessibility framework to
* provide an audio prompt for the widget when
* the widget is selected. The content-description
* for the widget must contain
* the string in your input argument.
*
* Matching is case-insensitive.
*
* @param desc Value to match
* @return UiSelector with the specified search criteria
*/
@NonNull
public UiSelector descriptionContains(@NonNull String desc) {
requireNonNull(desc, "desc cannot be null");
return buildSelector(SELECTOR_CONTAINS_DESCRIPTION, desc);
}
/**
* Set the search criteria to match the given resource ID.
*
* @param id Value to match
* @return UiSelector with the specified search criteria
*/
@NonNull
public UiSelector resourceId(@NonNull String id) {
requireNonNull(id, "id cannot be null");
return buildSelector(SELECTOR_RESOURCE_ID, id);
}
/**
* Set the search criteria to match the resource ID
* of the widget, using a regular expression.
*
* @param regex a regular expression
* @return UiSelector with the specified search criteria
*/
@NonNull
public UiSelector resourceIdMatches(@NonNull String regex) {
requireNonNull(regex, "regex cannot be null");
return buildSelector(SELECTOR_RESOURCE_ID_REGEX, Pattern.compile(regex));
}
/**
* Set the search criteria to match the widget by its node
* index in the layout hierarchy.
*
* The index value must be 0 or greater.
*
* Using the index can be unreliable and should only
* be used as a last resort for matching. Instead,
* consider using the {@link #instance(int)} method.
*
* @param index Value to match
* @return UiSelector with the specified search criteria
*/
@NonNull
public UiSelector index(final int index) {
return buildSelector(SELECTOR_INDEX, index);
}
/**
* Set the search criteria to match the
* widget by its instance number.
*
* The instance value must be 0 or greater, where
* the first instance is 0.
*
* For example, to simulate a user click on
* the third image that is enabled in a UI screen, you
* could specify a a search criteria where the instance is
* 2, the {@link #className(String)} matches the image
* widget class, and {@link #enabled(boolean)} is true.
* The code would look like this:
* <code>
* new UiSelector().className("android.widget.ImageView")
* .enabled(true).instance(2);
* </code>
*
* @param instance Value to match
* @return UiSelector with the specified search criteria
*/
@NonNull
public UiSelector instance(final int instance) {
return buildSelector(SELECTOR_INSTANCE, instance);
}
/**
* Set the search criteria to match widgets that are enabled.
*
* Typically, using this search criteria alone is not useful.
* You should also include additional criteria, such as text,
* content-description, or the class name for a widget.
*
* If no other search criteria is specified, and there is more
* than one matching widget, the first widget in the tree
* is selected.
*
* @param val Value to match
* @return UiSelector with the specified search criteria
*/
@NonNull
public UiSelector enabled(boolean val) {
return buildSelector(SELECTOR_ENABLED, val);
}
/**
* Set the search criteria to match widgets that have focus.
*
* Typically, using this search criteria alone is not useful.
* You should also include additional criteria, such as text,
* content-description, or the class name for a widget.
*
* If no other search criteria is specified, and there is more
* than one matching widget, the first widget in the tree
* is selected.
*
* @param val Value to match
* @return UiSelector with the specified search criteria
*/
@NonNull
public UiSelector focused(boolean val) {
return buildSelector(SELECTOR_FOCUSED, val);
}
/**
* Set the search criteria to match widgets that are focusable.
*
* Typically, using this search criteria alone is not useful.
* You should also include additional criteria, such as text,
* content-description, or the class name for a widget.
*
* If no other search criteria is specified, and there is more
* than one matching widget, the first widget in the tree
* is selected.
*
* @param val Value to match
* @return UiSelector with the specified search criteria
*/
@NonNull
public UiSelector focusable(boolean val) {
return buildSelector(SELECTOR_FOCUSABLE, val);
}
/**
* Set the search criteria to match widgets that are scrollable.
*
* Typically, using this search criteria alone is not useful.
* You should also include additional criteria, such as text,
* content-description, or the class name for a widget.
*
* If no other search criteria is specified, and there is more
* than one matching widget, the first widget in the tree
* is selected.
*
* @param val Value to match
* @return UiSelector with the specified search criteria
*/
@NonNull
public UiSelector scrollable(boolean val) {
return buildSelector(SELECTOR_SCROLLABLE, val);
}
/**
* Set the search criteria to match widgets that
* are currently selected.
*
* Typically, using this search criteria alone is not useful.
* You should also include additional criteria, such as text,
* content-description, or the class name for a widget.
*
* If no other search criteria is specified, and there is more
* than one matching widget, the first widget in the tree
* is selected.
*
* @param val Value to match
* @return UiSelector with the specified search criteria
*/
@NonNull
public UiSelector selected(boolean val) {
return buildSelector(SELECTOR_SELECTED, val);
}
/**
* Set the search criteria to match widgets that
* are currently checked (usually for checkboxes).
*
* Typically, using this search criteria alone is not useful.
* You should also include additional criteria, such as text,
* content-description, or the class name for a widget.
*
* If no other search criteria is specified, and there is more
* than one matching widget, the first widget in the tree
* is selected.
*
* @param val Value to match
* @return UiSelector with the specified search criteria
*/
@NonNull
public UiSelector checked(boolean val) {
return buildSelector(SELECTOR_CHECKED, val);
}
/**
* Set the search criteria to match widgets that are clickable.
*
* Typically, using this search criteria alone is not useful.
* You should also include additional criteria, such as text,
* content-description, or the class name for a widget.
*
* If no other search criteria is specified, and there is more
* than one matching widget, the first widget in the tree
* is selected.
*
* @param val Value to match
* @return UiSelector with the specified search criteria
*/
@NonNull
public UiSelector clickable(boolean val) {
return buildSelector(SELECTOR_CLICKABLE, val);
}
/**
* Set the search criteria to match widgets that are checkable.
*
* Typically, using this search criteria alone is not useful.
* You should also include additional criteria, such as text,
* content-description, or the class name for a widget.
*
* If no other search criteria is specified, and there is more
* than one matching widget, the first widget in the tree
* is selected.
*
* @param val Value to match
* @return UiSelector with the specified search criteria
*/
@NonNull
public UiSelector checkable(boolean val) {
return buildSelector(SELECTOR_CHECKABLE, val);
}
/**
* Set the search criteria to match widgets that are long-clickable.
*
* Typically, using this search criteria alone is not useful.
* You should also include additional criteria, such as text,
* content-description, or the class name for a widget.
*
* If no other search criteria is specified, and there is more
* than one matching widget, the first widget in the tree
* is selected.
*
* @param val Value to match
* @return UiSelector with the specified search criteria
*/
@NonNull
public UiSelector longClickable(boolean val) {
return buildSelector(SELECTOR_LONG_CLICKABLE, val);
}
/**
* Adds a child UiSelector criteria to this selector.
*
* Use this selector to narrow the search scope to
* child widgets under a specific parent widget.
*
* @param selector
* @return UiSelector with this added search criterion
*/
@NonNull
public UiSelector childSelector(@NonNull UiSelector selector) {
requireNonNull(selector, "selector cannot be null");
return buildSelector(SELECTOR_CHILD, selector);
}
private UiSelector patternSelector(UiSelector selector) {
return buildSelector(SELECTOR_PATTERN, selector);
}
private UiSelector containerSelector(UiSelector selector) {
return buildSelector(SELECTOR_CONTAINER, selector);
}
/**
* Adds a child UiSelector criteria to this selector which is used to
* start search from the parent widget.
*
* Use this selector to narrow the search scope to
* sibling widgets as well all child widgets under a parent.
*
* @param selector
* @return UiSelector with this added search criterion
*/
@NonNull
public UiSelector fromParent(@NonNull UiSelector selector) {
requireNonNull(selector, "selector cannot be null");
return buildSelector(SELECTOR_PARENT, selector);
}
/**
* Set the search criteria to match the package name
* of the application that contains the widget.
*
* @param name Value to match
* @return UiSelector with the specified search criteria
*/
@NonNull
public UiSelector packageName(@NonNull String name) {
requireNonNull(name, "name cannot be null");
return buildSelector(SELECTOR_PACKAGE_NAME, name);
}
/**
* Set the search criteria to match the package name
* of the application that contains the widget.
*
* @param regex a regular expression
* @return UiSelector with the specified search criteria
*/
@NonNull
public UiSelector packageNameMatches(@NonNull String regex) {
requireNonNull(regex, "regex cannot be null");
return buildSelector(SELECTOR_PACKAGE_NAME_REGEX, Pattern.compile(regex));
}
/**
* Building a UiSelector always returns a new UiSelector and never modifies the
* existing UiSelector being used.
*/
private UiSelector buildSelector(int selectorId, Object selectorValue) {
UiSelector selector = new UiSelector(this);
if (selectorId == SELECTOR_CHILD || selectorId == SELECTOR_PARENT)
selector.getLastSubSelector().mSelectorAttributes.put(selectorId, selectorValue);
else
selector.mSelectorAttributes.put(selectorId, selectorValue);
return selector;
}
/**
* Selectors may have a hierarchy defined by specifying child nodes to be matched.
* It is not necessary that every selector have more than one level. A selector
* can also be a single level referencing only one node. In such cases the return
* it null.
*
* @return a child selector if one exists. Else null if this selector does not
* reference child node.
*/
UiSelector getChildSelector() {
UiSelector selector = (UiSelector)mSelectorAttributes.get(UiSelector.SELECTOR_CHILD, null);
if (selector != null)
return new UiSelector(selector);
return null;
}
UiSelector getPatternSelector() {
UiSelector selector =
(UiSelector)mSelectorAttributes.get(UiSelector.SELECTOR_PATTERN, null);
if (selector != null)
return new UiSelector(selector);
return null;
}
UiSelector getContainerSelector() {
UiSelector selector =
(UiSelector)mSelectorAttributes.get(UiSelector.SELECTOR_CONTAINER, null);
if (selector != null)
return new UiSelector(selector);
return null;
}
UiSelector getParentSelector() {
UiSelector selector =
(UiSelector) mSelectorAttributes.get(UiSelector.SELECTOR_PARENT, null);
if (selector != null)
return new UiSelector(selector);
return null;
}
int getInstance() {
return getInt(UiSelector.SELECTOR_INSTANCE);
}
String getString(int criterion) {
return (String) mSelectorAttributes.get(criterion, null);
}
boolean getBoolean(int criterion) {
return (Boolean) mSelectorAttributes.get(criterion, false);
}
int getInt(int criterion) {
return (Integer) mSelectorAttributes.get(criterion, 0);
}
Pattern getPattern(int criterion) {
return (Pattern) mSelectorAttributes.get(criterion, null);
}
boolean isMatchFor(AccessibilityNodeInfo node, int index) {
int size = mSelectorAttributes.size();
for(int x = 0; x < size; x++) {
CharSequence s = null;
int criterion = mSelectorAttributes.keyAt(x);
switch(criterion) {
case UiSelector.SELECTOR_INDEX:
if (index != this.getInt(criterion))
return false;
break;
case UiSelector.SELECTOR_CHECKED:
if (node.isChecked() != getBoolean(criterion)) {
return false;
}
break;
case UiSelector.SELECTOR_CLASS:
s = node.getClassName();
if (s == null || !s.toString().contentEquals(getString(criterion))) {
return false;
}
break;
case UiSelector.SELECTOR_CLASS_REGEX:
s = node.getClassName();
if (s == null || !getPattern(criterion).matcher(s).matches()) {
return false;
}
break;
case UiSelector.SELECTOR_CLICKABLE:
if (node.isClickable() != getBoolean(criterion)) {
return false;
}
break;
case UiSelector.SELECTOR_CHECKABLE:
if (node.isCheckable() != getBoolean(criterion)) {
return false;
}
break;
case UiSelector.SELECTOR_LONG_CLICKABLE:
if (node.isLongClickable() != getBoolean(criterion)) {
return false;
}
break;
case UiSelector.SELECTOR_CONTAINS_DESCRIPTION:
s = node.getContentDescription();
if (s == null || !s.toString().toLowerCase()
.contains(getString(criterion).toLowerCase())) {
return false;
}
break;
case UiSelector.SELECTOR_START_DESCRIPTION:
s = node.getContentDescription();
if (s == null || !s.toString().toLowerCase()
.startsWith(getString(criterion).toLowerCase())) {
return false;
}
break;
case UiSelector.SELECTOR_DESCRIPTION:
s = node.getContentDescription();
if (s == null || !s.toString().contentEquals(getString(criterion))) {
return false;
}
break;
case UiSelector.SELECTOR_DESCRIPTION_REGEX:
s = node.getContentDescription();
if (s == null || !getPattern(criterion).matcher(s).matches()) {
return false;
}
break;
case UiSelector.SELECTOR_CONTAINS_TEXT:
s = node.getText();
if (s == null || !s.toString().toLowerCase()
.contains(getString(criterion).toLowerCase())) {
return false;
}
break;
case UiSelector.SELECTOR_START_TEXT:
s = node.getText();
if (s == null || !s.toString().toLowerCase()
.startsWith(getString(criterion).toLowerCase())) {
return false;
}
break;
case UiSelector.SELECTOR_TEXT:
s = node.getText();
if (s == null || !s.toString().contentEquals(getString(criterion))) {
return false;
}
break;
case UiSelector.SELECTOR_TEXT_REGEX:
s = node.getText();
if (s == null || !getPattern(criterion).matcher(s).matches()) {
return false;
}
break;
case UiSelector.SELECTOR_ENABLED:
if (node.isEnabled() != getBoolean(criterion)) {
return false;
}
break;
case UiSelector.SELECTOR_FOCUSABLE:
if (node.isFocusable() != getBoolean(criterion)) {
return false;
}
break;
case UiSelector.SELECTOR_FOCUSED:
if (node.isFocused() != getBoolean(criterion)) {
return false;
}
break;
case UiSelector.SELECTOR_ID:
break; //TODO: do we need this for AccessibilityNodeInfo.id?
case UiSelector.SELECTOR_PACKAGE_NAME:
s = node.getPackageName();
if (s == null || !s.toString().contentEquals(getString(criterion))) {
return false;
}
break;
case UiSelector.SELECTOR_PACKAGE_NAME_REGEX:
s = node.getPackageName();
if (s == null || !getPattern(criterion).matcher(s).matches()) {
return false;
}
break;
case UiSelector.SELECTOR_SCROLLABLE:
if (node.isScrollable() != getBoolean(criterion)) {
return false;
}
break;
case UiSelector.SELECTOR_SELECTED:
if (node.isSelected() != getBoolean(criterion)) {
return false;
}
break;
case UiSelector.SELECTOR_RESOURCE_ID:
s = node.getViewIdResourceName();
if (s == null || !s.toString().contentEquals(getString(criterion))) {
return false;
}
break;
case UiSelector.SELECTOR_RESOURCE_ID_REGEX:
s = node.getViewIdResourceName();
if (s == null || !getPattern(criterion).matcher(s).matches()) {
return false;
}
break;
}
}
return matchOrUpdateInstance();
}
private boolean matchOrUpdateInstance() {
int currentSelectorCounter = 0;
int currentSelectorInstance = 0;
// matched attributes - now check for matching instance number
if (mSelectorAttributes.indexOfKey(UiSelector.SELECTOR_INSTANCE) >= 0) {
currentSelectorInstance =
(Integer) mSelectorAttributes.get(UiSelector.SELECTOR_INSTANCE);
}
// instance is required. Add count if not already counting
if (mSelectorAttributes.indexOfKey(UiSelector.SELECTOR_COUNT) >= 0) {
currentSelectorCounter = (Integer) mSelectorAttributes.get(UiSelector.SELECTOR_COUNT);
}
// Verify
if (currentSelectorInstance == currentSelectorCounter) {
return true;
}
// Update count
if (currentSelectorInstance > currentSelectorCounter) {
mSelectorAttributes.put(UiSelector.SELECTOR_COUNT, ++currentSelectorCounter);
}
return false;
}
/**
* Leaf selector indicates no more child or parent selectors
* are declared in the this selector.
* @return true if is leaf.
*/
boolean isLeaf() {
return mSelectorAttributes.indexOfKey(UiSelector.SELECTOR_CHILD) < 0
&& mSelectorAttributes.indexOfKey(UiSelector.SELECTOR_PARENT) < 0;
}
boolean hasChildSelector() {
return mSelectorAttributes.indexOfKey(UiSelector.SELECTOR_CHILD) >= 0;
}
boolean hasPatternSelector() {
return mSelectorAttributes.indexOfKey(UiSelector.SELECTOR_PATTERN) >= 0;
}
boolean hasContainerSelector() {
return mSelectorAttributes.indexOfKey(UiSelector.SELECTOR_CONTAINER) >= 0;
}
boolean hasParentSelector() {
return mSelectorAttributes.indexOfKey(UiSelector.SELECTOR_PARENT) >= 0;
}
/**
* Returns the deepest selector in the chain of possible sub selectors.
* A chain of selector is created when either of {@link UiSelector#childSelector(UiSelector)}
* or {@link UiSelector#fromParent(UiSelector)} are used once or more in the construction of
* a selector.
* @return last UiSelector in chain
*/
private UiSelector getLastSubSelector() {
if (mSelectorAttributes.indexOfKey(UiSelector.SELECTOR_CHILD) >= 0) {
UiSelector child = (UiSelector)mSelectorAttributes.get(UiSelector.SELECTOR_CHILD);
if (child.getLastSubSelector() == null) {
return child;
}
return child.getLastSubSelector();
} else if (mSelectorAttributes.indexOfKey(UiSelector.SELECTOR_PARENT) >= 0) {
UiSelector parent = (UiSelector)mSelectorAttributes.get(UiSelector.SELECTOR_PARENT);
if (parent.getLastSubSelector() == null) {
return parent;
}
return parent.getLastSubSelector();
}
return this;
}
@Override
public String toString() {
return dumpToString(true);
}
String dumpToString(boolean all) {
StringBuilder builder = new StringBuilder();
builder.append(UiSelector.class.getSimpleName()).append("[");
final int criterionCount = mSelectorAttributes.size();
for (int i = 0; i < criterionCount; i++) {
if (i > 0) {
builder.append(", ");
}
final int criterion = mSelectorAttributes.keyAt(i);
switch (criterion) {
case SELECTOR_TEXT:
builder.append("TEXT=").append(mSelectorAttributes.valueAt(i));
break;
case SELECTOR_TEXT_REGEX:
builder.append("TEXT_REGEX=").append(mSelectorAttributes.valueAt(i));
break;
case SELECTOR_START_TEXT:
builder.append("START_TEXT=").append(mSelectorAttributes.valueAt(i));
break;
case SELECTOR_CONTAINS_TEXT:
builder.append("CONTAINS_TEXT=").append(mSelectorAttributes.valueAt(i));
break;
case SELECTOR_CLASS:
builder.append("CLASS=").append(mSelectorAttributes.valueAt(i));
break;
case SELECTOR_CLASS_REGEX:
builder.append("CLASS_REGEX=").append(mSelectorAttributes.valueAt(i));
break;
case SELECTOR_DESCRIPTION:
builder.append("DESCRIPTION=").append(mSelectorAttributes.valueAt(i));
break;
case SELECTOR_DESCRIPTION_REGEX:
builder.append("DESCRIPTION_REGEX=").append(mSelectorAttributes.valueAt(i));
break;
case SELECTOR_START_DESCRIPTION:
builder.append("START_DESCRIPTION=").append(mSelectorAttributes.valueAt(i));
break;
case SELECTOR_CONTAINS_DESCRIPTION:
builder.append("CONTAINS_DESCRIPTION=").append(mSelectorAttributes.valueAt(i));
break;
case SELECTOR_INDEX:
builder.append("INDEX=").append(mSelectorAttributes.valueAt(i));
break;
case SELECTOR_INSTANCE:
builder.append("INSTANCE=").append(mSelectorAttributes.valueAt(i));
break;
case SELECTOR_ENABLED:
builder.append("ENABLED=").append(mSelectorAttributes.valueAt(i));
break;
case SELECTOR_FOCUSED:
builder.append("FOCUSED=").append(mSelectorAttributes.valueAt(i));
break;
case SELECTOR_FOCUSABLE:
builder.append("FOCUSABLE=").append(mSelectorAttributes.valueAt(i));
break;
case SELECTOR_SCROLLABLE:
builder.append("SCROLLABLE=").append(mSelectorAttributes.valueAt(i));
break;
case SELECTOR_CLICKABLE:
builder.append("CLICKABLE=").append(mSelectorAttributes.valueAt(i));
break;
case SELECTOR_CHECKABLE:
builder.append("CHECKABLE=").append(mSelectorAttributes.valueAt(i));
break;
case SELECTOR_LONG_CLICKABLE:
builder.append("LONG_CLICKABLE=").append(mSelectorAttributes.valueAt(i));
break;
case SELECTOR_CHECKED:
builder.append("CHECKED=").append(mSelectorAttributes.valueAt(i));
break;
case SELECTOR_SELECTED:
builder.append("SELECTED=").append(mSelectorAttributes.valueAt(i));
break;
case SELECTOR_ID:
builder.append("ID=").append(mSelectorAttributes.valueAt(i));
break;
case SELECTOR_CHILD:
if (all) {
builder.append("CHILD=").append(mSelectorAttributes.valueAt(i));
} else {
builder.append("CHILD[..]");
}
break;
case SELECTOR_PATTERN:
if (all) {
builder.append("PATTERN=").append(mSelectorAttributes.valueAt(i));
} else {
builder.append("PATTERN[..]");
}
break;
case SELECTOR_CONTAINER:
if (all) {
builder.append("CONTAINER=").append(mSelectorAttributes.valueAt(i));
} else {
builder.append("CONTAINER[..]");
}
break;
case SELECTOR_PARENT:
if (all) {
builder.append("PARENT=").append(mSelectorAttributes.valueAt(i));
} else {
builder.append("PARENT[..]");
}
break;
case SELECTOR_COUNT:
builder.append("COUNT=").append(mSelectorAttributes.valueAt(i));
break;
case SELECTOR_PACKAGE_NAME:
builder.append("PACKAGE_NAME=").append(mSelectorAttributes.valueAt(i));
break;
case SELECTOR_PACKAGE_NAME_REGEX:
builder.append("PACKAGE_NAME_REGEX=").append(mSelectorAttributes.valueAt(i));
break;
case SELECTOR_RESOURCE_ID:
builder.append("RESOURCE_ID=").append(mSelectorAttributes.valueAt(i));
break;
case SELECTOR_RESOURCE_ID_REGEX:
builder.append("RESOURCE_ID_REGEX=").append(mSelectorAttributes.valueAt(i));
break;
default:
builder.append("UNDEFINED=").append(criterion).append(" ").append(
mSelectorAttributes.valueAt(i));
}
}
builder.append("]");
return builder.toString();
}
}