From c8946c1e95ad8527fe3ad4aff7ed16ba279d399a Mon Sep 17 00:00:00 2001 From: Ali Kia Date: Tue, 21 Nov 2017 13:33:01 +0800 Subject: [PATCH] add finger print command to android Driver --- .../io/appium/java_client/MobileCommand.java | 3 + .../io/appium/java_client/PressesKeyCode.java | 10 ++ .../android/AndroidMobileCommandHelper.java | 13 ++ .../java_client/android/FingerPrintTest.java | 141 ++++++++++++++++++ 4 files changed, 167 insertions(+) create mode 100644 src/test/java/io/appium/java_client/android/FingerPrintTest.java diff --git a/src/main/java/io/appium/java_client/MobileCommand.java b/src/main/java/io/appium/java_client/MobileCommand.java index d4a57044f..bb43506ff 100644 --- a/src/main/java/io/appium/java_client/MobileCommand.java +++ b/src/main/java/io/appium/java_client/MobileCommand.java @@ -68,6 +68,7 @@ public class MobileCommand { protected static final String IS_KEYBOARD_SHOWN; protected static final String IS_LOCKED; protected static final String LONG_PRESS_KEY_CODE; + protected static final String FINGER_PRINT; protected static final String OPEN_NOTIFICATIONS; protected static final String PRESS_KEY_CODE; protected static final String PUSH_FILE; @@ -116,6 +117,7 @@ public class MobileCommand { IS_KEYBOARD_SHOWN = "isKeyboardShown"; IS_LOCKED = "isLocked"; LONG_PRESS_KEY_CODE = "longPressKeyCode"; + FINGER_PRINT = "fingerPrint"; OPEN_NOTIFICATIONS = "openNotifications"; PRESS_KEY_CODE = "pressKeyCode"; PUSH_FILE = "pushFile"; @@ -170,6 +172,7 @@ public class MobileCommand { commandRepository.put(IS_LOCKED, postC("/session/:sessionId/appium/device/is_locked")); commandRepository.put(LONG_PRESS_KEY_CODE, postC("/session/:sessionId/appium/device/long_press_keycode")); + commandRepository.put(FINGER_PRINT, postC("/session/:sessionId/appium/device/finger_print")); commandRepository.put(OPEN_NOTIFICATIONS, postC("/session/:sessionId/appium/device/open_notifications")); commandRepository.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 9a13d73ce..375eed815 100644 --- a/src/main/java/io/appium/java_client/android/AndroidMobileCommandHelper.java +++ b/src/main/java/io/appium/java_client/android/AndroidMobileCommandHelper.java @@ -184,6 +184,19 @@ public class AndroidMobileCommandHelper extends MobileCommand { IS_LOCKED, ImmutableMap.of()); } + /** + * 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..cc850efc4 --- /dev/null +++ b/src/test/java/io/appium/java_client/android/FingerPrintTest.java @@ -0,0 +1,141 @@ +/* + * 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.NoSuchElementException; +import org.openqa.selenium.remote.DesiredCapabilities; + +import java.util.concurrent.TimeUnit; + +public class FingerPrintTest { + + private static final String PASSWORD_INPUT_ID = "com.android.settings:id/password_entry"; + private static final String FIRST_IN_LIST_XPATH = "//android.widget.ListView[1]/android.widget.LinearLayout[1]"; + private static AppiumDriverLocalService service; + + /** + * initialization. + */ + @BeforeClass public static void beforeClass() { + 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.LinearLayout[4]")).click(); + TimeUnit.SECONDS.sleep(2); + try { + // line below will throw exception if secure startup window is popped up + driver.findElementById(PASSWORD_INPUT_ID); + } catch (NoSuchElementException e) { + // in secure startup window + driver.findElementById("com.android.settings:id/encrypt_require_password").click(); + TimeUnit.SECONDS.sleep(2); + clickOKInPopup(driver); + clickNext(driver); + } + enterPasswordAndContinue(driver); + enterPasswordAndContinue(driver); + clickNext(driver); + driver.quit(); + } + + /** + * add a new finger print to security. + */ + @Test public void pressKeyCodeTest() throws InterruptedException { + final AndroidDriver driver = getAndroidDriver(".fingerprint.FingerprintSettings"); + TimeUnit.SECONDS.sleep(2); + enterPasswordAndContinue(driver); + // click add fingerprint + driver.findElementByXPath(FIRST_IN_LIST_XPATH).click(); + TimeUnit.SECONDS.sleep(2); + driver.fingerPrint(2); + TimeUnit.SECONDS.sleep(2); + try { + clickNext(driver); + } catch (Exception e) { + Assert.fail("fingerprint command fail to execute"); + } finally { + driver.quit(); + } + } + + /** + * disabling pin lock mode. + */ + @After public void after() throws InterruptedException { + final AndroidDriver driver = getAndroidDriver("ChooseLockGeneric"); + TimeUnit.SECONDS.sleep(2); + enterPasswordAndContinue(driver); + driver.findElementByXPath(FIRST_IN_LIST_XPATH).click(); + TimeUnit.SECONDS.sleep(2); + clickOKInPopup(driver); + driver.quit(); + } + + private AndroidDriver getAndroidDriver(String activity) { + DesiredCapabilities capabilities = new DesiredCapabilities(); + capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator"); + capabilities.setCapability("appPackage", "com.android.settings"); + capabilities.setCapability("appActivity", activity); + return new AndroidDriver(service.getUrl(), capabilities); + } + + private void enterPasswordAndContinue(AndroidDriver driver) throws InterruptedException { + driver.findElementById(PASSWORD_INPUT_ID).sendKeys("1234\n"); + TimeUnit.SECONDS.sleep(2); + } + + private void clickNext(AndroidDriver driver) throws InterruptedException { + driver.findElementById("com.android.settings:id/next_button").click(); + TimeUnit.SECONDS.sleep(2); + } + + private void clickOKInPopup(AndroidDriver driver) throws InterruptedException { + driver.findElementById("android:id/button1").click(); + TimeUnit.SECONDS.sleep(2); + } +}