From deeec9886af73e9f5a60968c8cf6cf5bd15b1748 Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Sun, 31 Oct 2021 19:49:12 +0100 Subject: [PATCH 1/2] chore: Deprecate legacy app management helpers --- .../appium/java_client/InteractsWithApps.java | 29 +-------- .../io/appium/java_client/MobileCommand.java | 4 +- .../java_client/PerformsTouchActions.java | 1 + ...nteractsWithFiles.java => PullsFiles.java} | 26 ++------ .../SupportsLegacyAppManagement.java | 59 +++++++++++++++++++ .../io/appium/java_client/TouchAction.java | 16 ++--- .../java_client/android/AndroidDriver.java | 6 +- .../java_client/android/PushesFiles.java | 4 +- .../io/appium/java_client/ios/IOSDriver.java | 6 +- .../appium/java_client/ios/PushesFiles.java | 19 ++---- .../java_client/windows/WindowsDriver.java | 22 ++++++- 11 files changed, 110 insertions(+), 82 deletions(-) rename src/main/java/io/appium/java_client/{InteractsWithFiles.java => PullsFiles.java} (69%) create mode 100644 src/main/java/io/appium/java_client/SupportsLegacyAppManagement.java diff --git a/src/main/java/io/appium/java_client/InteractsWithApps.java b/src/main/java/io/appium/java_client/InteractsWithApps.java index 202360e22..f1a15146e 100644 --- a/src/main/java/io/appium/java_client/InteractsWithApps.java +++ b/src/main/java/io/appium/java_client/InteractsWithApps.java @@ -17,13 +17,10 @@ package io.appium.java_client; import static io.appium.java_client.MobileCommand.ACTIVATE_APP; -import static io.appium.java_client.MobileCommand.CLOSE_APP; import static io.appium.java_client.MobileCommand.INSTALL_APP; import static io.appium.java_client.MobileCommand.IS_APP_INSTALLED; -import static io.appium.java_client.MobileCommand.LAUNCH_APP; import static io.appium.java_client.MobileCommand.QUERY_APP_STATE; import static io.appium.java_client.MobileCommand.REMOVE_APP; -import static io.appium.java_client.MobileCommand.RESET; import static io.appium.java_client.MobileCommand.RUN_APP_IN_BACKGROUND; import static io.appium.java_client.MobileCommand.TERMINATE_APP; import static io.appium.java_client.MobileCommand.prepareArguments; @@ -40,16 +37,9 @@ import java.util.AbstractMap; import javax.annotation.Nullable; +@SuppressWarnings("rawtypes") public interface InteractsWithApps extends ExecutesMethod { - /** - * Launches the app, which was provided in the capabilities at session creation, - * and (re)starts the session. - */ - default void launchApp() { - execute(LAUNCH_APP); - } - /** * Install an app on the mobile device. * @@ -63,7 +53,7 @@ default void installApp(String appPath) { * Install an app on the mobile device. * * @param appPath path to app to install or a remote URL. - * @param options Set of the corresponding instllation options for + * @param options Set of the corresponding installation options for * the particular platform. */ default void installApp(String appPath, @Nullable BaseInstallApplicationOptions options) { @@ -86,13 +76,6 @@ default boolean isAppInstalled(String bundleId) { new AbstractMap.SimpleEntry<>(IS_APP_INSTALLED, prepareArguments("bundleId", bundleId))); } - /** - * Resets the currently running app together with the session. - */ - default void resetApp() { - execute(RESET); - } - /** * Runs the current app as a background app for the time * requested. This is a synchronous method, it blocks while the @@ -132,14 +115,6 @@ default boolean removeApp(String bundleId, @Nullable BaseRemoveApplicationOption new AbstractMap.SimpleEntry<>(REMOVE_APP, prepareArguments(parameters, values))); } - /** - * Close the app which was provided in the capabilities at session creation - * and quits the session. - */ - default void closeApp() { - execute(CLOSE_APP); - } - /** * Activates the given app if it installed, but not running or if it is running in the * background. diff --git a/src/main/java/io/appium/java_client/MobileCommand.java b/src/main/java/io/appium/java_client/MobileCommand.java index 75435081e..4d20164ad 100644 --- a/src/main/java/io/appium/java_client/MobileCommand.java +++ b/src/main/java/io/appium/java_client/MobileCommand.java @@ -47,8 +47,8 @@ public class MobileCommand { public static final String RUN_APP_IN_BACKGROUND; protected static final String PERFORM_TOUCH_ACTION; protected static final String PERFORM_MULTI_TOUCH; - protected static final String LAUNCH_APP; - protected static final String CLOSE_APP; + public static final String LAUNCH_APP; + public static final String CLOSE_APP; protected static final String GET_DEVICE_TIME; protected static final String GET_SESSION; protected static final String LOG_EVENT; diff --git a/src/main/java/io/appium/java_client/PerformsTouchActions.java b/src/main/java/io/appium/java_client/PerformsTouchActions.java index 7058375f4..0ac7776d6 100644 --- a/src/main/java/io/appium/java_client/PerformsTouchActions.java +++ b/src/main/java/io/appium/java_client/PerformsTouchActions.java @@ -65,6 +65,7 @@ default TouchAction performTouchAction(TouchAction touchAction) { * is called. * * @param multiAction the MultiTouchAction object to perform. + * @return MultiTouchAction instance for chaining. */ @Deprecated default MultiTouchAction performMultiTouchAction(MultiTouchAction multiAction) { diff --git a/src/main/java/io/appium/java_client/InteractsWithFiles.java b/src/main/java/io/appium/java_client/PullsFiles.java similarity index 69% rename from src/main/java/io/appium/java_client/InteractsWithFiles.java rename to src/main/java/io/appium/java_client/PullsFiles.java index d8b6af05a..590e4aaa0 100644 --- a/src/main/java/io/appium/java_client/InteractsWithFiles.java +++ b/src/main/java/io/appium/java_client/PullsFiles.java @@ -26,57 +26,41 @@ import java.nio.charset.StandardCharsets; import java.util.Base64; -public interface InteractsWithFiles extends ExecutesMethod { +public interface PullsFiles extends ExecutesMethod { /** - * Pull a file from the simulator/device. - * On iOS the server should have ifuse - * libraries installed and configured properly for this feature to work - * on real devices. + * Pull a file from the remote system. * On Android the application under test should be * built with debuggable flag enabled in order to get access to its container * on the internal file system. * - * @see iFuse GitHub page6 - * @see osxFuse FAQ - * @see 'Debug Your App' developer article - * * @param remotePath If the path starts with @applicationId// prefix, then the file * will be pulled from the root of the corresponding application container. - * Otherwise the root folder is considered as / on Android and + * Otherwise, the root folder is considered as / on Android and * on iOS it is a media folder root (real devices only). * @return A byte array of Base64 encoded data. */ default byte[] pullFile(String remotePath) { Response response = execute(PULL_FILE, ImmutableMap.of("path", remotePath)); String base64String = response.getValue().toString(); - return Base64.getDecoder().decode(base64String.getBytes(StandardCharsets.UTF_8)); } /** - * Pull a folder content from the simulator/device. - * On iOS the server should have ifuse - * libraries installed and configured properly for this feature to work - * on real devices. + * Pull a folder content from the remote system. * On Android the application under test should be * built with debuggable flag enabled in order to get access to its container * on the internal file system. * - * @see iFuse GitHub page6 - * @see osxFuse FAQ - * @see 'Debug Your App' developer article - * * @param remotePath If the path starts with @applicationId/ prefix, then the folder * will be pulled from the root of the corresponding application container. - * Otherwise the root folder is considered as / on Android and + * Otherwise, the root folder is considered as / on Android and * on iOS it is a media folder root (real devices only). * @return A byte array of Base64 encoded zip archive data. */ default byte[] pullFolder(String remotePath) { Response response = execute(PULL_FOLDER, ImmutableMap.of("path", remotePath)); String base64String = response.getValue().toString(); - return Base64.getDecoder().decode(base64String.getBytes(StandardCharsets.UTF_8)); } diff --git a/src/main/java/io/appium/java_client/SupportsLegacyAppManagement.java b/src/main/java/io/appium/java_client/SupportsLegacyAppManagement.java new file mode 100644 index 000000000..7be14ec6d --- /dev/null +++ b/src/main/java/io/appium/java_client/SupportsLegacyAppManagement.java @@ -0,0 +1,59 @@ +/* + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * 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.java_client; + +import static io.appium.java_client.MobileCommand.CLOSE_APP; +import static io.appium.java_client.MobileCommand.LAUNCH_APP; +import static io.appium.java_client.MobileCommand.RESET; + +@Deprecated +public interface SupportsLegacyAppManagement extends ExecutesMethod { + /** + * Launches the app, which was provided in the capabilities at session creation, + * and (re)starts the session. + * + * @deprecated This method is deprecated and will be removed. + * See https://github.com/appium/appium/issues/15807 + */ + @Deprecated + default void launchApp() { + execute(LAUNCH_APP); + } + + /** + * Resets the currently running app together with the session. + * + * @deprecated This method is deprecated and will be removed. + * See https://github.com/appium/appium/issues/15807 + */ + @Deprecated + default void resetApp() { + execute(RESET); + } + + /** + * Close the app which was provided in the capabilities at session creation + * and quits the session. + * + * @deprecated This method is deprecated and will be removed. + * See https://github.com/appium/appium/issues/15807 + */ + @Deprecated + default void closeApp() { + execute(CLOSE_APP); + } +} diff --git a/src/main/java/io/appium/java_client/TouchAction.java b/src/main/java/io/appium/java_client/TouchAction.java index 669a32e26..866e87140 100644 --- a/src/main/java/io/appium/java_client/TouchAction.java +++ b/src/main/java/io/appium/java_client/TouchAction.java @@ -43,14 +43,14 @@ * Calling perform() sends the action command to the Mobile Driver. Otherwise, * more and more actions can be chained. * - * Touch actions are deprecated. - * Please use W3C Actions instead or the corresponding - * extension methods for the driver (if available). - * Check - * - https://www.youtube.com/watch?v=oAJ7jwMNFVU - * - https://appiumpro.com/editions/30-ios-specific-touch-action-methods - * - https://appiumpro.com/editions/29-automating-complex-gestures-with-the-w3c-actions-api - * for more details. + * @deprecated Touch actions are deprecated. + * Please use W3C Actions instead or the corresponding + * extension methods for the driver (if available). + * Check + * - https://www.youtube.com/watch?v=oAJ7jwMNFVU + * - https://appiumpro.com/editions/30-ios-specific-touch-action-methods + * - https://appiumpro.com/editions/29-automating-complex-gestures-with-the-w3c-actions-api + * for more details. */ @Deprecated public class TouchAction> implements PerformsActions { diff --git a/src/main/java/io/appium/java_client/android/AndroidDriver.java b/src/main/java/io/appium/java_client/android/AndroidDriver.java index 5ad9001c4..8e245bc09 100644 --- a/src/main/java/io/appium/java_client/android/AndroidDriver.java +++ b/src/main/java/io/appium/java_client/android/AndroidDriver.java @@ -31,9 +31,10 @@ import io.appium.java_client.HasOnScreenKeyboard; import io.appium.java_client.HidesKeyboard; import io.appium.java_client.InteractsWithApps; -import io.appium.java_client.InteractsWithFiles; +import io.appium.java_client.PullsFiles; import io.appium.java_client.LocksDevice; import io.appium.java_client.PerformsTouchActions; +import io.appium.java_client.SupportsLegacyAppManagement; import io.appium.java_client.android.connection.HasNetworkConnection; import io.appium.java_client.android.geolocation.SupportsExtendedGeolocationCommands; import io.appium.java_client.android.nativekey.PressesKey; @@ -66,8 +67,9 @@ public class AndroidDriver extends AppiumDriver implements PerformsTouchActions, HidesKeyboard, HasDeviceTime, - InteractsWithFiles, + PullsFiles, InteractsWithApps, + SupportsLegacyAppManagement, HasAppStrings, HasNetworkConnection, PushesFiles, diff --git a/src/main/java/io/appium/java_client/android/PushesFiles.java b/src/main/java/io/appium/java_client/android/PushesFiles.java index 6fdd73136..6d20d4581 100644 --- a/src/main/java/io/appium/java_client/android/PushesFiles.java +++ b/src/main/java/io/appium/java_client/android/PushesFiles.java @@ -21,14 +21,14 @@ import io.appium.java_client.CommandExecutionHelper; import io.appium.java_client.ExecutesMethod; -import io.appium.java_client.InteractsWithFiles; +import io.appium.java_client.PullsFiles; import org.apache.commons.codec.binary.Base64; import org.apache.commons.io.FileUtils; import java.io.File; import java.io.IOException; -public interface PushesFiles extends InteractsWithFiles, ExecutesMethod { +public interface PushesFiles extends PullsFiles, ExecutesMethod { /** * Saves base64 encoded data as a file on the remote mobile device. diff --git a/src/main/java/io/appium/java_client/ios/IOSDriver.java b/src/main/java/io/appium/java_client/ios/IOSDriver.java index cd64de300..db29cc5c6 100644 --- a/src/main/java/io/appium/java_client/ios/IOSDriver.java +++ b/src/main/java/io/appium/java_client/ios/IOSDriver.java @@ -28,9 +28,10 @@ import io.appium.java_client.HidesKeyboard; import io.appium.java_client.HidesKeyboardWithKeyName; import io.appium.java_client.InteractsWithApps; -import io.appium.java_client.InteractsWithFiles; +import io.appium.java_client.PullsFiles; import io.appium.java_client.LocksDevice; import io.appium.java_client.PerformsTouchActions; +import io.appium.java_client.SupportsLegacyAppManagement; import io.appium.java_client.battery.HasBattery; import io.appium.java_client.remote.SupportsContextSwitching; import io.appium.java_client.remote.SupportsLocation; @@ -61,8 +62,9 @@ public class IOSDriver extends AppiumDriver implements SupportsLocation, HidesKeyboard, HasDeviceTime, - InteractsWithFiles, + PullsFiles, InteractsWithApps, + SupportsLegacyAppManagement, HasAppStrings, PerformsTouchActions, HidesKeyboardWithKeyName, diff --git a/src/main/java/io/appium/java_client/ios/PushesFiles.java b/src/main/java/io/appium/java_client/ios/PushesFiles.java index 097deacf3..364586fb6 100644 --- a/src/main/java/io/appium/java_client/ios/PushesFiles.java +++ b/src/main/java/io/appium/java_client/ios/PushesFiles.java @@ -30,13 +30,7 @@ public interface PushesFiles extends ExecutesMethod { /** - * Saves base64 encoded data as a media file on the remote mobile device. - * The server should have ifuse - * libraries installed and configured properly for this feature to work - * on real devices. - * - * @see iFuse GitHub page - * @see osxFuse FAQ + * Saves base64 encoded data as a media file on the remote system. * * @param remotePath Path to file to write data to on remote device * Only the filename part matters there on Simulator, so the remote end @@ -53,13 +47,7 @@ default void pushFile(String remotePath, byte[] base64Data) { } /** - * Saves base64 encoded data as a media file on the remote mobile device. - * The server should have ifuse - * libraries installed and configured properly for this feature to work - * on real devices. - * - * @see iFuse GitHub page - * @see osxFuse FAQ + * Saves base64 encoded data as a media file on the remote system. * * @param remotePath See the documentation on {@link #pushFile(String, byte[])} * @param file Is an existing local file to be written to the remote device @@ -68,7 +56,8 @@ default void pushFile(String remotePath, byte[] base64Data) { default void pushFile(String remotePath, File file) throws IOException { checkNotNull(file, "A reference to file should not be NULL"); if (!file.exists()) { - throw new IOException(String.format("The given file %s doesn't exist", file.getAbsolutePath())); + throw new IOException(String.format("The given file %s doesn't exist", + file.getAbsolutePath())); } pushFile(remotePath, Base64.encodeBase64(FileUtils.readFileToByteArray(file))); } diff --git a/src/main/java/io/appium/java_client/windows/WindowsDriver.java b/src/main/java/io/appium/java_client/windows/WindowsDriver.java index 316081da9..dd12b921c 100644 --- a/src/main/java/io/appium/java_client/windows/WindowsDriver.java +++ b/src/main/java/io/appium/java_client/windows/WindowsDriver.java @@ -17,8 +17,10 @@ package io.appium.java_client.windows; import io.appium.java_client.AppiumDriver; -import io.appium.java_client.HidesKeyboardWithKeyName; +import io.appium.java_client.MobileCommand; import io.appium.java_client.PerformsTouchActions; +import io.appium.java_client.PullsFiles; +import io.appium.java_client.ios.PushesFiles; import io.appium.java_client.remote.AutomationName; import io.appium.java_client.screenrecording.CanRecordScreen; import io.appium.java_client.service.local.AppiumDriverLocalService; @@ -32,8 +34,8 @@ public class WindowsDriver extends AppiumDriver implements PerformsTouchActions, - PressesKeyCode, - HidesKeyboardWithKeyName, + PullsFiles, + PushesFiles, CanRecordScreen { private static final String PLATFORM_NAME = Platform.WINDOWS.name(); private static final String AUTOMATION_NAME = AutomationName.WINDOWS; @@ -80,4 +82,18 @@ public WindowsDriver(HttpClient.Factory httpClientFactory, Capabilities capabili public WindowsDriver(Capabilities capabilities) { super(ensurePlatformAndAutomationNames(capabilities, PLATFORM_NAME, AUTOMATION_NAME)); } + + /** + * Launch the application app under test after it was closed. + */ + public void launchApp() { + execute(MobileCommand.LAUNCH_APP); + } + + /** + * Close the app under test. + */ + public void closeApp() { + execute(MobileCommand.CLOSE_APP); + } } From 38a6d33582d0a57db29f69d2ae103ec7c1dd7eba Mon Sep 17 00:00:00 2001 From: Mykola Mokhnach Date: Sun, 31 Oct 2021 19:58:43 +0100 Subject: [PATCH 2/2] Move interfaces to a common place --- .../java_client/{ios => }/PushesFiles.java | 4 +- .../java_client/android/AndroidDriver.java | 1 + .../java_client/android/PushesFiles.java | 74 ------------------- .../io/appium/java_client/ios/IOSDriver.java | 1 + .../java_client/windows/WindowsDriver.java | 2 +- 5 files changed, 4 insertions(+), 78 deletions(-) rename src/main/java/io/appium/java_client/{ios => }/PushesFiles.java (95%) delete mode 100644 src/main/java/io/appium/java_client/android/PushesFiles.java diff --git a/src/main/java/io/appium/java_client/ios/PushesFiles.java b/src/main/java/io/appium/java_client/PushesFiles.java similarity index 95% rename from src/main/java/io/appium/java_client/ios/PushesFiles.java rename to src/main/java/io/appium/java_client/PushesFiles.java index 364586fb6..d6da2ca82 100644 --- a/src/main/java/io/appium/java_client/ios/PushesFiles.java +++ b/src/main/java/io/appium/java_client/PushesFiles.java @@ -14,13 +14,11 @@ * limitations under the License. */ -package io.appium.java_client.ios; +package io.appium.java_client; import static com.google.common.base.Preconditions.checkNotNull; import static io.appium.java_client.MobileCommand.pushFileCommand; -import io.appium.java_client.CommandExecutionHelper; -import io.appium.java_client.ExecutesMethod; import org.apache.commons.codec.binary.Base64; import org.apache.commons.io.FileUtils; diff --git a/src/main/java/io/appium/java_client/android/AndroidDriver.java b/src/main/java/io/appium/java_client/android/AndroidDriver.java index 8e245bc09..741a4b9f9 100644 --- a/src/main/java/io/appium/java_client/android/AndroidDriver.java +++ b/src/main/java/io/appium/java_client/android/AndroidDriver.java @@ -34,6 +34,7 @@ import io.appium.java_client.PullsFiles; import io.appium.java_client.LocksDevice; import io.appium.java_client.PerformsTouchActions; +import io.appium.java_client.PushesFiles; import io.appium.java_client.SupportsLegacyAppManagement; import io.appium.java_client.android.connection.HasNetworkConnection; import io.appium.java_client.android.geolocation.SupportsExtendedGeolocationCommands; diff --git a/src/main/java/io/appium/java_client/android/PushesFiles.java b/src/main/java/io/appium/java_client/android/PushesFiles.java deleted file mode 100644 index 6d20d4581..000000000 --- a/src/main/java/io/appium/java_client/android/PushesFiles.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * See the NOTICE file distributed with this work for additional - * information regarding copyright ownership. - * 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.java_client.android; - -import static com.google.common.base.Preconditions.checkNotNull; -import static io.appium.java_client.MobileCommand.pushFileCommand; - -import io.appium.java_client.CommandExecutionHelper; -import io.appium.java_client.ExecutesMethod; -import io.appium.java_client.PullsFiles; -import org.apache.commons.codec.binary.Base64; -import org.apache.commons.io.FileUtils; - -import java.io.File; -import java.io.IOException; - -public interface PushesFiles extends PullsFiles, ExecutesMethod { - - /** - * Saves base64 encoded data as a file on the remote mobile device. - * The application under test should be - * built with debuggable flag enabled in order to get access to its container - * on the internal file system. - * - * @see 'Debug Your App' developer article - * - * @param remotePath Path to file to write data to on remote device - * If the path starts with @applicationId/ prefix, then the file - * will be pushed to the root of the corresponding application container. - * @param base64Data Base64 encoded byte array of data to write to remote device - */ - default void pushFile(String remotePath, byte[] base64Data) { - CommandExecutionHelper.execute(this, pushFileCommand(remotePath, base64Data)); - } - - /** - * Saves the given file to the remote mobile device. - * The application under test should be - * built with debugMode flag enabled in order to get access to its container - * on the internal file system. - * - * @see 'Debug Your App' developer article - * - * @param remotePath Path to file to write data to on remote device. - * If the path starts with @applicationId/ prefix, then the file - * will be pushed to the root of the corresponding application container. - * @param file is a file to write to remote device - * @throws IOException when there are problems with a file or current file system - */ - default void pushFile(String remotePath, File file) throws IOException { - checkNotNull(file, "A reference to file should not be NULL"); - if (!file.exists()) { - throw new IOException("The given file " - + file.getAbsolutePath() + " doesn't exist"); - } - pushFile(remotePath, - Base64.encodeBase64(FileUtils.readFileToByteArray(file))); - } - -} diff --git a/src/main/java/io/appium/java_client/ios/IOSDriver.java b/src/main/java/io/appium/java_client/ios/IOSDriver.java index db29cc5c6..01a848b87 100644 --- a/src/main/java/io/appium/java_client/ios/IOSDriver.java +++ b/src/main/java/io/appium/java_client/ios/IOSDriver.java @@ -31,6 +31,7 @@ import io.appium.java_client.PullsFiles; import io.appium.java_client.LocksDevice; import io.appium.java_client.PerformsTouchActions; +import io.appium.java_client.PushesFiles; import io.appium.java_client.SupportsLegacyAppManagement; import io.appium.java_client.battery.HasBattery; import io.appium.java_client.remote.SupportsContextSwitching; diff --git a/src/main/java/io/appium/java_client/windows/WindowsDriver.java b/src/main/java/io/appium/java_client/windows/WindowsDriver.java index dd12b921c..00b21a1ed 100644 --- a/src/main/java/io/appium/java_client/windows/WindowsDriver.java +++ b/src/main/java/io/appium/java_client/windows/WindowsDriver.java @@ -20,7 +20,7 @@ import io.appium.java_client.MobileCommand; import io.appium.java_client.PerformsTouchActions; import io.appium.java_client.PullsFiles; -import io.appium.java_client.ios.PushesFiles; +import io.appium.java_client.PushesFiles; import io.appium.java_client.remote.AutomationName; import io.appium.java_client.screenrecording.CanRecordScreen; import io.appium.java_client.service.local.AppiumDriverLocalService;