appium-android-driver 14.2.1 → 14.2.2
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.
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
## [14.2.2](https://github.com/appium/appium-android-driver/compare/v14.2.1...v14.2.2) (2026-09-26)
|
|
2
|
+
|
|
3
|
+
### Bug Fixes
|
|
4
|
+
|
|
5
|
+
* preserve container file transfers and newline paths ([#1101](https://github.com/appium/appium-android-driver/issues/1101)) ([3685fe6](https://github.com/appium/appium-android-driver/commit/3685fe62d2d36c69cbac521e4645a0c10a0a948f))
|
|
6
|
+
* preserve file operations on older Android ([#1102](https://github.com/appium/appium-android-driver/issues/1102)) ([43c8bb2](https://github.com/appium/appium-android-driver/commit/43c8bb2e575cde5258c8de737f30c3b555b17d01))
|
|
7
|
+
|
|
1
8
|
## [14.2.1](https://github.com/appium/appium-android-driver/compare/v14.2.0...v14.2.1) (2026-09-26)
|
|
2
9
|
|
|
3
10
|
### Bug Fixes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-actions.d.ts","sourceRoot":"","sources":["../../../lib/commands/file-actions.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"file-actions.d.ts","sourceRoot":"","sources":["../../../lib/commands/file-actions.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,cAAc,CAAC;AAMhD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,QAAQ,CAAC,IAAI,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA+CvF;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,QAAQ,CAAC,IAAI,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA+DpH;AAED;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAYzF;AAED;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAOhG"}
|
|
@@ -2,8 +2,7 @@ import path from 'node:path';
|
|
|
2
2
|
import { fs, util, zip, tempDir } from '@appium/support';
|
|
3
3
|
import { errors } from 'appium/driver.js';
|
|
4
4
|
const CONTAINER_PATH_MARKER = '@';
|
|
5
|
-
|
|
6
|
-
const CONTAINER_PATH_PATTERN = new RegExp(`^${CONTAINER_PATH_MARKER}([^/]+)/(.+)`);
|
|
5
|
+
const CONTAINER_PATH_PATTERN = new RegExp(`^${CONTAINER_PATH_MARKER}([^/]+)/(.+)`, 's');
|
|
7
6
|
const ANDROID_MEDIA_RESCAN_INTENT = 'android.intent.action.MEDIA_SCANNER_SCAN_FILE';
|
|
8
7
|
/**
|
|
9
8
|
* Pulls a file from the remote device.
|
|
@@ -25,35 +24,43 @@ export async function pullFile(remotePath) {
|
|
|
25
24
|
throw new errors.InvalidArgumentError(`It is expected that remote path points to a file and not to a folder. '${remotePath}' is given instead`);
|
|
26
25
|
}
|
|
27
26
|
let tmpDestination = null;
|
|
28
|
-
if (remotePath.startsWith(CONTAINER_PATH_MARKER)) {
|
|
29
|
-
const [packageId, pathInContainer] = parseContainerPath(remotePath);
|
|
30
|
-
this.log.debug(`Parsed package identifier '${packageId}' from '${remotePath}'. Will get the data from '${pathInContainer}'`);
|
|
31
|
-
tmpDestination = `/data/local/tmp/${path.posix.basename(pathInContainer)}`;
|
|
32
|
-
try {
|
|
33
|
-
await this.adb.shell(['run-as', util.quote(packageId), `chmod 777 '${escapePath(pathInContainer)}'`]);
|
|
34
|
-
await this.adb.shell([
|
|
35
|
-
'run-as',
|
|
36
|
-
util.quote(packageId),
|
|
37
|
-
`cp -f '${escapePath(pathInContainer)}' '${escapePath(tmpDestination)}'`,
|
|
38
|
-
]);
|
|
39
|
-
}
|
|
40
|
-
catch (e) {
|
|
41
|
-
throw this.log.errorWithException(`Cannot access the container of '${packageId}' application. ` +
|
|
42
|
-
`Is the application installed and has 'debuggable' build option set to true? ` +
|
|
43
|
-
`Original error: ${e.message}`);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
27
|
const localFile = await tempDir.path({ prefix: 'appium', suffix: '.tmp' });
|
|
47
28
|
try {
|
|
29
|
+
if (remotePath.startsWith(CONTAINER_PATH_MARKER)) {
|
|
30
|
+
const [packageId, pathInContainer] = parseContainerPath(remotePath);
|
|
31
|
+
this.log.debug(`Parsed package identifier '${packageId}' from '${remotePath}'. Will get the data from '${pathInContainer}'`);
|
|
32
|
+
try {
|
|
33
|
+
tmpDestination = await this.adb.shell(['mktemp', '/data/local/tmp/appium-pull-XXXXXX']);
|
|
34
|
+
// The shell user opens the destination; run-as only needs to read the source.
|
|
35
|
+
// App users cannot create files in /data/local/tmp on non-rooted devices.
|
|
36
|
+
await this.adb.shell([
|
|
37
|
+
'run-as',
|
|
38
|
+
util.quote(packageId),
|
|
39
|
+
'cat',
|
|
40
|
+
util.quote(pathInContainer),
|
|
41
|
+
'>',
|
|
42
|
+
util.quote(tmpDestination),
|
|
43
|
+
]);
|
|
44
|
+
}
|
|
45
|
+
catch (e) {
|
|
46
|
+
throw this.log.errorWithException(`Cannot access the container of '${packageId}' application. ` +
|
|
47
|
+
`Is the application installed and has 'debuggable' build option set to true? ` +
|
|
48
|
+
`Original error: ${e.message}`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
48
51
|
await this.adb.pull(tmpDestination || remotePath, localFile);
|
|
49
52
|
return (await util.toInMemoryBase64(localFile)).toString();
|
|
50
53
|
}
|
|
51
54
|
finally {
|
|
52
|
-
|
|
53
|
-
await fs.
|
|
55
|
+
try {
|
|
56
|
+
if (await fs.exists(localFile)) {
|
|
57
|
+
await fs.unlink(localFile);
|
|
58
|
+
}
|
|
54
59
|
}
|
|
55
|
-
|
|
56
|
-
|
|
60
|
+
finally {
|
|
61
|
+
if (tmpDestination) {
|
|
62
|
+
await this.adb.shell(['rm', '-f', util.quote(tmpDestination)]);
|
|
63
|
+
}
|
|
57
64
|
}
|
|
58
65
|
}
|
|
59
66
|
}
|
|
@@ -247,7 +254,14 @@ async function scanMedia(remotePath) {
|
|
|
247
254
|
await this.settingsApp.scanMedia(remotePath);
|
|
248
255
|
}
|
|
249
256
|
else {
|
|
250
|
-
await this.adb.shell([
|
|
257
|
+
await this.adb.shell([
|
|
258
|
+
'am',
|
|
259
|
+
'broadcast',
|
|
260
|
+
'-a',
|
|
261
|
+
ANDROID_MEDIA_RESCAN_INTENT,
|
|
262
|
+
'-d',
|
|
263
|
+
util.quote(`file://${remotePath}`),
|
|
264
|
+
]);
|
|
251
265
|
}
|
|
252
266
|
}
|
|
253
267
|
catch (e) {
|
|
@@ -270,7 +284,9 @@ function createFSTests(adb) {
|
|
|
270
284
|
const performRemoteFsCheck = async (p, op, runAs) => {
|
|
271
285
|
const passFlag = '__PASS__';
|
|
272
286
|
const checkCmd = `[ -${op} '${escapePath(p)}' ] && echo ${passFlag}`;
|
|
273
|
-
|
|
287
|
+
// Older Android images provide [ as a shell builtin, not an executable
|
|
288
|
+
// that run-as can invoke directly.
|
|
289
|
+
const fullCmd = runAs ? `run-as ${util.quote(runAs)} sh -c '${escapePath(checkCmd)}'` : checkCmd;
|
|
274
290
|
try {
|
|
275
291
|
return (await adb.shell([fullCmd])).includes(passFlag);
|
|
276
292
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-actions.js","sourceRoot":"","sources":["../../../lib/commands/file-actions.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,EAAC,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAC,MAAM,iBAAiB,CAAC;AAEvD,OAAO,EAAC,MAAM,EAAC,MAAM,kBAAkB,CAAC;AAIxC,MAAM,qBAAqB,GAAG,GAAG,CAAC;AAClC,
|
|
1
|
+
{"version":3,"file":"file-actions.js","sourceRoot":"","sources":["../../../lib/commands/file-actions.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,8 +7,7 @@ import {errors} from 'appium/driver.js';
|
|
|
7
7
|
import type {AndroidDriver} from '../driver.js';
|
|
8
8
|
|
|
9
9
|
const CONTAINER_PATH_MARKER = '@';
|
|
10
|
-
|
|
11
|
-
const CONTAINER_PATH_PATTERN = new RegExp(`^${CONTAINER_PATH_MARKER}([^/]+)/(.+)`);
|
|
10
|
+
const CONTAINER_PATH_PATTERN = new RegExp(`^${CONTAINER_PATH_MARKER}([^/]+)/(.+)`, 's');
|
|
12
11
|
const ANDROID_MEDIA_RESCAN_INTENT = 'android.intent.action.MEDIA_SCANNER_SCAN_FILE';
|
|
13
12
|
|
|
14
13
|
/**
|
|
@@ -33,37 +32,44 @@ export async function pullFile(this: AndroidDriver, remotePath: string): Promise
|
|
|
33
32
|
);
|
|
34
33
|
}
|
|
35
34
|
let tmpDestination: string | null = null;
|
|
36
|
-
if (remotePath.startsWith(CONTAINER_PATH_MARKER)) {
|
|
37
|
-
const [packageId, pathInContainer] = parseContainerPath(remotePath);
|
|
38
|
-
this.log.debug(
|
|
39
|
-
`Parsed package identifier '${packageId}' from '${remotePath}'. Will get the data from '${pathInContainer}'`,
|
|
40
|
-
);
|
|
41
|
-
tmpDestination = `/data/local/tmp/${path.posix.basename(pathInContainer)}`;
|
|
42
|
-
try {
|
|
43
|
-
await this.adb.shell(['run-as', util.quote(packageId), `chmod 777 '${escapePath(pathInContainer)}'`]);
|
|
44
|
-
await this.adb.shell([
|
|
45
|
-
'run-as',
|
|
46
|
-
util.quote(packageId),
|
|
47
|
-
`cp -f '${escapePath(pathInContainer)}' '${escapePath(tmpDestination)}'`,
|
|
48
|
-
]);
|
|
49
|
-
} catch (e) {
|
|
50
|
-
throw this.log.errorWithException(
|
|
51
|
-
`Cannot access the container of '${packageId}' application. ` +
|
|
52
|
-
`Is the application installed and has 'debuggable' build option set to true? ` +
|
|
53
|
-
`Original error: ${(e as Error).message}`,
|
|
54
|
-
);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
35
|
const localFile = await tempDir.path({prefix: 'appium', suffix: '.tmp'});
|
|
58
36
|
try {
|
|
37
|
+
if (remotePath.startsWith(CONTAINER_PATH_MARKER)) {
|
|
38
|
+
const [packageId, pathInContainer] = parseContainerPath(remotePath);
|
|
39
|
+
this.log.debug(
|
|
40
|
+
`Parsed package identifier '${packageId}' from '${remotePath}'. Will get the data from '${pathInContainer}'`,
|
|
41
|
+
);
|
|
42
|
+
try {
|
|
43
|
+
tmpDestination = await this.adb.shell(['mktemp', '/data/local/tmp/appium-pull-XXXXXX']);
|
|
44
|
+
// The shell user opens the destination; run-as only needs to read the source.
|
|
45
|
+
// App users cannot create files in /data/local/tmp on non-rooted devices.
|
|
46
|
+
await this.adb.shell([
|
|
47
|
+
'run-as',
|
|
48
|
+
util.quote(packageId),
|
|
49
|
+
'cat',
|
|
50
|
+
util.quote(pathInContainer),
|
|
51
|
+
'>',
|
|
52
|
+
util.quote(tmpDestination),
|
|
53
|
+
]);
|
|
54
|
+
} catch (e) {
|
|
55
|
+
throw this.log.errorWithException(
|
|
56
|
+
`Cannot access the container of '${packageId}' application. ` +
|
|
57
|
+
`Is the application installed and has 'debuggable' build option set to true? ` +
|
|
58
|
+
`Original error: ${(e as Error).message}`,
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
59
62
|
await this.adb.pull(tmpDestination || remotePath, localFile);
|
|
60
63
|
return (await util.toInMemoryBase64(localFile)).toString();
|
|
61
64
|
} finally {
|
|
62
|
-
|
|
63
|
-
await fs.
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
try {
|
|
66
|
+
if (await fs.exists(localFile)) {
|
|
67
|
+
await fs.unlink(localFile);
|
|
68
|
+
}
|
|
69
|
+
} finally {
|
|
70
|
+
if (tmpDestination) {
|
|
71
|
+
await this.adb.shell(['rm', '-f', util.quote(tmpDestination)]);
|
|
72
|
+
}
|
|
67
73
|
}
|
|
68
74
|
}
|
|
69
75
|
}
|
|
@@ -274,7 +280,14 @@ async function scanMedia(this: AndroidDriver, remotePath: string): Promise<void>
|
|
|
274
280
|
if ((await this.adb.getApiLevel()) >= 29) {
|
|
275
281
|
await this.settingsApp.scanMedia(remotePath);
|
|
276
282
|
} else {
|
|
277
|
-
await this.adb.shell([
|
|
283
|
+
await this.adb.shell([
|
|
284
|
+
'am',
|
|
285
|
+
'broadcast',
|
|
286
|
+
'-a',
|
|
287
|
+
ANDROID_MEDIA_RESCAN_INTENT,
|
|
288
|
+
'-d',
|
|
289
|
+
util.quote(`file://${remotePath}`),
|
|
290
|
+
]);
|
|
278
291
|
}
|
|
279
292
|
} catch (e) {
|
|
280
293
|
const err = e as {stderr?: string; message?: string};
|
|
@@ -298,7 +311,9 @@ function createFSTests(adb: ADB) {
|
|
|
298
311
|
const performRemoteFsCheck = async (p: string, op: 'd' | 'f' | 'e', runAs?: string): Promise<boolean> => {
|
|
299
312
|
const passFlag = '__PASS__';
|
|
300
313
|
const checkCmd = `[ -${op} '${escapePath(p)}' ] && echo ${passFlag}`;
|
|
301
|
-
|
|
314
|
+
// Older Android images provide [ as a shell builtin, not an executable
|
|
315
|
+
// that run-as can invoke directly.
|
|
316
|
+
const fullCmd = runAs ? `run-as ${util.quote(runAs)} sh -c '${escapePath(checkCmd)}'` : checkCmd;
|
|
302
317
|
try {
|
|
303
318
|
return (await adb.shell([fullCmd])).includes(passFlag);
|
|
304
319
|
} catch {
|