aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore7
-rw-r--r--Android.mk16
-rw-r--r--build.gradle9
-rw-r--r--contributing.md9
-rw-r--r--contributing_aosp.md20
-rw-r--r--droiddriver-android_support_test/Android.mk19
-rw-r--r--droiddriver-android_support_test/build.gradle14
-rw-r--r--gradle/wrapper/gradle-wrapper.jarbin0 -> 51018 bytes
-rw-r--r--gradle/wrapper/gradle-wrapper.properties6
-rwxr-xr-xgradlew164
-rw-r--r--gradlew.bat90
-rw-r--r--manualtest/Android.mk17
-rw-r--r--manualtest/build.gradle15
-rw-r--r--manualtest/src/io/appium/droiddriver/manualtest/ManualTest.java4
-rw-r--r--src/io/appium/droiddriver/base/AbstractDroidDriver.java86
-rw-r--r--src/io/appium/droiddriver/base/BaseDroidDriver.java61
-rw-r--r--src/io/appium/droiddriver/base/CompositeDroidDriver.java59
-rw-r--r--src/io/appium/droiddriver/duo/DuoDriver.java57
-rw-r--r--src/io/appium/droiddriver/finders/Attribute.java2
-rw-r--r--src/io/appium/droiddriver/finders/By.java4
-rw-r--r--src/io/appium/droiddriver/finders/Predicates.java2
-rw-r--r--src/io/appium/droiddriver/helpers/DroidDrivers.java4
-rw-r--r--src/io/appium/droiddriver/helpers/SingleRun.java2
-rw-r--r--src/io/appium/droiddriver/instrumentation/ViewElement.java4
-rw-r--r--src/io/appium/droiddriver/runner/MinSdkVersion.java6
-rw-r--r--src/io/appium/droiddriver/runner/UseUiAutomation.java6
-rw-r--r--src/io/appium/droiddriver/scroll/DynamicSentinelStrategy.java2
-rw-r--r--src/io/appium/droiddriver/scroll/StepBasedScroller.java4
-rw-r--r--src/io/appium/droiddriver/uiautomation/UiAutomationElement.java18
-rw-r--r--src/io/appium/droiddriver/validators/DefaultAccessibilityValidator.java10
30 files changed, 520 insertions, 197 deletions
diff --git a/.gitignore b/.gitignore
index 3d0ebbd..93237bf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,17 +3,14 @@ gen/
# gradle junk
.gradle
-gradle/
-gradlew
-gradlew.bat
build
# Android Studio junk
.idea/
*.iml
-# Don't check in properties
-*.properties
+# Don't check in local.properties
+local.properties
.DS_Store
diff --git a/Android.mk b/Android.mk
deleted file mode 100644
index 2a752d6..0000000
--- a/Android.mk
+++ /dev/null
@@ -1,16 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_MODULE := droiddriver
-LOCAL_MODULE_TAGS := optional
-LOCAL_SDK_VERSION := 19
-
-LOCAL_JAVACFLAGS += -Xlint:deprecation -Xlint:unchecked
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-include $(CLEAR_VARS)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/build.gradle b/build.gradle
index 3af6346..cbf12f1 100644
--- a/build.gradle
+++ b/build.gradle
@@ -2,7 +2,6 @@
// sdk.dir for the Android SDK path, you can run
// $ ANDROID_HOME=/path/to/android-sdk gradle build
-// Gradle >= 2.4 required
buildscript {
ext.bintrayUser = project.hasProperty('bintrayUser') ? project.bintrayUser : System.getenv('BINTRAY_USER')
ext.bintrayKey = project.hasProperty('bintrayKey') ? project.bintrayKey : System.getenv('BINTRAY_KEY')
@@ -12,7 +11,7 @@ buildscript {
jcenter()
}
dependencies {
- classpath 'com.android.tools.build:gradle:1.0.1'
+ classpath 'com.android.tools.build:gradle:1.3.0'
classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3'
classpath 'com.jakewharton.sdkmanager:gradle-plugin:0.12.0'
if (bintrayEnabled) {
@@ -30,16 +29,16 @@ apply plugin: 'android-sdk-manager'
apply plugin: 'com.android.library'
tasks.withType(JavaCompile) {
- options.compilerArgs << '-Xlint:deprecation'
+ options.compilerArgs << '-Xlint:deprecation' << '-Xlint:unchecked'
}
android {
- compileSdkVersion 21
+ compileSdkVersion 23
buildToolsVersion '21.1.2'
defaultConfig {
minSdkVersion 8
- targetSdkVersion 21
+ targetSdkVersion 23
versionCode 1
versionName version
}
diff --git a/contributing.md b/contributing.md
index f8ae829..645ef1b 100644
--- a/contributing.md
+++ b/contributing.md
@@ -6,18 +6,13 @@ The [`master` branch](https://github.com/appium/droiddriver/tree/master) on GitH
Code changes should be [submitted to AOSP](contributing_aosp.md) and then they'll be synced to GitHub once they've passed code reivew on Gerrit.
-#### Requirements
+#### Build
-Gradle 2.2.1 or better is required to be installed on the system. In Android Studio, you'll need to provide the gradle location.
-
-On Mac OSX with homebrew, `brew install gradle` will install gradle. To locate the path, use `brew info gradle` The homebrew path follows this format: `/usr/local/Cellar/gradle/2.2.1/libexec`
-
-If you installed gradle using the zip (`gradle-2.2.1-bin.zip`), then the path will be the `gradle-2.2.1` folder.
+`./gradlew build`
#### Import into Android Studio
- Clone from git
- Launch Android Studio and select `Open an existing Android Studio project`
- Navigate to `droiddriver/build.gradle` and press Choose
-- Select `Use local gradle distribution` and enter the Gradle path
- Android Studio will now import the project successfully
diff --git a/contributing_aosp.md b/contributing_aosp.md
index c57a0d1..58bca60 100644
--- a/contributing_aosp.md
+++ b/contributing_aosp.md
@@ -16,9 +16,12 @@ $ repo sync
```
The code should be downloaded to the current dir. You may see some lines in the output like:
-curl: (22) The requested URL returned error: 401 Unauthorized
+
+`curl: (22) The requested URL returned error: 401 Unauthorized`
+
These messages seem non-fatal and you should see these dirs after it is done:
-build/ external/ frameworks/ Makefile prebuilts/
+
+`build/ external/ frameworks/ Makefile prebuilts/`
#### Submitting Patches
@@ -51,16 +54,3 @@ When commenting on the code, posts will show up as drafts. Drafts are not visibl
- `repo upload`
The [`repo prune`](https://source.android.com/source/using-repo.html) command can be used to delete already merged branches.
-
-#### Building
-
-This sets up environment and some bash functions, particularly "tapas"
-(the counterpart of "lunch" for unbundled projects) and "m".
-
-```bash
-$ . build/envsetup.sh
-$ tapas droiddriver ManualDD
-$ m
-```
-
-ManualDD is an APK you can use to manually test DroidDriver.
diff --git a/droiddriver-android_support_test/Android.mk b/droiddriver-android_support_test/Android.mk
deleted file mode 100644
index 22c6c0a..0000000
--- a/droiddriver-android_support_test/Android.mk
+++ /dev/null
@@ -1,19 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_MODULE := droiddriver-android_support_test
-LOCAL_MODULE_TAGS := optional
-LOCAL_SDK_VERSION := 19
-
-LOCAL_JAVACFLAGS += -Xlint:deprecation -Xlint:unchecked
-
-# android-support-test requires /frameworks/testing, /external/junit, /external/hamcrest
-LOCAL_JAVA_LIBRARIES := droiddriver android-support-test
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
-
-include $(CLEAR_VARS)
-
-include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/droiddriver-android_support_test/build.gradle b/droiddriver-android_support_test/build.gradle
index 3f6120f..9d71de2 100644
--- a/droiddriver-android_support_test/build.gradle
+++ b/droiddriver-android_support_test/build.gradle
@@ -3,8 +3,7 @@ buildscript {
jcenter()
}
dependencies {
- // this requires Gradle 2
- classpath 'com.android.tools.build:gradle:1.0.1'
+ classpath 'com.android.tools.build:gradle:1.3.0'
classpath 'com.jakewharton.sdkmanager:gradle-plugin:0.12.0'
}
}
@@ -27,24 +26,23 @@ dependencies {
// For development only.
compile 'io.appium:droiddriver:1.0.0-SNAPSHOT'
} else {
- // This is broken now b/c droiddriver-1.0.0 is not published yet
- compile 'io.appium:droiddriver:1.0.0'
+ compile 'io.appium:droiddriver:1.0.0-BETA1'
}
- compile 'com.android.support.test:testing-support-lib:0.1'
+ compile 'com.android.support.test:runner:0.4.1'
}
tasks.withType(JavaCompile) {
- options.compilerArgs << '-Xlint:deprecation'
+ options.compilerArgs << '-Xlint:deprecation' << '-Xlint:unchecked'
}
android {
- compileSdkVersion 21
+ compileSdkVersion 23
buildToolsVersion '21.1.2'
defaultConfig {
minSdkVersion 8
- targetSdkVersion 21
+ targetSdkVersion 23
versionCode 1
}
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..c97a8bd
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..80b332a
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Mon Mar 14 09:50:19 PDT 2016
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.8-all.zip
diff --git a/gradlew b/gradlew
new file mode 100755
index 0000000..91a7e26
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,164 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched.
+if $cygwin ; then
+ [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+fi
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >&-
+APP_HOME="`pwd -P`"
+cd "$SAVED" >&-
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000..aec9973
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/manualtest/Android.mk b/manualtest/Android.mk
deleted file mode 100644
index 6b52b73..0000000
--- a/manualtest/Android.mk
+++ /dev/null
@@ -1,17 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-include $(CLEAR_VARS)
-LOCAL_PACKAGE_NAME := ManualDD
-
-LOCAL_MODULE_TAGS := optional
-LOCAL_PROGUARD_ENABLED := disabled
-
-LOCAL_SRC_FILES := \
- $(call all-java-files-under, src)
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
- droiddriver
-
-LOCAL_SDK_VERSION := 19
-
-include $(BUILD_PACKAGE)
-
diff --git a/manualtest/build.gradle b/manualtest/build.gradle
index a732fe3..5be41b8 100644
--- a/manualtest/build.gradle
+++ b/manualtest/build.gradle
@@ -3,8 +3,7 @@ buildscript {
jcenter()
}
dependencies {
- // this requires Gradle 2
- classpath 'com.android.tools.build:gradle:1.0.1'
+ classpath 'com.android.tools.build:gradle:1.3.0'
}
}
@@ -12,17 +11,13 @@ buildscript {
apply plugin: 'com.android.application'
android {
- compileSdkVersion 21
+ compileSdkVersion 23
buildToolsVersion '21.1.2'
-
defaultConfig {
minSdkVersion 8
- targetSdkVersion 21
- // Force remove the suffix '.test'
- testApplicationId 'io.appium.droiddriver.manualtest'
+ targetSdkVersion 23
testInstrumentationRunner 'io.appium.droiddriver.runner.TestRunner'
}
-
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
@@ -31,6 +26,8 @@ android {
java.srcDirs = ['src']
}
}
+ productFlavors {
+ }
}
// Building with droiddriver source. Common tests should use droiddriver from jcenter by having
@@ -39,7 +36,7 @@ android {
// jcenter()
// }
// dependencies {
-// androidTestCompile 'io.appium:droiddriver:0.9.1-BETA' // or another version
+// androidTestCompile 'io.appium:droiddriver:1.0.0-BETA1' // or another version
// }
dependencies {
androidTestCompile project(':droiddriver')
diff --git a/manualtest/src/io/appium/droiddriver/manualtest/ManualTest.java b/manualtest/src/io/appium/droiddriver/manualtest/ManualTest.java
index 83966f7..59beac4 100644
--- a/manualtest/src/io/appium/droiddriver/manualtest/ManualTest.java
+++ b/manualtest/src/io/appium/droiddriver/manualtest/ManualTest.java
@@ -16,10 +16,10 @@ import io.appium.droiddriver.uiautomation.UiAutomationDriver;
* {@link #testSetTextForPassword} assumes the password_edit field is displayed
* on screen.
* <p>
- * Run it as (optionally with -e debug true)
+ * Run it with
*
* <pre>
- * adb shell am instrument -w io.appium.droiddriver.manualtest/io.appium.droiddriver.runner.TestRunner
+ * ../gradlew :connectedAndroidTest
* </pre>
*/
public class ManualTest extends BaseDroidDriverTest<Activity> {
diff --git a/src/io/appium/droiddriver/base/AbstractDroidDriver.java b/src/io/appium/droiddriver/base/AbstractDroidDriver.java
new file mode 100644
index 0000000..bf0df4b
--- /dev/null
+++ b/src/io/appium/droiddriver/base/AbstractDroidDriver.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2016 DroidDriver committers
+ *
+ * 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 io.appium.droiddriver.base;
+
+import io.appium.droiddriver.DroidDriver;
+import io.appium.droiddriver.Poller;
+import io.appium.droiddriver.UiElement;
+import io.appium.droiddriver.actions.InputInjector;
+import io.appium.droiddriver.exceptions.ElementNotFoundException;
+import io.appium.droiddriver.exceptions.TimeoutException;
+import io.appium.droiddriver.finders.Finder;
+import io.appium.droiddriver.util.Logs;
+
+/**
+ * Base DroidDriver that implements the common operations.
+ */
+public abstract class AbstractDroidDriver implements DroidDriver {
+
+ private Poller poller = new DefaultPoller();
+
+ @Override
+ public boolean has(Finder finder) {
+ try {
+ refreshUiElementTree();
+ find(finder);
+ return true;
+ } catch (ElementNotFoundException enfe) {
+ return false;
+ }
+ }
+
+ @Override
+ public boolean has(Finder finder, long timeoutMillis) {
+ try {
+ getPoller().pollFor(this, finder, Poller.EXISTS, timeoutMillis);
+ return true;
+ } catch (TimeoutException e) {
+ return false;
+ }
+ }
+
+ @Override
+ public UiElement on(Finder finder) {
+ Logs.call(this, "on", finder);
+ return getPoller().pollFor(this, finder, Poller.EXISTS);
+ }
+
+ @Override
+ public void checkExists(Finder finder) {
+ Logs.call(this, "checkExists", finder);
+ getPoller().pollFor(this, finder, Poller.EXISTS);
+ }
+
+ @Override
+ public void checkGone(Finder finder) {
+ Logs.call(this, "checkGone", finder);
+ getPoller().pollFor(this, finder, Poller.GONE);
+ }
+
+ @Override
+ public Poller getPoller() {
+ return poller;
+ }
+
+ @Override
+ public void setPoller(Poller poller) {
+ this.poller = poller;
+ }
+
+ public abstract InputInjector getInjector();
+
+} \ No newline at end of file
diff --git a/src/io/appium/droiddriver/base/BaseDroidDriver.java b/src/io/appium/droiddriver/base/BaseDroidDriver.java
index e985a38..d6114c6 100644
--- a/src/io/appium/droiddriver/base/BaseDroidDriver.java
+++ b/src/io/appium/droiddriver/base/BaseDroidDriver.java
@@ -18,22 +18,16 @@ package io.appium.droiddriver.base;
import android.util.Log;
-import io.appium.droiddriver.DroidDriver;
-import io.appium.droiddriver.Poller;
import io.appium.droiddriver.UiElement;
-import io.appium.droiddriver.actions.InputInjector;
-import io.appium.droiddriver.exceptions.ElementNotFoundException;
-import io.appium.droiddriver.exceptions.TimeoutException;
import io.appium.droiddriver.finders.ByXPath;
import io.appium.droiddriver.finders.Finder;
import io.appium.droiddriver.util.Logs;
/**
- * Base DroidDriver that implements the common operations.
+ * Enhances AbstractDroidDriver to include basic element handling and matching operations.
*/
-public abstract class BaseDroidDriver<R, E extends BaseUiElement<R, E>> implements DroidDriver {
+public abstract class BaseDroidDriver<R, E extends BaseUiElement<R, E>> extends AbstractDroidDriver {
- private Poller poller = new DefaultPoller();
private E rootElement;
@Override
@@ -42,57 +36,6 @@ public abstract class BaseDroidDriver<R, E extends BaseUiElement<R, E>> implemen
return finder.find(getRootElement());
}
- @Override
- public boolean has(Finder finder) {
- try {
- refreshUiElementTree();
- find(finder);
- return true;
- } catch (ElementNotFoundException enfe) {
- return false;
- }
- }
-
- @Override
- public boolean has(Finder finder, long timeoutMillis) {
- try {
- getPoller().pollFor(this, finder, Poller.EXISTS, timeoutMillis);
- return true;
- } catch (TimeoutException e) {
- return false;
- }
- }
-
- @Override
- public UiElement on(Finder finder) {
- Logs.call(this, "on", finder);
- return getPoller().pollFor(this, finder, Poller.EXISTS);
- }
-
- @Override
- public void checkExists(Finder finder) {
- Logs.call(this, "checkExists", finder);
- getPoller().pollFor(this, finder, Poller.EXISTS);
- }
-
- @Override
- public void checkGone(Finder finder) {
- Logs.call(this, "checkGone", finder);
- getPoller().pollFor(this, finder, Poller.GONE);
- }
-
- @Override
- public Poller getPoller() {
- return poller;
- }
-
- @Override
- public void setPoller(Poller poller) {
- this.poller = poller;
- }
-
- public abstract InputInjector getInjector();
-
protected abstract E newRootElement();
/**
diff --git a/src/io/appium/droiddriver/base/CompositeDroidDriver.java b/src/io/appium/droiddriver/base/CompositeDroidDriver.java
new file mode 100644
index 0000000..c92c5c3
--- /dev/null
+++ b/src/io/appium/droiddriver/base/CompositeDroidDriver.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2016 DroidDriver committers
+ *
+ * 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 io.appium.droiddriver.base;
+
+import io.appium.droiddriver.UiDevice;
+import io.appium.droiddriver.UiElement;
+import io.appium.droiddriver.actions.InputInjector;
+import io.appium.droiddriver.finders.Finder;
+
+/**
+ * Helper class to ease creation of drivers that defer actions to other drivers.
+ */
+public abstract class CompositeDroidDriver extends AbstractDroidDriver {
+ /**
+ * Determines which DroidDriver should handle the current situation.
+ *
+ * @return The DroidDriver instance to use
+ */
+ protected abstract AbstractDroidDriver getApplicableDriver();
+
+ @Override
+ public InputInjector getInjector() {
+ return getApplicableDriver().getInjector();
+ }
+
+ @Override
+ public UiDevice getUiDevice() {
+ return getApplicableDriver().getUiDevice();
+ }
+
+ @Override
+ public UiElement find(Finder finder) {
+ return getApplicableDriver().find(finder);
+ }
+
+ @Override
+ public void refreshUiElementTree() {
+ getApplicableDriver().refreshUiElementTree();
+ }
+
+ @Override
+ public boolean dumpUiElementTree(String path) {
+ return getApplicableDriver().dumpUiElementTree(path);
+ }
+}
diff --git a/src/io/appium/droiddriver/duo/DuoDriver.java b/src/io/appium/droiddriver/duo/DuoDriver.java
new file mode 100644
index 0000000..0ad84bf
--- /dev/null
+++ b/src/io/appium/droiddriver/duo/DuoDriver.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2016 DroidDriver committers
+ *
+ * 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 io.appium.droiddriver.duo;
+
+import android.annotation.TargetApi;
+import android.app.Activity;
+import android.app.Instrumentation;
+
+import io.appium.droiddriver.base.AbstractDroidDriver;
+import io.appium.droiddriver.base.CompositeDroidDriver;
+import io.appium.droiddriver.instrumentation.InstrumentationDriver;
+import io.appium.droiddriver.uiautomation.UiAutomationDriver;
+import io.appium.droiddriver.util.ActivityUtils;
+import io.appium.droiddriver.util.InstrumentationUtils;
+
+/**
+ * Implementation of DroidDriver that attempts to use the best driver for the current activity.
+ * If the activity is part of the application under instrumentation, the InstrumentationDriver is
+ * used. Otherwise, the UiAutomationDriver is used.
+ */
+@TargetApi(18)
+public class DuoDriver extends CompositeDroidDriver {
+ private final String targetApkPackage;
+ private final UiAutomationDriver uiAutomationDriver;
+ private final InstrumentationDriver instrumentationDriver;
+
+ public DuoDriver() {
+ Instrumentation instrumentation = InstrumentationUtils.getInstrumentation();
+ targetApkPackage = InstrumentationUtils.getTargetContext().getPackageName();
+ uiAutomationDriver = new UiAutomationDriver(instrumentation);
+ instrumentationDriver = new InstrumentationDriver(instrumentation);
+ }
+
+ @Override
+ protected AbstractDroidDriver getApplicableDriver() {
+ Activity activity = ActivityUtils.getRunningActivity();
+ if (activity != null && targetApkPackage.equals(
+ activity.getApplicationContext().getPackageName())) {
+ return instrumentationDriver;
+ }
+ return uiAutomationDriver;
+ }
+}
diff --git a/src/io/appium/droiddriver/finders/Attribute.java b/src/io/appium/droiddriver/finders/Attribute.java
index 9dda497..c2aa83a 100644
--- a/src/io/appium/droiddriver/finders/Attribute.java
+++ b/src/io/appium/droiddriver/finders/Attribute.java
@@ -38,7 +38,7 @@ public enum Attribute {
private final String name;
- private Attribute(String name) {
+ Attribute(String name) {
this.name = name;
}
diff --git a/src/io/appium/droiddriver/finders/By.java b/src/io/appium/droiddriver/finders/By.java
index 0b6a57f..9a38622 100644
--- a/src/io/appium/droiddriver/finders/By.java
+++ b/src/io/appium/droiddriver/finders/By.java
@@ -16,6 +16,8 @@
package io.appium.droiddriver.finders;
+import static io.appium.droiddriver.util.Preconditions.checkNotNull;
+
import android.content.Context;
import java.util.ArrayList;
@@ -25,8 +27,6 @@ import io.appium.droiddriver.UiElement;
import io.appium.droiddriver.exceptions.ElementNotFoundException;
import io.appium.droiddriver.util.InstrumentationUtils;
-import static io.appium.droiddriver.util.Preconditions.checkNotNull;
-
/**
* Convenience methods to create commonly used finders.
*/
diff --git a/src/io/appium/droiddriver/finders/Predicates.java b/src/io/appium/droiddriver/finders/Predicates.java
index f32b365..0d2d9df 100644
--- a/src/io/appium/droiddriver/finders/Predicates.java
+++ b/src/io/appium/droiddriver/finders/Predicates.java
@@ -124,6 +124,7 @@ public final class Predicates {
* {@code true}. The components are evaluated in order, and evaluation will be "short-circuited"
* as soon as a false predicate is found.
*/
+ @SuppressWarnings("RedundantTypeArguments") // Some compilers cannot infer <T>
@SafeVarargs
public static <T> Predicate<T> allOf(final Predicate<? super T>... components) {
return Predicates.<T>allOf(Arrays.asList(components));
@@ -158,6 +159,7 @@ public final class Predicates {
* {@code true}. The components are evaluated in order, and evaluation will be "short-circuited"
* as soon as a true predicate is found.
*/
+ @SuppressWarnings("RedundantTypeArguments") // Some compilers cannot infer <T>
@SafeVarargs
public static <T> Predicate<T> anyOf(final Predicate<? super T>... components) {
return Predicates.<T>anyOf(Arrays.asList(components));
diff --git a/src/io/appium/droiddriver/helpers/DroidDrivers.java b/src/io/appium/droiddriver/helpers/DroidDrivers.java
index 7725bf5..e55d595 100644
--- a/src/io/appium/droiddriver/helpers/DroidDrivers.java
+++ b/src/io/appium/droiddriver/helpers/DroidDrivers.java
@@ -21,9 +21,9 @@ import android.app.Instrumentation;
import android.os.Build;
import io.appium.droiddriver.DroidDriver;
+import io.appium.droiddriver.duo.DuoDriver;
import io.appium.droiddriver.exceptions.DroidDriverException;
import io.appium.droiddriver.instrumentation.InstrumentationDriver;
-import io.appium.droiddriver.uiautomation.UiAutomationDriver;
import io.appium.droiddriver.util.InstrumentationUtils;
/**
@@ -83,7 +83,7 @@ public class DroidDrivers {
// If "dd.driver" is not specified, return default.
if (hasUiAutomation()) {
checkUiAutomation();
- return new UiAutomationDriver(instrumentation);
+ return new DuoDriver();
}
return new InstrumentationDriver(instrumentation);
}
diff --git a/src/io/appium/droiddriver/helpers/SingleRun.java b/src/io/appium/droiddriver/helpers/SingleRun.java
index 5ffd21e..714c777 100644
--- a/src/io/appium/droiddriver/helpers/SingleRun.java
+++ b/src/io/appium/droiddriver/helpers/SingleRun.java
@@ -24,7 +24,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
* a class effect.
*/
public abstract class SingleRun {
- private AtomicBoolean hasRun = new AtomicBoolean();
+ private final AtomicBoolean hasRun = new AtomicBoolean();
/**
* Calls {@link #run()} if it is the first time this method is called upon this instance.
diff --git a/src/io/appium/droiddriver/instrumentation/ViewElement.java b/src/io/appium/droiddriver/instrumentation/ViewElement.java
index e706362..ab87817 100644
--- a/src/io/appium/droiddriver/instrumentation/ViewElement.java
+++ b/src/io/appium/droiddriver/instrumentation/ViewElement.java
@@ -16,6 +16,8 @@
package io.appium.droiddriver.instrumentation;
+import static io.appium.droiddriver.util.Strings.charSequenceToString;
+
import android.content.res.Resources;
import android.graphics.Rect;
import android.view.View;
@@ -40,8 +42,6 @@ import io.appium.droiddriver.finders.Attribute;
import io.appium.droiddriver.util.InstrumentationUtils;
import io.appium.droiddriver.util.Preconditions;
-import static io.appium.droiddriver.util.Strings.charSequenceToString;
-
/**
* A UiElement that is backed by a View.
*/
diff --git a/src/io/appium/droiddriver/runner/MinSdkVersion.java b/src/io/appium/droiddriver/runner/MinSdkVersion.java
index c1ea2e9..a05b3fc 100644
--- a/src/io/appium/droiddriver/runner/MinSdkVersion.java
+++ b/src/io/appium/droiddriver/runner/MinSdkVersion.java
@@ -16,14 +16,14 @@
package io.appium.droiddriver.runner;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.ElementType.TYPE;
-
/**
* This annotation indicates that its target needs a minimum SDK version
* specified as its value.
diff --git a/src/io/appium/droiddriver/runner/UseUiAutomation.java b/src/io/appium/droiddriver/runner/UseUiAutomation.java
index 316ac8f..66ef880 100644
--- a/src/io/appium/droiddriver/runner/UseUiAutomation.java
+++ b/src/io/appium/droiddriver/runner/UseUiAutomation.java
@@ -16,14 +16,14 @@
package io.appium.droiddriver.runner;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
-import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.ElementType.TYPE;
-
/**
* This annotation indicates that its target needs
* {@link android.app.UiAutomation}. It is effectively equivalent to
diff --git a/src/io/appium/droiddriver/scroll/DynamicSentinelStrategy.java b/src/io/appium/droiddriver/scroll/DynamicSentinelStrategy.java
index 051cfa7..b42b60d 100644
--- a/src/io/appium/droiddriver/scroll/DynamicSentinelStrategy.java
+++ b/src/io/appium/droiddriver/scroll/DynamicSentinelStrategy.java
@@ -39,7 +39,7 @@ public class DynamicSentinelStrategy extends SentinelStrategy {
/**
* Interface for determining whether sentinel is updated.
*/
- public static interface IsUpdatedStrategy {
+ public interface IsUpdatedStrategy {
/**
* Returns whether {@code newSentinel} is updated from {@code oldSentinel}.
*/
diff --git a/src/io/appium/droiddriver/scroll/StepBasedScroller.java b/src/io/appium/droiddriver/scroll/StepBasedScroller.java
index 6dbc79e..11c42f4 100644
--- a/src/io/appium/droiddriver/scroll/StepBasedScroller.java
+++ b/src/io/appium/droiddriver/scroll/StepBasedScroller.java
@@ -15,6 +15,8 @@
*/
package io.appium.droiddriver.scroll;
+import static io.appium.droiddriver.scroll.Direction.LogicalDirection.BACKWARD;
+
import android.util.Log;
import io.appium.droiddriver.DroidDriver;
@@ -29,8 +31,6 @@ import io.appium.droiddriver.scroll.Direction.DirectionConverter;
import io.appium.droiddriver.scroll.Direction.PhysicalDirection;
import io.appium.droiddriver.util.Logs;
-import static io.appium.droiddriver.scroll.Direction.LogicalDirection.BACKWARD;
-
/**
* A {@link Scroller} that looks for the desired item in the currently shown
* content of the scrollable container, otherwise scrolls the container one step
diff --git a/src/io/appium/droiddriver/uiautomation/UiAutomationElement.java b/src/io/appium/droiddriver/uiautomation/UiAutomationElement.java
index c011749..5b99131 100644
--- a/src/io/appium/droiddriver/uiautomation/UiAutomationElement.java
+++ b/src/io/appium/droiddriver/uiautomation/UiAutomationElement.java
@@ -16,6 +16,8 @@
package io.appium.droiddriver.uiautomation;
+import static io.appium.droiddriver.util.Strings.charSequenceToString;
+
import android.annotation.TargetApi;
import android.app.UiAutomation;
import android.app.UiAutomation.AccessibilityEventFilter;
@@ -37,8 +39,6 @@ import io.appium.droiddriver.finders.Attribute;
import io.appium.droiddriver.uiautomation.UiAutomationContext.UiAutomationCallable;
import io.appium.droiddriver.util.Preconditions;
-import static io.appium.droiddriver.util.Strings.charSequenceToString;
-
/**
* A UiElement that gets attributes via the Accessibility API.
*/
@@ -96,9 +96,9 @@ public class UiAutomationElement extends BaseUiElement<AccessibilityNodeInfo, Ui
put(attribs, Attribute.BOUNDS, getBounds(node));
attributes = Collections.unmodifiableMap(attribs);
- // Order matters as getVisibleBounds depends on visible
+ // Order matters as findVisibleBounds depends on visible
visible = node.isVisibleToUser();
- visibleBounds = getVisibleBounds(node);
+ visibleBounds = findVisibleBounds();
List<UiAutomationElement> mutableChildren = buildChildren(node);
this.children = mutableChildren == null ? null : Collections.unmodifiableList(mutableChildren);
}
@@ -132,21 +132,19 @@ public class UiAutomationElement extends BaseUiElement<AccessibilityNodeInfo, Ui
return rect;
}
- private Rect getVisibleBounds(AccessibilityNodeInfo node) {
+ private Rect findVisibleBounds() {
if (!visible) {
return new Rect();
}
- Rect visibleBounds = getBounds();
+ Rect foundBounds = getBounds();
UiAutomationElement parent = getParent();
- Rect parentBounds;
while (parent != null) {
- parentBounds = parent.getBounds();
- if (!visibleBounds.intersect(parentBounds)) {
+ if (!foundBounds.intersect(parent.getBounds())) {
return new Rect();
}
parent = parent.getParent();
}
- return visibleBounds;
+ return foundBounds;
}
@Override
diff --git a/src/io/appium/droiddriver/validators/DefaultAccessibilityValidator.java b/src/io/appium/droiddriver/validators/DefaultAccessibilityValidator.java
index 1ce3649..b78d0a5 100644
--- a/src/io/appium/droiddriver/validators/DefaultAccessibilityValidator.java
+++ b/src/io/appium/droiddriver/validators/DefaultAccessibilityValidator.java
@@ -41,14 +41,8 @@ public class DefaultAccessibilityValidator implements Validator {
// Logic from TalkBack
private static boolean isAccessibilityFocusable(UiElement element) {
- if (isActionableForAccessibility(element)) {
- return true;
- }
-
- if (isTopLevelScrollItem(element) && (isSpeakingNode(element))) {
- return true;
- }
- return false;
+ return isActionableForAccessibility(element)
+ || (isTopLevelScrollItem(element) && isSpeakingNode(element));
}
private static boolean isTopLevelScrollItem(UiElement element) {