appium-android-driver 12.4.9 → 12.4.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/build/lib/commands/app-management.d.ts.map +1 -1
  3. package/build/lib/commands/app-management.js.map +1 -1
  4. package/build/lib/commands/appearance.d.ts +9 -9
  5. package/build/lib/commands/appearance.d.ts.map +1 -1
  6. package/build/lib/commands/appearance.js +6 -7
  7. package/build/lib/commands/appearance.js.map +1 -1
  8. package/build/lib/commands/bluetooth.d.ts +13 -7
  9. package/build/lib/commands/bluetooth.d.ts.map +1 -1
  10. package/build/lib/commands/bluetooth.js +6 -10
  11. package/build/lib/commands/bluetooth.js.map +1 -1
  12. package/build/lib/commands/deviceidle.d.ts +9 -5
  13. package/build/lib/commands/deviceidle.d.ts.map +1 -1
  14. package/build/lib/commands/deviceidle.js +5 -9
  15. package/build/lib/commands/deviceidle.js.map +1 -1
  16. package/build/lib/commands/element.d.ts +90 -66
  17. package/build/lib/commands/element.d.ts.map +1 -1
  18. package/build/lib/commands/element.js +74 -53
  19. package/build/lib/commands/element.js.map +1 -1
  20. package/build/lib/commands/execute.d.ts +12 -8
  21. package/build/lib/commands/execute.d.ts.map +1 -1
  22. package/build/lib/commands/execute.js +13 -18
  23. package/build/lib/commands/execute.js.map +1 -1
  24. package/build/lib/commands/gestures.d.ts +8 -5
  25. package/build/lib/commands/gestures.d.ts.map +1 -1
  26. package/build/lib/commands/gestures.js +5 -6
  27. package/build/lib/commands/gestures.js.map +1 -1
  28. package/build/lib/commands/image-injection.d.ts +10 -11
  29. package/build/lib/commands/image-injection.d.ts.map +1 -1
  30. package/build/lib/commands/image-injection.js +7 -16
  31. package/build/lib/commands/image-injection.js.map +1 -1
  32. package/build/lib/commands/ime.d.ts +23 -17
  33. package/build/lib/commands/ime.d.ts.map +1 -1
  34. package/build/lib/commands/ime.js +20 -17
  35. package/build/lib/commands/ime.js.map +1 -1
  36. package/build/lib/commands/keyboard.d.ts +55 -39
  37. package/build/lib/commands/keyboard.d.ts.map +1 -1
  38. package/build/lib/commands/keyboard.js +47 -33
  39. package/build/lib/commands/keyboard.js.map +1 -1
  40. package/build/lib/commands/legacy.d.ts +16 -7
  41. package/build/lib/commands/legacy.d.ts.map +1 -1
  42. package/build/lib/commands/legacy.js +12 -6
  43. package/build/lib/commands/legacy.js.map +1 -1
  44. package/build/lib/commands/log.d.ts +7 -7
  45. package/build/lib/commands/log.d.ts.map +1 -1
  46. package/build/lib/commands/log.js +0 -1
  47. package/build/lib/commands/log.js.map +1 -1
  48. package/build/lib/commands/media-projection.d.ts +32 -36
  49. package/build/lib/commands/media-projection.d.ts.map +1 -1
  50. package/build/lib/commands/media-projection.js +27 -54
  51. package/build/lib/commands/media-projection.js.map +1 -1
  52. package/build/lib/commands/memory.d.ts +7 -7
  53. package/build/lib/commands/memory.d.ts.map +1 -1
  54. package/build/lib/commands/memory.js +4 -8
  55. package/build/lib/commands/memory.js.map +1 -1
  56. package/build/lib/commands/misc.d.ts +38 -26
  57. package/build/lib/commands/misc.d.ts.map +1 -1
  58. package/build/lib/commands/misc.js +31 -24
  59. package/build/lib/commands/misc.js.map +1 -1
  60. package/build/lib/commands/nfc.d.ts +7 -7
  61. package/build/lib/commands/nfc.d.ts.map +1 -1
  62. package/build/lib/commands/nfc.js +6 -10
  63. package/build/lib/commands/nfc.js.map +1 -1
  64. package/build/lib/commands/performance.d.ts.map +1 -1
  65. package/build/lib/commands/performance.js.map +1 -1
  66. package/build/lib/commands/permissions.d.ts +47 -19
  67. package/build/lib/commands/permissions.d.ts.map +1 -1
  68. package/build/lib/commands/permissions.js +21 -36
  69. package/build/lib/commands/permissions.js.map +1 -1
  70. package/build/lib/commands/resources.d.ts +16 -16
  71. package/build/lib/commands/resources.d.ts.map +1 -1
  72. package/build/lib/commands/resources.js +12 -38
  73. package/build/lib/commands/resources.js.map +1 -1
  74. package/build/lib/commands/shell.d.ts.map +1 -1
  75. package/build/lib/commands/shell.js +1 -1
  76. package/build/lib/commands/shell.js.map +1 -1
  77. package/build/lib/commands/system-bars.d.ts +27 -21
  78. package/build/lib/commands/system-bars.d.ts.map +1 -1
  79. package/build/lib/commands/system-bars.js +23 -40
  80. package/build/lib/commands/system-bars.js.map +1 -1
  81. package/build/lib/commands/time.d.ts +17 -14
  82. package/build/lib/commands/time.d.ts.map +1 -1
  83. package/build/lib/commands/time.js +13 -13
  84. package/build/lib/commands/time.js.map +1 -1
  85. package/build/lib/commands/types.d.ts +17 -0
  86. package/build/lib/commands/types.d.ts.map +1 -1
  87. package/lib/commands/app-management.ts +3 -3
  88. package/lib/commands/{appearance.js → appearance.ts} +17 -9
  89. package/lib/commands/{bluetooth.js → bluetooth.ts} +13 -11
  90. package/lib/commands/{deviceidle.js → deviceidle.ts} +13 -12
  91. package/lib/commands/element.ts +234 -0
  92. package/lib/commands/{execute.js → execute.ts} +24 -19
  93. package/lib/commands/gestures.ts +19 -0
  94. package/lib/commands/{image-injection.js → image-injection.ts} +17 -19
  95. package/lib/commands/ime.ts +79 -0
  96. package/lib/commands/keyboard.ts +163 -0
  97. package/lib/commands/legacy.ts +41 -0
  98. package/lib/commands/log.ts +9 -9
  99. package/lib/commands/{media-projection.js → media-projection.ts} +69 -68
  100. package/lib/commands/memory.ts +29 -0
  101. package/lib/commands/misc.ts +118 -0
  102. package/lib/commands/{nfc.js → nfc.ts} +12 -11
  103. package/lib/commands/performance.ts +2 -1
  104. package/lib/commands/{permissions.js → permissions.ts} +58 -50
  105. package/lib/commands/{resources.js → resources.ts} +44 -52
  106. package/lib/commands/shell.ts +2 -1
  107. package/lib/commands/{system-bars.js → system-bars.ts} +59 -50
  108. package/lib/commands/{time.js → time.ts} +26 -16
  109. package/lib/commands/types.ts +27 -0
  110. package/package.json +1 -1
  111. package/lib/commands/element.js +0 -158
  112. package/lib/commands/gestures.js +0 -15
  113. package/lib/commands/ime.js +0 -64
  114. package/lib/commands/keyboard.js +0 -119
  115. package/lib/commands/legacy.js +0 -28
  116. package/lib/commands/memory.js +0 -27
  117. package/lib/commands/misc.js +0 -92
@@ -0,0 +1,234 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-vars */
2
+
3
+ import {errors} from 'appium/driver';
4
+ import type {Position, Size} from '@appium/types';
5
+ import type {AndroidDriver} from '../driver';
6
+ import type {DoSetElementValueOpts} from './types';
7
+
8
+ /**
9
+ * Gets an attribute value from an element.
10
+ *
11
+ * @param attribute The name of the attribute to retrieve.
12
+ * @param elementId The element identifier.
13
+ * @returns Promise that resolves to the attribute value, or `null` if not found.
14
+ * @throws {errors.NotImplementedError} This method is not implemented.
15
+ */
16
+ export async function getAttribute(
17
+ this: AndroidDriver,
18
+ attribute: string,
19
+ elementId: string,
20
+ ): Promise<string | null> {
21
+ throw new errors.NotImplementedError('Not implemented');
22
+ }
23
+
24
+ /**
25
+ * Clicks on an element.
26
+ *
27
+ * @param elementId The element identifier.
28
+ * @returns Promise that resolves when the click is performed.
29
+ * @throws {errors.NotImplementedError} This method is not implemented.
30
+ */
31
+ export async function click(
32
+ this: AndroidDriver,
33
+ elementId: string,
34
+ ): Promise<void> {
35
+ throw new errors.NotImplementedError('Not implemented');
36
+ }
37
+
38
+ /**
39
+ * Gets the text content of an element.
40
+ *
41
+ * @param elementId The element identifier.
42
+ * @returns Promise that resolves to the element's text content.
43
+ * @throws {errors.NotImplementedError} This method is not implemented.
44
+ */
45
+ export async function getText(
46
+ this: AndroidDriver,
47
+ elementId: string,
48
+ ): Promise<string> {
49
+ throw new errors.NotImplementedError('Not implemented');
50
+ }
51
+
52
+ /**
53
+ * Gets the location of an element on the screen.
54
+ *
55
+ * @param elementId The element identifier.
56
+ * @returns Promise that resolves to the element's position (x, y coordinates).
57
+ * @throws {errors.NotImplementedError} This method is not implemented.
58
+ */
59
+ export async function getLocation(
60
+ this: AndroidDriver,
61
+ elementId: string,
62
+ ): Promise<Position> {
63
+ throw new errors.NotImplementedError('Not implemented');
64
+ }
65
+
66
+ /**
67
+ * Gets the size of an element.
68
+ *
69
+ * @param elementId The element identifier.
70
+ * @returns Promise that resolves to the element's size (width, height).
71
+ * @throws {errors.NotImplementedError} This method is not implemented.
72
+ */
73
+ export async function getSize(
74
+ this: AndroidDriver,
75
+ elementId: string,
76
+ ): Promise<Size> {
77
+ throw new errors.NotImplementedError('Not implemented');
78
+ }
79
+
80
+ /**
81
+ * Gets the class name of an element.
82
+ *
83
+ * @param elementId The element identifier.
84
+ * @returns Promise that resolves to the element's class name.
85
+ */
86
+ export async function getName(
87
+ this: AndroidDriver,
88
+ elementId: string,
89
+ ): Promise<string> {
90
+ return await this.getAttribute('className', elementId) as string;
91
+ }
92
+
93
+ /**
94
+ * Checks if an element is displayed.
95
+ *
96
+ * @param elementId The element identifier.
97
+ * @returns Promise that resolves to `true` if the element is displayed, `false` otherwise.
98
+ */
99
+ export async function elementDisplayed(
100
+ this: AndroidDriver,
101
+ elementId: string,
102
+ ): Promise<boolean> {
103
+ return (await this.getAttribute('displayed', elementId)) === 'true';
104
+ }
105
+
106
+ /**
107
+ * Checks if an element is enabled.
108
+ *
109
+ * @param elementId The element identifier.
110
+ * @returns Promise that resolves to `true` if the element is enabled, `false` otherwise.
111
+ */
112
+ export async function elementEnabled(
113
+ this: AndroidDriver,
114
+ elementId: string,
115
+ ): Promise<boolean> {
116
+ return (await this.getAttribute('enabled', elementId)) === 'true';
117
+ }
118
+
119
+ /**
120
+ * Checks if an element is selected.
121
+ *
122
+ * @param elementId The element identifier.
123
+ * @returns Promise that resolves to `true` if the element is selected, `false` otherwise.
124
+ */
125
+ export async function elementSelected(
126
+ this: AndroidDriver,
127
+ elementId: string,
128
+ ): Promise<boolean> {
129
+ return (await this.getAttribute('selected', elementId)) === 'true';
130
+ }
131
+
132
+ /**
133
+ * Sets the value of an element.
134
+ *
135
+ * @param keys The text to set, either as a string or an array of strings (which will be joined).
136
+ * @param elementId The element identifier.
137
+ * @param replace If `true`, replaces the existing value. If `false`, appends to it. Defaults to `false`.
138
+ * @returns Promise that resolves when the value is set.
139
+ */
140
+ export async function setElementValue(
141
+ this: AndroidDriver,
142
+ keys: string | string[],
143
+ elementId: string,
144
+ replace = false,
145
+ ): Promise<void> {
146
+ const text = keys instanceof Array ? keys.join('') : keys;
147
+ return await this.doSetElementValue({
148
+ elementId,
149
+ text: String(text),
150
+ replace,
151
+ });
152
+ }
153
+
154
+ /**
155
+ * Sets the value of an element.
156
+ *
157
+ * Reason for isolating doSetElementValue from setElementValue is for reusing setElementValue
158
+ * across android-drivers (like appium-uiautomator2-driver) and to avoid code duplication.
159
+ * Other android-drivers (like appium-uiautomator2-driver) need to override doSetElementValue
160
+ * to facilitate setElementValue.
161
+ *
162
+ * @param params The parameters for setting the element value.
163
+ * @returns Promise that resolves when the value is set.
164
+ * @throws {errors.NotImplementedError} This method is not implemented.
165
+ */
166
+ export async function doSetElementValue(
167
+ this: AndroidDriver,
168
+ params: DoSetElementValueOpts,
169
+ ): Promise<void> {
170
+ throw new errors.NotImplementedError('Not implemented');
171
+ }
172
+
173
+ /**
174
+ * Sets the value of an element (appends to existing value).
175
+ *
176
+ * @param keys The text to set, either as a string or an array of strings (which will be joined).
177
+ * @param elementId The element identifier.
178
+ * @returns Promise that resolves when the value is set.
179
+ */
180
+ export async function setValue(
181
+ this: AndroidDriver,
182
+ keys: string | string[],
183
+ elementId: string,
184
+ ): Promise<void> {
185
+ return await this.setElementValue(keys, elementId, false);
186
+ }
187
+
188
+ /**
189
+ * Replaces the value of an element.
190
+ *
191
+ * @param keys The text to set, either as a string or an array of strings (which will be joined).
192
+ * @param elementId The element identifier.
193
+ * @returns Promise that resolves when the value is replaced.
194
+ */
195
+ export async function replaceValue(
196
+ this: AndroidDriver,
197
+ keys: string | string[],
198
+ elementId: string,
199
+ ): Promise<void> {
200
+ return await this.setElementValue(keys, elementId, true);
201
+ }
202
+
203
+ /**
204
+ * Sets the value of an element immediately using ADB input.
205
+ *
206
+ * @param keys The text to set, either as a string or an array of strings (which will be joined).
207
+ * @param elementId The element identifier.
208
+ * @returns Promise that resolves when the value is set.
209
+ */
210
+ export async function setValueImmediate(
211
+ this: AndroidDriver,
212
+ keys: string | string[],
213
+ elementId: string,
214
+ ): Promise<void> {
215
+ const text = Array.isArray(keys) ? keys.join('') : keys;
216
+ // first, make sure we are focused on the element
217
+ await this.click(elementId);
218
+ // then send through adb
219
+ await this.adb.inputText(text);
220
+ }
221
+
222
+ /**
223
+ * Gets the location of an element relative to the view.
224
+ *
225
+ * @param elementId The element identifier.
226
+ * @returns Promise that resolves to the element's position (x, y coordinates).
227
+ */
228
+ export async function getLocationInView(
229
+ this: AndroidDriver,
230
+ elementId: string,
231
+ ): Promise<Position> {
232
+ return await this.getLocation(elementId);
233
+ }
234
+
@@ -1,16 +1,26 @@
1
1
  import _ from 'lodash';
2
2
  import {errors, PROTOCOLS} from 'appium/driver';
3
3
  import { util } from '@appium/support';
4
+ import type {StringRecord, Element} from '@appium/types';
5
+ import type {AndroidDriver} from '../driver';
6
+ import type {Chromedriver} from 'appium-chromedriver';
4
7
 
5
8
  const EXECUTE_SCRIPT_PREFIX = 'mobile:';
6
9
 
7
10
  /**
8
- * @this {AndroidDriver}
9
- * @param {string} script
10
- * @param {ExecuteMethodArgs} [args]
11
- * @returns {Promise<any>}
11
+ * Executes a script on the device or in a web context.
12
+ *
13
+ * @param script The script to execute. If it starts with 'mobile:', it will be treated
14
+ * as a mobile command. Otherwise, it will be executed in the web context (if available).
15
+ * @param args Optional arguments to pass to the script.
16
+ * @returns Promise that resolves to the script execution result.
17
+ * @throws {errors.NotImplementedError} If not in a web context and script doesn't start with 'mobile:'.
12
18
  */
13
- export async function execute(script, args) {
19
+ export async function execute(
20
+ this: AndroidDriver,
21
+ script: string,
22
+ args?: ExecuteMethodArgs,
23
+ ): Promise<any> {
14
24
  if (_.startsWith(script, EXECUTE_SCRIPT_PREFIX)) {
15
25
  const formattedScript = script.trim().replace(/^mobile:\s*/, `${EXECUTE_SCRIPT_PREFIX} `);
16
26
  const executeMethodArgs = preprocessExecuteMethodArgs(args);
@@ -20,13 +30,11 @@ export async function execute(script, args) {
20
30
  throw new errors.NotImplementedError();
21
31
  }
22
32
  const endpoint =
23
- /** @type {import('appium-chromedriver').Chromedriver} */ (this.chromedriver).jwproxy
33
+ (this.chromedriver as Chromedriver).jwproxy
24
34
  .downstreamProtocol === PROTOCOLS.MJSONWP
25
35
  ? '/execute'
26
36
  : '/execute/sync';
27
- return await /** @type {import('appium-chromedriver').Chromedriver} */ (
28
- this.chromedriver
29
- ).jwproxy.command(endpoint, 'POST', {
37
+ return await (this.chromedriver as Chromedriver).jwproxy.command(endpoint, 'POST', {
30
38
  script,
31
39
  args,
32
40
  });
@@ -37,11 +45,11 @@ export async function execute(script, args) {
37
45
  /**
38
46
  * Massages the arguments going into an execute method.
39
47
  *
40
- * @param {ExecuteMethodArgs} [args]
41
- * @returns {StringRecord}
48
+ * @param args Optional arguments to preprocess.
49
+ * @returns Preprocessed arguments as a StringRecord.
42
50
  */
43
- function preprocessExecuteMethodArgs(args) {
44
- const executeMethodArgs = /** @type {StringRecord} */ ((_.isArray(args) ? _.first(args) : args) ?? {});
51
+ function preprocessExecuteMethodArgs(args?: ExecuteMethodArgs): StringRecord {
52
+ const executeMethodArgs = (_.isArray(args) ? _.first(args) : args) ?? {} as StringRecord;
45
53
 
46
54
  /**
47
55
  * Renames the deprecated `element` key to `elementId`. Historically,
@@ -57,7 +65,7 @@ function preprocessExecuteMethodArgs(args) {
57
65
  */
58
66
  if ('elementId' in executeMethodArgs) {
59
67
  executeMethodArgs.elementId = util.unwrapElement(
60
- /** @type {import('@appium/types').Element|string} */ (executeMethodArgs.elementId),
68
+ executeMethodArgs.elementId as Element | string,
61
69
  );
62
70
  }
63
71
 
@@ -66,8 +74,5 @@ function preprocessExecuteMethodArgs(args) {
66
74
 
67
75
  // #endregion
68
76
 
69
- /**
70
- * @typedef {import('../driver').AndroidDriver} AndroidDriver
71
- * @typedef {import('@appium/types').StringRecord} StringRecord
72
- * @typedef {readonly any[] | readonly [StringRecord] | Readonly<StringRecord>} ExecuteMethodArgs
73
- */
77
+ type ExecuteMethodArgs = readonly any[] | readonly [StringRecord] | Readonly<StringRecord>;
78
+
@@ -0,0 +1,19 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-vars */
2
+ import {errors} from 'appium/driver';
3
+ import type {StringRecord} from '@appium/types';
4
+ import type {AndroidDriver} from '../driver';
5
+
6
+ /**
7
+ * Performs a series of actions (gestures) on the device.
8
+ *
9
+ * @param actions An array of action objects to perform.
10
+ * @returns Promise that resolves when all actions are performed.
11
+ * @throws {errors.NotImplementedError} This method is not implemented.
12
+ */
13
+ export async function performActions(
14
+ this: AndroidDriver,
15
+ actions: StringRecord[],
16
+ ): Promise<void> {
17
+ throw new errors.NotImplementedError('Not implemented');
18
+ }
19
+
@@ -3,6 +3,7 @@ import path from 'node:path';
3
3
  import {fs, tempDir} from '@appium/support';
4
4
  import crypto from 'node:crypto';
5
5
  import _ from 'lodash';
6
+ import type {AndroidDriver} from '../driver';
6
7
 
7
8
  const EMULATOR_RESOURCES_ROOT = ['emulator', 'resources'];
8
9
  const CONFIG_NAME = 'Toren1BD.posters';
@@ -25,13 +26,15 @@ const PNG_MAGIC_LENGTH = 4;
25
26
  * Updates the emulator configuration to show the
26
27
  * image using the given properties when one opens the Camera app.
27
28
  *
28
- * @this {AndroidDriver}
29
- * @param {string} sdkRoot ADB SDK root folder path
30
- * @returns {Promise<boolean>} If emulator services restart is needed
31
- * to load the updated config or false if the current config is already up to date
29
+ * @param sdkRoot ADB SDK root folder path
30
+ * @returns Promise that resolves to `true` if emulator services restart is needed
31
+ * to load the updated config or `false` if the current config is already up to date
32
32
  * or does not need to be updated
33
33
  */
34
- export async function prepareEmulatorForImageInjection(sdkRoot) {
34
+ export async function prepareEmulatorForImageInjection(
35
+ this: AndroidDriver,
36
+ sdkRoot: string,
37
+ ): Promise<boolean> {
35
38
  const { injectedImageProperties: props } = this.opts;
36
39
  if (!props) {
37
40
  return false;
@@ -74,11 +77,15 @@ export async function prepareEmulatorForImageInjection(sdkRoot) {
74
77
  * already prepared and loaded either manually or using the
75
78
  * `injectedImageProperties` capability.
76
79
  *
77
- * @this {AndroidDriver}
78
- * @param {string} payload Base64-encoded payload of a .png image to be injected
79
- * @returns {Promise<void>}
80
+ * @param payload Base64-encoded payload of a .png image to be injected
81
+ * @returns Promise that resolves when the image is injected.
82
+ * @throws {Error} If called on a non-emulator device.
83
+ * @throws {errors.InvalidArgumentError} If the payload is not a valid base64-encoded PNG.
80
84
  */
81
- export async function mobileInjectEmulatorCameraImage(payload) {
85
+ export async function mobileInjectEmulatorCameraImage(
86
+ this: AndroidDriver,
87
+ payload: string,
88
+ ): Promise<void> {
82
89
  if (!this.isEmulator()) {
83
90
  throw new Error('The image injection feature is only available on emulators');
84
91
  }
@@ -110,12 +117,7 @@ export async function mobileInjectEmulatorCameraImage(payload) {
110
117
 
111
118
  // #region Internal helpers
112
119
 
113
- /**
114
- *
115
- * @param {Buffer} buffer
116
- * @returns {string}
117
- */
118
- function calculateImageHash(buffer) {
120
+ function calculateImageHash(buffer: Buffer): string {
119
121
  const hasher = crypto.createHash('sha1');
120
122
  hasher.update(buffer);
121
123
  return hasher.digest('hex');
@@ -123,7 +125,3 @@ function calculateImageHash(buffer) {
123
125
 
124
126
  // #endregion
125
127
 
126
- /**
127
- * @typedef {import('appium-adb').ADB} ADB
128
- * @typedef {import('../driver').AndroidDriver} AndroidDriver
129
- */
@@ -0,0 +1,79 @@
1
+ import {errors} from 'appium/driver';
2
+ import type {AndroidDriver} from '../driver';
3
+
4
+ /**
5
+ * Checks if an IME (Input Method Editor) is activated.
6
+ *
7
+ * @returns Promise that resolves to `true` (IME is always activated on Android devices).
8
+ */
9
+ export async function isIMEActivated(
10
+ this: AndroidDriver,
11
+ ): Promise<boolean> {
12
+ // IME is always activated on Android devices
13
+ return true;
14
+ }
15
+
16
+ /**
17
+ * Gets the list of available IME engines.
18
+ *
19
+ * @returns Promise that resolves to an array of IME engine identifiers.
20
+ */
21
+ export async function availableIMEEngines(
22
+ this: AndroidDriver,
23
+ ): Promise<string[]> {
24
+ this.log.debug('Retrieving available IMEs');
25
+ const engines = await this.adb.availableIMEs();
26
+ this.log.debug(`Engines: ${JSON.stringify(engines)}`);
27
+ return engines;
28
+ }
29
+
30
+ /**
31
+ * Gets the currently active IME engine.
32
+ *
33
+ * @returns Promise that resolves to the active IME engine identifier.
34
+ */
35
+ export async function getActiveIMEEngine(
36
+ this: AndroidDriver,
37
+ ): Promise<string> {
38
+ this.log.debug('Retrieving current default IME');
39
+ return String(await this.adb.defaultIME());
40
+ }
41
+
42
+ /**
43
+ * Activates an IME engine.
44
+ *
45
+ * @param imeId The IME engine identifier to activate.
46
+ * @returns Promise that resolves when the IME is activated.
47
+ * @throws {errors.IMENotAvailableError} If the IME is not available.
48
+ */
49
+ export async function activateIMEEngine(
50
+ this: AndroidDriver,
51
+ imeId: string,
52
+ ): Promise<void> {
53
+ this.log.debug(`Attempting to activate IME ${imeId}`);
54
+ const availableEngines = await this.adb.availableIMEs();
55
+ if (availableEngines.indexOf(imeId) === -1) {
56
+ this.log.debug('IME not found, failing');
57
+ throw new errors.IMENotAvailableError();
58
+ }
59
+ this.log.debug('Found installed IME, attempting to activate');
60
+ await this.adb.enableIME(imeId);
61
+ await this.adb.setIME(imeId);
62
+ }
63
+
64
+ /**
65
+ * Deactivates the currently active IME engine.
66
+ *
67
+ * @returns Promise that resolves when the IME is deactivated.
68
+ */
69
+ export async function deactivateIMEEngine(
70
+ this: AndroidDriver,
71
+ ): Promise<void> {
72
+ const currentEngine = await this.getActiveIMEEngine();
73
+ // XXX: this allowed 'null' to be passed into `adb.shell`
74
+ if (currentEngine) {
75
+ this.log.debug(`Attempting to deactivate ${currentEngine}`);
76
+ await this.adb.disableIME(currentEngine);
77
+ }
78
+ }
79
+
@@ -0,0 +1,163 @@
1
+ /* eslint-disable @typescript-eslint/no-unused-vars */
2
+ import _ from 'lodash';
3
+ import {errors} from 'appium/driver';
4
+ import {UNICODE_IME, EMPTY_IME} from 'io.appium.settings';
5
+ import type {AndroidDriver} from '../driver';
6
+ import type {SendKeysOpts} from './types';
7
+
8
+ /**
9
+ * Hides the on-screen keyboard.
10
+ *
11
+ * @returns Promise that resolves to `true` if the keyboard was hidden, `false` otherwise.
12
+ */
13
+ export async function hideKeyboard(
14
+ this: AndroidDriver,
15
+ ): Promise<boolean> {
16
+ return await this.adb.hideKeyboard();
17
+ }
18
+
19
+ /**
20
+ * Checks if the on-screen keyboard is currently shown.
21
+ *
22
+ * @returns Promise that resolves to `true` if the keyboard is shown, `false` otherwise.
23
+ */
24
+ export async function isKeyboardShown(
25
+ this: AndroidDriver,
26
+ ): Promise<boolean> {
27
+ const {isKeyboardShown} = await this.adb.isSoftKeyboardPresent();
28
+ return isKeyboardShown;
29
+ }
30
+
31
+ /**
32
+ * Sends keys to the active element.
33
+ *
34
+ * @param keys The keys to send, either as a string or an array of strings (which will be joined).
35
+ * @returns Promise that resolves when the keys are sent.
36
+ */
37
+ export async function keys(
38
+ this: AndroidDriver,
39
+ keys: string | string[],
40
+ ): Promise<void> {
41
+ // Protocol sends an array; rethink approach
42
+ const keysStr = _.isArray(keys) ? keys.join('') : keys;
43
+ await this.doSendKeys({
44
+ text: keysStr,
45
+ replace: false,
46
+ });
47
+ }
48
+
49
+ /**
50
+ * Sends keys to the active element.
51
+ *
52
+ * @param params The parameters for sending keys.
53
+ * @returns Promise that resolves when the keys are sent.
54
+ * @throws {errors.NotImplementedError} This method is not implemented.
55
+ */
56
+ export async function doSendKeys(
57
+ this: AndroidDriver,
58
+ params: SendKeysOpts,
59
+ ): Promise<void> {
60
+ throw new errors.NotImplementedError('Not implemented');
61
+ }
62
+
63
+ /**
64
+ * Sends a key event to the device.
65
+ *
66
+ * @deprecated Use {@link pressKeyCode} instead.
67
+ * @param keycode The key code to press.
68
+ * @param metastate Optional meta state flags.
69
+ * @returns Promise that resolves when the key event is sent.
70
+ */
71
+ export async function keyevent(
72
+ this: AndroidDriver,
73
+ keycode: string | number,
74
+ metastate?: number,
75
+ ): Promise<void> {
76
+ // TODO deprecate keyevent; currently wd only implements keyevent
77
+ this.log.warn('keyevent will be deprecated use pressKeyCode');
78
+ return await this.pressKeyCode(keycode, metastate);
79
+ }
80
+
81
+ /**
82
+ * Presses a key code on the device.
83
+ *
84
+ * @param keycode The key code to press.
85
+ * @param metastate Optional meta state flags.
86
+ * @returns Promise that resolves when the key code is pressed.
87
+ * @throws {errors.NotImplementedError} This method is not implemented.
88
+ */
89
+ export async function pressKeyCode(
90
+ this: AndroidDriver,
91
+ keycode: string | number,
92
+ metastate?: number,
93
+ ): Promise<void> {
94
+ throw new errors.NotImplementedError('Not implemented');
95
+ }
96
+
97
+ /**
98
+ * Long presses a key code on the device.
99
+ *
100
+ * @param keycode The key code to long press.
101
+ * @param metastate Optional meta state flags.
102
+ * @returns Promise that resolves when the key code is long pressed.
103
+ * @throws {errors.NotImplementedError} This method is not implemented.
104
+ */
105
+ export async function longPressKeyCode(
106
+ this: AndroidDriver,
107
+ keycode: string | number,
108
+ metastate?: number,
109
+ ): Promise<void> {
110
+ throw new errors.NotImplementedError('Not implemented');
111
+ }
112
+
113
+ /**
114
+ * Performs an editor action on the active input field.
115
+ *
116
+ * @param action The editor action to perform (e.g., 'done', 'go', 'next').
117
+ * @returns Promise that resolves when the editor action is performed.
118
+ */
119
+ export async function mobilePerformEditorAction(
120
+ this: AndroidDriver,
121
+ action: string | number,
122
+ ): Promise<void> {
123
+ await this.settingsApp.performEditorAction(action);
124
+ }
125
+
126
+ // #region Internal Helpers
127
+
128
+ /**
129
+ * Initializes Unicode keyboard support.
130
+ *
131
+ * @deprecated
132
+ * @returns Promise that resolves to the default IME identifier that was active before.
133
+ */
134
+ export async function initUnicodeKeyboard(
135
+ this: AndroidDriver,
136
+ ): Promise<string | null> {
137
+ this.log.debug('Enabling Unicode keyboard support');
138
+
139
+ // get the default IME so we can return back to it later if we want
140
+ const defaultIME = await this.adb.defaultIME();
141
+
142
+ this.log.debug(`Unsetting previous IME ${defaultIME}`);
143
+ this.log.debug(`Setting IME to '${UNICODE_IME}'`);
144
+ await this.adb.enableIME(UNICODE_IME);
145
+ await this.adb.setIME(UNICODE_IME);
146
+ return defaultIME;
147
+ }
148
+
149
+ /**
150
+ * Hides the on-screen keyboard completely by setting IME to empty.
151
+ *
152
+ * @returns Promise that resolves when the keyboard is hidden.
153
+ */
154
+ export async function hideKeyboardCompletely(
155
+ this: AndroidDriver,
156
+ ): Promise<void> {
157
+ this.log.debug(`Hiding the on-screen keyboard by setting IME to '${EMPTY_IME}'`);
158
+ await this.adb.enableIME(EMPTY_IME);
159
+ await this.adb.setIME(EMPTY_IME);
160
+ }
161
+
162
+ // #endregion
163
+
@@ -0,0 +1,41 @@
1
+ import { errors } from 'appium/driver';
2
+ import type {AndroidDriver} from '../driver';
3
+
4
+ const ISSUE_URL = 'https://github.com/appium/appium/issues/15807';
5
+
6
+ /**
7
+ * Launches the application.
8
+ *
9
+ * @returns Promise that resolves when the app is launched.
10
+ * @throws {errors.UnsupportedOperationError} This API is not supported anymore.
11
+ */
12
+ export async function launchApp(
13
+ this: AndroidDriver,
14
+ ): Promise<void> {
15
+ throw new errors.UnsupportedOperationError(`This API is not supported anymore. See ${ISSUE_URL}`);
16
+ }
17
+
18
+ /**
19
+ * Closes the application.
20
+ *
21
+ * @returns Promise that resolves when the app is closed.
22
+ * @throws {errors.UnsupportedOperationError} This API is not supported anymore.
23
+ */
24
+ export async function closeApp(
25
+ this: AndroidDriver,
26
+ ): Promise<void> {
27
+ throw new errors.UnsupportedOperationError(`This API is not supported anymore. See ${ISSUE_URL}`);
28
+ }
29
+
30
+ /**
31
+ * Resets the application state.
32
+ *
33
+ * @returns Promise that resolves when the app is reset.
34
+ * @throws {errors.UnsupportedOperationError} This API is not supported anymore.
35
+ */
36
+ export async function reset(
37
+ this: AndroidDriver,
38
+ ): Promise<void> {
39
+ throw new errors.UnsupportedOperationError(`This API is not supported anymore. See ${ISSUE_URL}`);
40
+ }
41
+