();
+ ofNullable(this.keyCode).ifPresentOrElse(x -> map.put("keycode", x), () -> {
+ throw new IllegalStateException("The key code must be set");
+ });
+ ofNullable(this.metaState).ifPresent(x -> map.put("metastate", x));
+ ofNullable(this.flags).ifPresent(x -> map.put("flags", x));
+ return Collections.unmodifiableMap(map);
}
}
diff --git a/src/main/java/io/appium/java_client/android/nativekey/KeyEventMetaModifier.java b/src/main/java/io/appium/java_client/android/nativekey/KeyEventMetaModifier.java
index e4f998b99..b32de52bc 100644
--- a/src/main/java/io/appium/java_client/android/nativekey/KeyEventMetaModifier.java
+++ b/src/main/java/io/appium/java_client/android/nativekey/KeyEventMetaModifier.java
@@ -23,103 +23,103 @@ public enum KeyEventMetaModifier {
*/
SELECTING(0x800),
/**
- * This mask is used to check whether one of the ALT meta keys is pressed.
+ * This mask is used to check whether one of the ALT meta keys is pressed.
*
* @see AndroidKey#ALT_LEFT
* @see AndroidKey#ALT_RIGHT
*/
ALT_ON(0x02),
/**
- * This mask is used to check whether the left ALT meta key is pressed.
+ * This mask is used to check whether the left ALT meta key is pressed.
*
* @see AndroidKey#ALT_LEFT
*/
ALT_LEFT_ON(0x10),
/**
- * This mask is used to check whether the right the ALT meta key is pressed.
+ * This mask is used to check whether the right the ALT meta key is pressed.
*
* @see AndroidKey#ALT_RIGHT
*/
ALT_RIGHT_ON(0x20),
/**
- * This mask is used to check whether one of the SHIFT meta keys is pressed.
+ * This mask is used to check whether one of the SHIFT meta keys is pressed.
*
* @see AndroidKey#SHIFT_LEFT
* @see AndroidKey#SHIFT_RIGHT
*/
SHIFT_ON(0x1),
/**
- * This mask is used to check whether the left SHIFT meta key is pressed.
+ * This mask is used to check whether the left SHIFT meta key is pressed.
*
* @see AndroidKey#SHIFT_LEFT
*/
SHIFT_LEFT_ON(0x40),
/**
- * This mask is used to check whether the right SHIFT meta key is pressed.
+ * This mask is used to check whether the right SHIFT meta key is pressed.
*
* @see AndroidKey#SHIFT_RIGHT
*/
SHIFT_RIGHT_ON(0x80),
/**
- * This mask is used to check whether the SYM meta key is pressed.
+ * This mask is used to check whether the SYM meta key is pressed.
*/
SYM_ON(0x4),
/**
- * This mask is used to check whether the FUNCTION meta key is pressed.
+ * This mask is used to check whether the FUNCTION meta key is pressed.
*/
FUNCTION_ON(0x8),
/**
- * This mask is used to check whether one of the CTRL meta keys is pressed.
+ * This mask is used to check whether one of the CTRL meta keys is pressed.
*
* @see AndroidKey#CTRL_LEFT
* @see AndroidKey#CTRL_RIGHT
*/
CTRL_ON(0x1000),
/**
- * This mask is used to check whether the left CTRL meta key is pressed.
+ * This mask is used to check whether the left CTRL meta key is pressed.
*
* @see AndroidKey#CTRL_LEFT
*/
CTRL_LEFT_ON(0x2000),
/**
- * This mask is used to check whether the right CTRL meta key is pressed.
+ * This mask is used to check whether the right CTRL meta key is pressed.
*
* @see AndroidKey#CTRL_RIGHT
*/
CTRL_RIGHT_ON(0x4000),
/**
- * This mask is used to check whether one of the META meta keys is pressed.
+ * This mask is used to check whether one of the META meta keys is pressed.
*
* @see AndroidKey#META_LEFT
* @see AndroidKey#META_RIGHT
*/
META_ON(0x10000),
/**
- * This mask is used to check whether the left META meta key is pressed.
+ * This mask is used to check whether the left META meta key is pressed.
*
* @see AndroidKey#META_LEFT
*/
META_LEFT_ON(0x20000),
/**
- * This mask is used to check whether the right META meta key is pressed.
+ * This mask is used to check whether the right META meta key is pressed.
*
* @see AndroidKey#META_RIGHT
*/
META_RIGHT_ON(0x40000),
/**
- * This mask is used to check whether the CAPS LOCK meta key is on.
+ * This mask is used to check whether the CAPS LOCK meta key is on.
*
* @see AndroidKey#CAPS_LOCK
*/
CAPS_LOCK_ON(0x100000),
/**
- * This mask is used to check whether the NUM LOCK meta key is on.
+ * This mask is used to check whether the NUM LOCK meta key is on.
*
* @see AndroidKey#NUM_LOCK
*/
NUM_LOCK_ON(0x200000),
/**
- * This mask is used to check whether the SCROLL LOCK meta key is on.
+ * This mask is used to check whether the SCROLL LOCK meta key is on.
*
* @see AndroidKey#SCROLL_LOCK
*/
diff --git a/src/main/java/io/appium/java_client/android/nativekey/PressesKey.java b/src/main/java/io/appium/java_client/android/nativekey/PressesKey.java
index b4c39767c..af633a1d9 100644
--- a/src/main/java/io/appium/java_client/android/nativekey/PressesKey.java
+++ b/src/main/java/io/appium/java_client/android/nativekey/PressesKey.java
@@ -16,15 +16,18 @@
package io.appium.java_client.android.nativekey;
-import static io.appium.java_client.MobileCommand.LONG_PRESS_KEY_CODE;
-import static io.appium.java_client.MobileCommand.PRESS_KEY_CODE;
-
+import io.appium.java_client.CanRememberExtensionPresence;
import io.appium.java_client.CommandExecutionHelper;
import io.appium.java_client.ExecutesMethod;
+import org.openqa.selenium.UnsupportedCommandException;
-import java.util.AbstractMap;
+import java.util.HashMap;
+import java.util.Map;
+
+import static io.appium.java_client.MobileCommand.LONG_PRESS_KEY_CODE;
+import static io.appium.java_client.MobileCommand.PRESS_KEY_CODE;
-public interface PressesKey extends ExecutesMethod {
+public interface PressesKey extends ExecutesMethod, CanRememberExtensionPresence {
/**
* Send a key event to the device under test.
@@ -32,8 +35,16 @@ public interface PressesKey extends ExecutesMethod {
* @param keyEvent The generated native key event
*/
default void pressKey(KeyEvent keyEvent) {
- CommandExecutionHelper.execute(this,
- new AbstractMap.SimpleEntry<>(PRESS_KEY_CODE, keyEvent.build()));
+ final String extName = "mobile: pressKey";
+ try {
+ CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, keyEvent.build());
+ } catch (UnsupportedCommandException e) {
+ // TODO: Remove the fallback
+ CommandExecutionHelper.execute(
+ markExtensionAbsence(extName),
+ Map.entry(PRESS_KEY_CODE, keyEvent.build())
+ );
+ }
}
/**
@@ -42,7 +53,17 @@ default void pressKey(KeyEvent keyEvent) {
* @param keyEvent The generated native key event
*/
default void longPressKey(KeyEvent keyEvent) {
- CommandExecutionHelper.execute(this,
- new AbstractMap.SimpleEntry<>(LONG_PRESS_KEY_CODE, keyEvent.build()));
+ final String extName = "mobile: pressKey";
+ try {
+ var args = new HashMap<>(keyEvent.build());
+ args.put("isLongPress", true);
+ CommandExecutionHelper.executeScript(assertExtensionExists(extName), extName, args);
+ } catch (UnsupportedCommandException e) {
+ // TODO: Remove the fallback
+ CommandExecutionHelper.execute(
+ markExtensionAbsence(extName),
+ Map.entry(LONG_PRESS_KEY_CODE, keyEvent.build())
+ );
+ }
}
}
diff --git a/src/main/java/io/appium/java_client/android/options/EspressoOptions.java b/src/main/java/io/appium/java_client/android/options/EspressoOptions.java
index 0baebf02f..da14a620e 100644
--- a/src/main/java/io/appium/java_client/android/options/EspressoOptions.java
+++ b/src/main/java/io/appium/java_client/android/options/EspressoOptions.java
@@ -32,13 +32,12 @@
import io.appium.java_client.android.options.app.SupportsAllowTestPackagesOption;
import io.appium.java_client.android.options.app.SupportsAndroidInstallTimeoutOption;
import io.appium.java_client.android.options.app.SupportsAppActivityOption;
-import io.appium.java_client.android.options.app.SupportsIntentOptionsOption;
-import io.appium.java_client.android.options.app.SupportsAppWaitDurationOption;
import io.appium.java_client.android.options.app.SupportsAppPackageOption;
import io.appium.java_client.android.options.app.SupportsAppWaitActivityOption;
+import io.appium.java_client.android.options.app.SupportsAppWaitDurationOption;
import io.appium.java_client.android.options.app.SupportsAppWaitPackageOption;
import io.appium.java_client.android.options.app.SupportsAutoGrantPermissionsOption;
-import io.appium.java_client.android.options.app.SupportsEnforceAppInstallOption;
+import io.appium.java_client.android.options.app.SupportsIntentOptionsOption;
import io.appium.java_client.android.options.app.SupportsRemoteAppsCacheLimitOption;
import io.appium.java_client.android.options.app.SupportsUninstallOtherPackagesOption;
import io.appium.java_client.android.options.avd.SupportsAvdArgsOption;
@@ -89,6 +88,7 @@
import io.appium.java_client.remote.options.SupportsAppOption;
import io.appium.java_client.remote.options.SupportsAutoWebViewOption;
import io.appium.java_client.remote.options.SupportsDeviceNameOption;
+import io.appium.java_client.remote.options.SupportsEnforceAppInstallOption;
import io.appium.java_client.remote.options.SupportsIsHeadlessOption;
import io.appium.java_client.remote.options.SupportsLanguageOption;
import io.appium.java_client.remote.options.SupportsLocaleOption;
@@ -101,7 +101,10 @@
import java.util.Map;
/**
- * https://github.com/appium/appium-espresso-driver#capabilities
+ * Provides options specific to the Espresso Driver.
+ *
+ * For more details, refer to the
+ * capabilities documentation
*/
public class EspressoOptions extends BaseOptions implements
// General options: https://github.com/appium/appium-uiautomator2-driver#general
diff --git a/src/main/java/io/appium/java_client/android/options/UiAutomator2Options.java b/src/main/java/io/appium/java_client/android/options/UiAutomator2Options.java
index 14eddf9eb..77115496f 100644
--- a/src/main/java/io/appium/java_client/android/options/UiAutomator2Options.java
+++ b/src/main/java/io/appium/java_client/android/options/UiAutomator2Options.java
@@ -31,13 +31,12 @@
import io.appium.java_client.android.options.app.SupportsAllowTestPackagesOption;
import io.appium.java_client.android.options.app.SupportsAndroidInstallTimeoutOption;
import io.appium.java_client.android.options.app.SupportsAppActivityOption;
-import io.appium.java_client.android.options.app.SupportsAppWaitDurationOption;
import io.appium.java_client.android.options.app.SupportsAppPackageOption;
import io.appium.java_client.android.options.app.SupportsAppWaitActivityOption;
+import io.appium.java_client.android.options.app.SupportsAppWaitDurationOption;
import io.appium.java_client.android.options.app.SupportsAppWaitForLaunchOption;
import io.appium.java_client.android.options.app.SupportsAppWaitPackageOption;
import io.appium.java_client.android.options.app.SupportsAutoGrantPermissionsOption;
-import io.appium.java_client.android.options.app.SupportsEnforceAppInstallOption;
import io.appium.java_client.android.options.app.SupportsIntentActionOption;
import io.appium.java_client.android.options.app.SupportsIntentCategoryOption;
import io.appium.java_client.android.options.app.SupportsIntentFlagsOption;
@@ -50,7 +49,6 @@
import io.appium.java_client.android.options.avd.SupportsAvdOption;
import io.appium.java_client.android.options.avd.SupportsAvdReadyTimeoutOption;
import io.appium.java_client.android.options.avd.SupportsGpsEnabledOption;
-import io.appium.java_client.remote.options.SupportsIsHeadlessOption;
import io.appium.java_client.android.options.avd.SupportsNetworkSpeedOption;
import io.appium.java_client.android.options.context.SupportsAutoWebviewTimeoutOption;
import io.appium.java_client.android.options.context.SupportsChromeLoggingPrefsOption;
@@ -78,7 +76,6 @@
import io.appium.java_client.android.options.mjpeg.SupportsMjpegScreenshotUrlOption;
import io.appium.java_client.android.options.mjpeg.SupportsMjpegServerPortOption;
import io.appium.java_client.android.options.other.SupportsDisableSuppressAccessibilityServiceOption;
-import io.appium.java_client.remote.options.SupportsSkipLogCaptureOption;
import io.appium.java_client.android.options.other.SupportsUserProfileOption;
import io.appium.java_client.android.options.server.SupportsDisableWindowAnimationOption;
import io.appium.java_client.android.options.server.SupportsSkipDeviceInitializationOption;
@@ -97,17 +94,23 @@
import io.appium.java_client.remote.options.SupportsClearSystemFilesOption;
import io.appium.java_client.remote.options.SupportsDeviceNameOption;
import io.appium.java_client.remote.options.SupportsEnablePerformanceLoggingOption;
+import io.appium.java_client.remote.options.SupportsEnforceAppInstallOption;
+import io.appium.java_client.remote.options.SupportsIsHeadlessOption;
import io.appium.java_client.remote.options.SupportsLanguageOption;
import io.appium.java_client.remote.options.SupportsLocaleOption;
import io.appium.java_client.remote.options.SupportsOrientationOption;
import io.appium.java_client.remote.options.SupportsOtherAppsOption;
+import io.appium.java_client.remote.options.SupportsSkipLogCaptureOption;
import io.appium.java_client.remote.options.SupportsUdidOption;
import org.openqa.selenium.Capabilities;
import java.util.Map;
/**
- * https://github.com/appium/appium-uiautomator2-driver#capabilities
+ * Provides options specific to the UiAutomator2 Driver.
+ *
+ * For more details, refer to the
+ * capabilities documentation
*/
public class UiAutomator2Options extends BaseOptions implements
// General options: https://github.com/appium/appium-uiautomator2-driver#general
diff --git a/src/main/java/io/appium/java_client/android/options/adb/SupportsLogcatFilterSpecsOption.java b/src/main/java/io/appium/java_client/android/options/adb/SupportsLogcatFilterSpecsOption.java
index 6aca7a15e..f58076fe6 100644
--- a/src/main/java/io/appium/java_client/android/options/adb/SupportsLogcatFilterSpecsOption.java
+++ b/src/main/java/io/appium/java_client/android/options/adb/SupportsLogcatFilterSpecsOption.java
@@ -20,6 +20,7 @@
import io.appium.java_client.remote.options.CanSetCapability;
import org.openqa.selenium.Capabilities;
+import java.util.List;
import java.util.Optional;
public interface SupportsLogcatFilterSpecsOption> extends
@@ -27,25 +28,28 @@ public interface SupportsLogcatFilterSpecsOption> exten
String LOGCAT_FILTER_SPECS_OPTION = "logcatFilterSpecs";
/**
- * Series of tag[:priority] where tag is a log component tag (or * for all)
- * and priority is: V Verbose, D Debug, I Info, W Warn, E Error, F Fatal,
- * S Silent (supress all output). '' means ':d' and tag by itself means tag:v.
- * If not specified on the commandline, filterspec is set from ANDROID_LOG_TAGS.
- * If no filterspec is found, filter defaults to '*:I'.
+ * Allows to customize logcat output filtering.
*
- * @param format The filter specifier.
+ * @param format The filter specifier. Consists from series of `tag[:priority]` items,
+ * where `tag` is a log component tag (or `*` to match any value)
+ * and `priority`: V (Verbose), D (Debug), I (Info), W (Warn), E (Error), F (Fatal),
+ * S (Silent - suppresses all output). `tag` without `priority` defaults to `tag:v`.
+ * If not specified, filterspec is set from ANDROID_LOG_TAGS environment variable.
+ * If no filterspec is found, filter defaults to `*:I`, which means
+ * to only show log lines with any tag and the log level INFO or higher.
* @return self instance for chaining.
*/
- default T setLogcatFilterSpecs(String format) {
+ default T setLogcatFilterSpecs(List format) {
return amend(LOGCAT_FILTER_SPECS_OPTION, format);
}
/**
* Get the logcat filter format.
*
- * @return Format specifier.
+ * @return Format specifier. See the documentation on {@link #setLogcatFilterSpecs(List)} for more details.
*/
- default Optional getLogcatFilterSpecs() {
- return Optional.ofNullable((String) getCapability(LOGCAT_FILTER_SPECS_OPTION));
+ default Optional> getLogcatFilterSpecs() {
+ //noinspection unchecked
+ return Optional.ofNullable((List) getCapability(LOGCAT_FILTER_SPECS_OPTION));
}
}
diff --git a/src/main/java/io/appium/java_client/android/options/app/IntentOptions.java b/src/main/java/io/appium/java_client/android/options/app/IntentOptions.java
index e651a4b91..67f09f2b5 100644
--- a/src/main/java/io/appium/java_client/android/options/app/IntentOptions.java
+++ b/src/main/java/io/appium/java_client/android/options/app/IntentOptions.java
@@ -261,7 +261,7 @@ public IntentOptions withEi(Map ei) {
private Map convertMapValues(Map map, Function converter) {
return map.entrySet().stream()
.collect(Collectors.toMap(
- Map.Entry::getKey, (entry) -> converter.apply(String.valueOf(entry.getValue())))
+ Map.Entry::getKey, entry -> converter.apply(String.valueOf(entry.getValue())))
);
}
@@ -272,7 +272,7 @@ private Map convertMapValues(Map map, Function> getEi() {
Optional