diff --git a/src/main/java/io/appium/java_client/MobileCommand.java b/src/main/java/io/appium/java_client/MobileCommand.java index 57782caaf..7b8d8c392 100644 --- a/src/main/java/io/appium/java_client/MobileCommand.java +++ b/src/main/java/io/appium/java_client/MobileCommand.java @@ -62,6 +62,7 @@ public class MobileCommand { protected static final String IS_KEYBOARD_SHOWN = "isKeyboardShown"; protected static final String IS_LOCKED = "isLocked"; protected static final String LONG_PRESS_KEY_CODE = "longPressKeyCode"; + protected static final String FINGER_PRINT = "fingerPrint"; protected static final String OPEN_NOTIFICATIONS = "openNotifications"; protected static final String PRESS_KEY_CODE = "pressKeyCode"; protected static final String PUSH_FILE = "pushFile"; @@ -112,6 +113,7 @@ private static Map createCommandRepository() { result.put(IS_LOCKED, postC("/session/:sessionId/appium/device/is_locked")); result.put(LONG_PRESS_KEY_CODE, postC("/session/:sessionId/appium/device/long_press_keycode")); + result.put(FINGER_PRINT, postC("/session/:sessionId/appium/device/finger_print")); result.put(OPEN_NOTIFICATIONS, postC("/session/:sessionId/appium/device/open_notifications")); result.put(PRESS_KEY_CODE, diff --git a/src/main/java/io/appium/java_client/PressesKeyCode.java b/src/main/java/io/appium/java_client/PressesKeyCode.java index 4ad06f104..fcd5794f0 100644 --- a/src/main/java/io/appium/java_client/PressesKeyCode.java +++ b/src/main/java/io/appium/java_client/PressesKeyCode.java @@ -18,6 +18,7 @@ import static io.appium.java_client.MobileCommand.longPressKeyCodeCommand; import static io.appium.java_client.MobileCommand.pressKeyCodeCommand; +import static io.appium.java_client.android.AndroidMobileCommandHelper.fingerPrintCommand; public interface PressesKeyCode extends ExecutesMethod { @@ -41,6 +42,15 @@ default void pressKeyCode(int key, Integer metastate) { CommandExecutionHelper.execute(this, pressKeyCodeCommand(key, metastate)); } + /** + * Authenticate users by using their finger print scans on supported emulators. + * + * @param fingerPrintId finger prints stored in Android Keystore system (from 1 to 10) + */ + default void fingerPrint(int fingerPrintId) { + CommandExecutionHelper.execute(this, fingerPrintCommand(fingerPrintId)); + } + /** * Send a long key event to the device. * diff --git a/src/main/java/io/appium/java_client/android/AndroidMobileCommandHelper.java b/src/main/java/io/appium/java_client/android/AndroidMobileCommandHelper.java index e9ea6b6dd..a445156c8 100644 --- a/src/main/java/io/appium/java_client/android/AndroidMobileCommandHelper.java +++ b/src/main/java/io/appium/java_client/android/AndroidMobileCommandHelper.java @@ -166,6 +166,19 @@ public class AndroidMobileCommandHelper extends MobileCommand { LONG_PRESS_KEY_CODE, prepareArguments(parameters, values)); } + /** + * This method forms a {@link java.util.Map} of parameters for the + * finger print authentication invocation. + * + * @param fingerPrintId finger prints stored in Android Keystore system (from 1 to 10) + * @return a key-value pair. The key is the command name. The value is a + * {@link java.util.Map} command arguments. + */ + public static Map.Entry> fingerPrintCommand(int fingerPrintId) { + return new AbstractMap.SimpleEntry<>(FINGER_PRINT, + prepareArguments("fingerprintId", fingerPrintId)); + } + /** * This method forms a {@link java.util.Map} of parameters for the * notification opening. diff --git a/src/test/java/io/appium/java_client/android/FingerPrintTest.java b/src/test/java/io/appium/java_client/android/FingerPrintTest.java new file mode 100644 index 000000000..1c9408e33 --- /dev/null +++ b/src/test/java/io/appium/java_client/android/FingerPrintTest.java @@ -0,0 +1,120 @@ +/* + * 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 io.appium.java_client.remote.MobileCapabilityType; +import io.appium.java_client.service.local.AppiumDriverLocalService; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.openqa.selenium.By; +import org.openqa.selenium.remote.DesiredCapabilities; + +import java.util.concurrent.TimeUnit; + +public class FingerPrintTest { + private static AppiumDriverLocalService service; + + /** + * initialization. + */ + @BeforeClass public static void beforeClass() throws Exception { + service = AppiumDriverLocalService.buildDefaultService(); + service.start(); + + if (service == null || !service.isRunning()) { + throw new ExceptionInInitializerError("An appium server node is not started!"); + } + } + + /** + * finishing. + */ + @AfterClass public static void afterClass() { + if (service != null) { + service.stop(); + } + } + + /** + * enable system security which is required for finger print activation. + */ + @Before public void before() throws Exception { + final AndroidDriver driver = getAndroidDriver("ChooseLockGeneric"); + TimeUnit.SECONDS.sleep(2); + // clicking the pin lock mode + driver.findElement(By.xpath("//android.widget.ListView[1]/android.widget.LinearLayout[4]")) + .click(); + TimeUnit.SECONDS.sleep(2); + driver.findElement(By.id("com.android.settings:id/password_entry")).sendKeys("1234\n"); + TimeUnit.SECONDS.sleep(2); + driver.findElement(By.id("com.android.settings:id/password_entry")).sendKeys("1234\n"); + TimeUnit.SECONDS.sleep(2); + driver.findElement(By.id("com.android.settings:id/next_button")).click(); + TimeUnit.SECONDS.sleep(2); + driver.quit(); + } + + /** + * add a new finger print to security. + */ + @Test public void pressKeyCodeTest() throws Exception { + try { + final AndroidDriver driver = getAndroidDriver(".fingerprint.FingerprintSettings"); + TimeUnit.SECONDS.sleep(2); + driver.findElement(By.id("com.android.settings:id/password_entry")).sendKeys("1234\n"); + TimeUnit.SECONDS.sleep(2); + driver.findElement( + By.xpath("//android.widget.ListView[1]/android.widget.LinearLayout[1]")).click(); + TimeUnit.SECONDS.sleep(2); + driver.fingerPrint(2); + driver.findElement(By.id("com.android.settings:id/next_button")).click(); + TimeUnit.SECONDS.sleep(2); + driver.quit(); + } catch (Exception ignored) { + Assert.fail(); + } + } + + /** + * disabling pin lock mode. + */ + @After public void after() throws Exception { + final AndroidDriver driver = getAndroidDriver("ChooseLockGeneric"); + TimeUnit.SECONDS.sleep(2); + driver.findElement(By.id("com.android.settings:id/password_entry")).sendKeys("1234\n"); + TimeUnit.SECONDS.sleep(2); + driver.findElement(By.xpath("//android.widget.ListView[1]/android.widget.LinearLayout[1]")) + .click(); + TimeUnit.SECONDS.sleep(2); + driver.findElement(By.id("android:id/button1")).click(); + TimeUnit.SECONDS.sleep(2); + driver.quit(); + } + + private AndroidDriver getAndroidDriver(String activity) throws Exception { + DesiredCapabilities capabilities = new DesiredCapabilities(); + capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator"); + capabilities.setCapability("appPackage", "com.android.settings"); + capabilities.setCapability("appActivity", activity); + return (AndroidDriver) new AndroidDriver(service.getUrl(), capabilities); + } + +}