0
# Device Interaction
1
2
Hardware-level device interactions including keyboard management, device rotation, location services, hardware actions, and device state control. These capabilities enable comprehensive device-level testing scenarios.
3
4
## Capabilities
5
6
### Keyboard Management
7
8
Control virtual keyboard visibility and send keyboard input including platform-specific key events.
9
10
```python {.api}
11
def hide_keyboard(self, key_name: str = None, key = None, strategy: str = None):
12
"""
13
Hide the virtual keyboard.
14
15
Args:
16
key_name (str, optional): Name of key to press to hide keyboard
17
key (str, optional): Key to press to hide keyboard
18
strategy (str, optional): Strategy to use ('press', 'pressKey', 'swipeDown', 'tapOut', 'tapOutside')
19
"""
20
21
def is_keyboard_shown(self) -> bool:
22
"""
23
Check if virtual keyboard is currently displayed.
24
25
Returns:
26
bool: True if keyboard is shown, False otherwise
27
"""
28
29
def keyevent(self, keycode: int, metastate: int = None):
30
"""
31
Send Android keycode event.
32
33
Args:
34
keycode (int): Android keycode constant
35
metastate (int, optional): Meta key state flags
36
"""
37
38
def press_keycode(self, keycode: int, metastate: int = None, flags: int = None):
39
"""
40
Press Android key with additional options.
41
42
Args:
43
keycode (int): Android keycode to press
44
metastate (int, optional): Meta key state flags (SHIFT, ALT, etc.)
45
flags (int, optional): Additional key event flags
46
"""
47
48
def long_press_keycode(self, keycode: int, metastate: int = None, flags: int = None):
49
"""
50
Long press Android key.
51
52
Args:
53
keycode (int): Android keycode to long press
54
metastate (int, optional): Meta key state flags
55
flags (int, optional): Additional key event flags
56
"""
57
```
58
59
### Hardware Actions
60
61
Control device hardware features including shake, device locking, and physical device interactions.
62
63
```python {.api}
64
def shake(self):
65
"""Shake the device (triggers accelerometer event)."""
66
67
def lock(self, seconds: int = None):
68
"""
69
Lock the device screen.
70
71
Args:
72
seconds (int, optional): Duration to keep device locked
73
"""
74
75
def unlock(self):
76
"""Unlock the device screen."""
77
78
def is_locked(self) -> bool:
79
"""
80
Check if device screen is locked.
81
82
Returns:
83
bool: True if device is locked, False otherwise
84
"""
85
```
86
87
### Biometric Authentication
88
89
Control biometric authentication features including Touch ID, Face ID, and fingerprint authentication for security testing.
90
91
```python {.api}
92
def touch_id(self, match: bool):
93
"""
94
Simulate Touch ID authentication (iOS only).
95
96
Args:
97
match (bool): True to simulate successful authentication, False for failure
98
"""
99
100
def toggle_touch_id_enrollment(self):
101
"""Toggle Touch ID enrollment status (iOS only)."""
102
103
def finger_print(self, finger_id: int):
104
"""
105
Authenticate with fingerprint (Android only).
106
107
Args:
108
finger_id (int): Finger ID to use for authentication (1-10)
109
"""
110
```
111
112
### Location Services
113
114
Control GPS location and location-based services for testing location-aware applications.
115
116
```python {.api}
117
def set_location(self, latitude: float, longitude: float, altitude: float = None):
118
"""
119
Set device GPS coordinates.
120
121
Args:
122
latitude (float): Latitude coordinate
123
longitude (float): Longitude coordinate
124
altitude (float, optional): Altitude in meters
125
"""
126
127
@property
128
def location(self) -> dict:
129
"""
130
Get current device location.
131
132
Returns:
133
dict: Location data with 'latitude', 'longitude', and 'altitude' keys
134
"""
135
```
136
137
### Device Time
138
139
Access and format device time information for testing time-dependent functionality.
140
141
```python {.api}
142
def get_device_time(self, format: str = None) -> str:
143
"""
144
Get device time in specified format.
145
146
Args:
147
format (str, optional): Time format string (e.g., 'YYYY-MM-DD HH:mm:ss')
148
If None, returns default format
149
150
Returns:
151
str: Formatted device time string
152
"""
153
```
154
155
### Clipboard Operations
156
157
Manage device clipboard content for testing copy/paste functionality and data sharing.
158
159
```python {.api}
160
def get_clipboard(self, content_type = None) -> str:
161
"""
162
Get clipboard content.
163
164
Args:
165
content_type: Type of content to retrieve (ClipboardContentType enum)
166
If None, gets plaintext content
167
168
Returns:
169
str: Clipboard content (may be base64 encoded for binary data)
170
"""
171
172
def set_clipboard(self, content: str, content_type = None):
173
"""
174
Set clipboard content.
175
176
Args:
177
content (str): Content to set in clipboard
178
content_type: Type of content being set (ClipboardContentType enum)
179
If None, sets as plaintext
180
"""
181
```
182
183
### Gesture Actions
184
185
Advanced touch gesture methods for complex interactions including scrolling, dragging, tapping, and swiping.
186
187
```python {.api}
188
def scroll(self, origin_el, destination_el, duration: int = None):
189
"""
190
Scroll from one element to another.
191
192
Args:
193
origin_el (WebElement): Element to start scroll from
194
destination_el (WebElement): Element to scroll to
195
duration (int, optional): Duration of scroll in milliseconds
196
"""
197
198
def drag_and_drop(self, origin_el, destination_el, pause: int = None):
199
"""
200
Drag element from origin to destination.
201
202
Args:
203
origin_el (WebElement): Element to drag from
204
destination_el (WebElement): Element to drop at
205
pause (int, optional): Pause duration in milliseconds
206
"""
207
208
def tap(self, positions: list, duration: int = None):
209
"""
210
Multi-touch tap gesture.
211
212
Args:
213
positions (list): List of (x, y) coordinate tuples for tap points
214
duration (int, optional): Duration to hold tap in milliseconds
215
"""
216
217
def swipe(self, start_x: int, start_y: int, end_x: int, end_y: int, duration: int = None):
218
"""
219
Swipe gesture from start to end coordinates.
220
221
Args:
222
start_x (int): Starting X coordinate
223
start_y (int): Starting Y coordinate
224
end_x (int): Ending X coordinate
225
end_y (int): Ending Y coordinate
226
duration (int, optional): Swipe duration in milliseconds
227
"""
228
229
def flick(self, start_x: int, start_y: int, end_x: int, end_y: int):
230
"""
231
Flick gesture from start to end coordinates.
232
233
Args:
234
start_x (int): Starting X coordinate
235
start_y (int): Starting Y coordinate
236
end_x (int): Ending X coordinate
237
end_y (int): Ending Y coordinate
238
"""
239
```
240
241
## Usage Examples
242
243
### Keyboard Interaction
244
245
```python
246
from appium import webdriver
247
from appium.options.android import UiAutomator2Options
248
249
# Setup
250
options = UiAutomator2Options()
251
driver = webdriver.Remote("http://localhost:4723", options=options)
252
253
# Basic keyboard management
254
text_field = driver.find_element("id", "input_field")
255
text_field.click()
256
257
# Check if keyboard appeared
258
if driver.is_keyboard_shown():
259
print("Keyboard is visible")
260
261
# Type text normally
262
text_field.send_keys("Hello World")
263
264
# Hide keyboard
265
driver.hide_keyboard()
266
267
# Android-specific key events
268
driver.press_keycode(4) # Back key
269
driver.press_keycode(3) # Home key
270
driver.long_press_keycode(26) # Power key (long press)
271
272
# Special key combinations
273
driver.press_keycode(67, metastate=1) # Delete with shift
274
```
275
276
### Hardware and Device Control
277
278
```python
279
# Device locking and unlocking
280
driver.lock(5) # Lock for 5 seconds
281
time.sleep(6)
282
283
if driver.is_locked():
284
driver.unlock()
285
print("Device unlocked")
286
287
# Shake device to trigger accelerometer
288
driver.shake()
289
290
# Useful for testing shake-to-refresh or shake gestures
291
shake_element = driver.find_element("id", "shake_detector")
292
driver.shake()
293
assert "Shake detected" in shake_element.text
294
```
295
296
### Location-Based Testing
297
298
```python
299
# Set GPS coordinates for testing
300
driver.set_location(37.7749, -122.4194, 30) # San Francisco with altitude
301
302
# Verify location in app
303
location_display = driver.find_element("id", "current_location")
304
assert "San Francisco" in location_display.text
305
306
# Get current location
307
current_location = driver.location
308
print(f"Current location: {current_location['latitude']}, {current_location['longitude']}")
309
310
# Test location-based features
311
driver.set_location(40.7128, -74.0060) # New York
312
# Trigger location-based functionality in app
313
location_button = driver.find_element("id", "get_weather")
314
location_button.click()
315
316
weather_display = driver.find_element("id", "weather_info")
317
assert "New York" in weather_display.text
318
```
319
320
### Time-Based Testing
321
322
```python
323
# Get device time in different formats
324
default_time = driver.get_device_time()
325
print(f"Default time: {default_time}")
326
327
formatted_time = driver.get_device_time("YYYY-MM-DD HH:mm:ss")
328
print(f"Formatted time: {formatted_time}")
329
330
iso_time = driver.get_device_time("YYYY-MM-DDTHH:mm:ssZ")
331
print(f"ISO time: {iso_time}")
332
333
# Use time for testing time-sensitive features
334
timestamp_element = driver.find_element("id", "timestamp")
335
app_time = timestamp_element.text
336
device_time = driver.get_device_time("HH:mm")
337
# Verify app shows current device time
338
```
339
340
### Clipboard Operations
341
342
```python
343
from appium.webdriver.common.clipboard_content_type import ClipboardContentType
344
345
# Set text in clipboard
346
driver.set_clipboard("Test clipboard content")
347
348
# Get clipboard content
349
clipboard_text = driver.get_clipboard()
350
print(f"Clipboard contains: {clipboard_text}")
351
352
# Test copy/paste functionality
353
source_text = driver.find_element("id", "source_text")
354
source_text.long_press() # Long press to show context menu
355
356
copy_button = driver.find_element("id", "copy")
357
copy_button.click()
358
359
# Verify clipboard content
360
copied_text = driver.get_clipboard()
361
assert copied_text == source_text.text
362
363
# Paste in another field
364
target_field = driver.find_element("id", "target_field")
365
target_field.click()
366
target_field.long_press()
367
368
paste_button = driver.find_element("id", "paste")
369
paste_button.click()
370
371
# Verify paste worked
372
assert target_field.text == copied_text
373
```
374
375
### Advanced Keyboard Scenarios
376
377
```python
378
# Complex keyboard interaction scenarios
379
def test_keyboard_with_different_strategies():
380
"""Test different keyboard hiding strategies."""
381
382
strategies = ['press', 'swipeDown', 'tapOut']
383
384
for strategy in strategies:
385
# Open keyboard
386
input_field = driver.find_element("id", "test_input")
387
input_field.click()
388
389
if driver.is_keyboard_shown():
390
try:
391
driver.hide_keyboard(strategy=strategy)
392
print(f"Successfully hid keyboard with strategy: {strategy}")
393
except Exception as e:
394
print(f"Strategy {strategy} failed: {e}")
395
396
# Android keycode examples
397
def send_navigation_keys():
398
"""Send various Android navigation keys."""
399
400
# Common Android keycodes
401
KEYCODE_BACK = 4
402
KEYCODE_HOME = 3
403
KEYCODE_MENU = 82
404
KEYCODE_SEARCH = 84
405
KEYCODE_VOLUME_UP = 24
406
KEYCODE_VOLUME_DOWN = 25
407
408
# Navigate using hardware keys
409
driver.press_keycode(KEYCODE_MENU) # Open menu
410
driver.press_keycode(KEYCODE_BACK) # Go back
411
driver.press_keycode(KEYCODE_HOME) # Go to home screen
412
```
413
414
### Error Handling
415
416
```python
417
def safe_keyboard_operations():
418
"""Safely handle keyboard operations with error checking."""
419
420
try:
421
# Try to hide keyboard
422
if driver.is_keyboard_shown():
423
driver.hide_keyboard()
424
except Exception as e:
425
print(f"Could not hide keyboard: {e}")
426
# Try alternative method
427
driver.press_keycode(4) # Back key on Android
428
429
def safe_location_setting():
430
"""Safely set location with validation."""
431
432
try:
433
driver.set_location(37.7749, -122.4194)
434
435
# Verify location was set
436
location = driver.location
437
if abs(location['latitude'] - 37.7749) > 0.01:
438
print("Location may not have been set correctly")
439
except Exception as e:
440
print(f"Could not set location: {e}")
441
```
442
443
## Types
444
445
```python {.api}
446
from typing import Tuple, List, Dict, Union
447
# Keyboard types
448
KeyCode = int # Android keycode constants
449
MetaState = int # Key modifier flags
450
KeyEventFlags = int
451
452
# Location types
453
Latitude = float
454
Longitude = float
455
Altitude = float
456
LocationDict = Dict[str, float] # {'latitude': float, 'longitude': float, 'altitude': float}
457
458
# Time types
459
TimeFormat = str # Format string like 'YYYY-MM-DD HH:mm:ss'
460
DeviceTime = str # Formatted time string
461
462
# Clipboard types
463
class ClipboardContentType:
464
PLAINTEXT = "plaintext"
465
URL = "url"
466
IMAGE = "image"
467
468
ClipboardContent = str # May be base64 encoded for binary content
469
470
# Gesture types
471
TouchPosition = Tuple[int, int] # (x, y) coordinate tuple
472
TouchPositions = List[TouchPosition] # List of touch coordinates
473
Duration = int # Duration in milliseconds
474
GestureSpeed = int # Gesture speed parameter
475
476
# Biometric types
477
FingerID = int # Finger ID for fingerprint authentication (1-10)
478
BiometricMatch = bool # Authentication success/failure
479
```