Skip to content

Commit c8946c1

Browse files
committed
add finger print command to android Driver
1 parent cdf001a commit c8946c1

File tree

4 files changed

+167
-0
lines changed

4 files changed

+167
-0
lines changed

src/main/java/io/appium/java_client/MobileCommand.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ public class MobileCommand {
6868
protected static final String IS_KEYBOARD_SHOWN;
6969
protected static final String IS_LOCKED;
7070
protected static final String LONG_PRESS_KEY_CODE;
71+
protected static final String FINGER_PRINT;
7172
protected static final String OPEN_NOTIFICATIONS;
7273
protected static final String PRESS_KEY_CODE;
7374
protected static final String PUSH_FILE;
@@ -116,6 +117,7 @@ public class MobileCommand {
116117
IS_KEYBOARD_SHOWN = "isKeyboardShown";
117118
IS_LOCKED = "isLocked";
118119
LONG_PRESS_KEY_CODE = "longPressKeyCode";
120+
FINGER_PRINT = "fingerPrint";
119121
OPEN_NOTIFICATIONS = "openNotifications";
120122
PRESS_KEY_CODE = "pressKeyCode";
121123
PUSH_FILE = "pushFile";
@@ -170,6 +172,7 @@ public class MobileCommand {
170172
commandRepository.put(IS_LOCKED, postC("/session/:sessionId/appium/device/is_locked"));
171173
commandRepository.put(LONG_PRESS_KEY_CODE,
172174
postC("/session/:sessionId/appium/device/long_press_keycode"));
175+
commandRepository.put(FINGER_PRINT, postC("/session/:sessionId/appium/device/finger_print"));
173176
commandRepository.put(OPEN_NOTIFICATIONS,
174177
postC("/session/:sessionId/appium/device/open_notifications"));
175178
commandRepository.put(PRESS_KEY_CODE,

src/main/java/io/appium/java_client/PressesKeyCode.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
import static io.appium.java_client.MobileCommand.longPressKeyCodeCommand;
2020
import static io.appium.java_client.MobileCommand.pressKeyCodeCommand;
21+
import static io.appium.java_client.android.AndroidMobileCommandHelper.fingerPrintCommand;
2122

2223
public interface PressesKeyCode extends ExecutesMethod {
2324

@@ -41,6 +42,15 @@ default void pressKeyCode(int key, Integer metastate) {
4142
CommandExecutionHelper.execute(this, pressKeyCodeCommand(key, metastate));
4243
}
4344

45+
/**
46+
* Authenticate users by using their finger print scans on supported emulators.
47+
*
48+
* @param fingerPrintId finger prints stored in Android Keystore system (from 1 to 10)
49+
*/
50+
default void fingerPrint(int fingerPrintId) {
51+
CommandExecutionHelper.execute(this, fingerPrintCommand(fingerPrintId));
52+
}
53+
4454
/**
4555
* Send a long key event to the device.
4656
*

src/main/java/io/appium/java_client/android/AndroidMobileCommandHelper.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,19 @@ public class AndroidMobileCommandHelper extends MobileCommand {
184184
IS_LOCKED, ImmutableMap.<String, Object>of());
185185
}
186186

187+
/**
188+
* This method forms a {@link java.util.Map} of parameters for the
189+
* finger print authentication invocation.
190+
*
191+
* @param fingerPrintId finger prints stored in Android Keystore system (from 1 to 10)
192+
* @return a key-value pair. The key is the command name. The value is a
193+
* {@link java.util.Map} command arguments.
194+
*/
195+
public static Map.Entry<String, Map<String, ?>> fingerPrintCommand(int fingerPrintId) {
196+
return new AbstractMap.SimpleEntry<>(FINGER_PRINT,
197+
prepareArguments("fingerprintId", fingerPrintId));
198+
}
199+
187200
/**
188201
* This method forms a {@link java.util.Map} of parameters for the
189202
* notification opening.
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (the "License");
3+
* you may not use this file except in compliance with the License.
4+
* See the NOTICE file distributed with this work for additional
5+
* information regarding copyright ownership.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.appium.java_client.android;
18+
19+
import io.appium.java_client.remote.MobileCapabilityType;
20+
import io.appium.java_client.service.local.AppiumDriverLocalService;
21+
import org.junit.After;
22+
import org.junit.AfterClass;
23+
import org.junit.Assert;
24+
import org.junit.Before;
25+
import org.junit.BeforeClass;
26+
import org.junit.Test;
27+
import org.openqa.selenium.By;
28+
import org.openqa.selenium.NoSuchElementException;
29+
import org.openqa.selenium.remote.DesiredCapabilities;
30+
31+
import java.util.concurrent.TimeUnit;
32+
33+
public class FingerPrintTest {
34+
35+
private static final String PASSWORD_INPUT_ID = "com.android.settings:id/password_entry";
36+
private static final String FIRST_IN_LIST_XPATH = "//android.widget.ListView[1]/android.widget.LinearLayout[1]";
37+
private static AppiumDriverLocalService service;
38+
39+
/**
40+
* initialization.
41+
*/
42+
@BeforeClass public static void beforeClass() {
43+
service = AppiumDriverLocalService.buildDefaultService();
44+
service.start();
45+
46+
if (service == null || !service.isRunning()) {
47+
throw new ExceptionInInitializerError("An appium server node is not started!");
48+
}
49+
}
50+
51+
/**
52+
* finishing.
53+
*/
54+
@AfterClass public static void afterClass() {
55+
if (service != null) {
56+
service.stop();
57+
}
58+
}
59+
60+
/**
61+
* enable system security which is required for finger print activation.
62+
*/
63+
@Before public void before() throws Exception {
64+
final AndroidDriver driver = getAndroidDriver("ChooseLockGeneric");
65+
TimeUnit.SECONDS.sleep(2);
66+
// clicking the pin lock mode
67+
driver.findElement(By.xpath("//android.widget.LinearLayout[4]")).click();
68+
TimeUnit.SECONDS.sleep(2);
69+
try {
70+
// line below will throw exception if secure startup window is popped up
71+
driver.findElementById(PASSWORD_INPUT_ID);
72+
} catch (NoSuchElementException e) {
73+
// in secure startup window
74+
driver.findElementById("com.android.settings:id/encrypt_require_password").click();
75+
TimeUnit.SECONDS.sleep(2);
76+
clickOKInPopup(driver);
77+
clickNext(driver);
78+
}
79+
enterPasswordAndContinue(driver);
80+
enterPasswordAndContinue(driver);
81+
clickNext(driver);
82+
driver.quit();
83+
}
84+
85+
/**
86+
* add a new finger print to security.
87+
*/
88+
@Test public void pressKeyCodeTest() throws InterruptedException {
89+
final AndroidDriver driver = getAndroidDriver(".fingerprint.FingerprintSettings");
90+
TimeUnit.SECONDS.sleep(2);
91+
enterPasswordAndContinue(driver);
92+
// click add fingerprint
93+
driver.findElementByXPath(FIRST_IN_LIST_XPATH).click();
94+
TimeUnit.SECONDS.sleep(2);
95+
driver.fingerPrint(2);
96+
TimeUnit.SECONDS.sleep(2);
97+
try {
98+
clickNext(driver);
99+
} catch (Exception e) {
100+
Assert.fail("fingerprint command fail to execute");
101+
} finally {
102+
driver.quit();
103+
}
104+
}
105+
106+
/**
107+
* disabling pin lock mode.
108+
*/
109+
@After public void after() throws InterruptedException {
110+
final AndroidDriver driver = getAndroidDriver("ChooseLockGeneric");
111+
TimeUnit.SECONDS.sleep(2);
112+
enterPasswordAndContinue(driver);
113+
driver.findElementByXPath(FIRST_IN_LIST_XPATH).click();
114+
TimeUnit.SECONDS.sleep(2);
115+
clickOKInPopup(driver);
116+
driver.quit();
117+
}
118+
119+
private AndroidDriver getAndroidDriver(String activity) {
120+
DesiredCapabilities capabilities = new DesiredCapabilities();
121+
capabilities.setCapability(MobileCapabilityType.DEVICE_NAME, "Android Emulator");
122+
capabilities.setCapability("appPackage", "com.android.settings");
123+
capabilities.setCapability("appActivity", activity);
124+
return new AndroidDriver<AndroidElement>(service.getUrl(), capabilities);
125+
}
126+
127+
private void enterPasswordAndContinue(AndroidDriver driver) throws InterruptedException {
128+
driver.findElementById(PASSWORD_INPUT_ID).sendKeys("1234\n");
129+
TimeUnit.SECONDS.sleep(2);
130+
}
131+
132+
private void clickNext(AndroidDriver driver) throws InterruptedException {
133+
driver.findElementById("com.android.settings:id/next_button").click();
134+
TimeUnit.SECONDS.sleep(2);
135+
}
136+
137+
private void clickOKInPopup(AndroidDriver driver) throws InterruptedException {
138+
driver.findElementById("android:id/button1").click();
139+
TimeUnit.SECONDS.sleep(2);
140+
}
141+
}

0 commit comments

Comments
 (0)