From 5d01b4175440a1d0904326b16ce63556c2cacb54 Mon Sep 17 00:00:00 2001 From: vchimev Date: Tue, 27 Feb 2018 17:30:17 +0200 Subject: [PATCH 1/6] feat(android): add "Don't keep activities" abilities This allows you to turn on/off "Don't keep activities" setting in the Developer options for Android. --- lib/android-controller.d.ts | 2 ++ lib/android-controller.ts | 17 +++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/lib/android-controller.d.ts b/lib/android-controller.d.ts index 7fd5e2e..fbe6786 100644 --- a/lib/android-controller.d.ts +++ b/lib/android-controller.d.ts @@ -58,6 +58,8 @@ export declare class AndroidController { private static checkAndroid(); private static executeAdbCommand(device, command); private static gettokenPrefix(type); + private static getAlwaysFinishActivitiesGlobalSettingsValue(device); + static setDontKeepActivities(value: boolean, device: IDevice): void; } export declare class AndroidDevice extends Device { constructor(name: string, apiLevel: any, type: DeviceType, token?: string, status?: Status, pid?: number); diff --git a/lib/android-controller.ts b/lib/android-controller.ts index 85807e4..3d3de16 100644 --- a/lib/android-controller.ts +++ b/lib/android-controller.ts @@ -583,6 +583,23 @@ export class AndroidController { private static gettokenPrefix(type: DeviceType) { return type === DeviceType.DEVICE ? "" : "emulator-"; } + + private static getAlwaysFinishActivitiesGlobalSettingsValue(device: IDevice): boolean { + const prefix = AndroidController.gettokenPrefix(device.type); + return executeCommand(AndroidController.ADB + " -s " + `${prefix}${device.token}` + " shell settings get global always_finish_activities").trim() === "1"; + } + + public static setDontKeepActivities(value: boolean, device: IDevice) { + let status: 0 | 1; + value ? status = 1 : status = 0; + + const prefix = AndroidController.gettokenPrefix(device.type); + executeCommand(AndroidController.ADB + ` -s ${prefix}${device.token} shell service call activity 43 i32 ${status}`); + + if (this.getAlwaysFinishActivitiesGlobalSettingsValue(device) !== value) { + throw new Error(`Failed to set \"Don't keep activities\" to ${value}!`); + } + } } export class AndroidDevice extends Device { From db80284a997a007839ce4451e48d13fcc171d26b Mon Sep 17 00:00:00 2001 From: vchimev Date: Tue, 27 Feb 2018 19:28:52 +0200 Subject: [PATCH 2/6] refactor(android-controller): setDontKeepActivities method --- lib/android-controller.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/android-controller.ts b/lib/android-controller.ts index 3d3de16..21a0f08 100644 --- a/lib/android-controller.ts +++ b/lib/android-controller.ts @@ -590,14 +590,13 @@ export class AndroidController { } public static setDontKeepActivities(value: boolean, device: IDevice) { - let status: 0 | 1; - value ? status = 1 : status = 0; - + const status = value ? 0 : 1; const prefix = AndroidController.gettokenPrefix(device.type); - executeCommand(AndroidController.ADB + ` -s ${prefix}${device.token} shell service call activity 43 i32 ${status}`); + const command = `${AndroidController.ADB} -s ${prefix}${device.token} shell service call activity 43 i32 ${status}`; + executeCommand(command); if (this.getAlwaysFinishActivitiesGlobalSettingsValue(device) !== value) { - throw new Error(`Failed to set \"Don't keep activities\" to ${value}!`); + throw new Error(`Failed to set "Don't keep activities" to ${value}!`); } } } From 5d1cb40698590f0f9fa9829ff504ae81ca0f2196 Mon Sep 17 00:00:00 2001 From: vchimev Date: Tue, 27 Feb 2018 19:35:11 +0200 Subject: [PATCH 3/6] refactor(android-controller): getAlwaysFinishActivitiesGlobalSettingsValue method --- lib/android-controller.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/android-controller.ts b/lib/android-controller.ts index 21a0f08..3b6f933 100644 --- a/lib/android-controller.ts +++ b/lib/android-controller.ts @@ -586,7 +586,9 @@ export class AndroidController { private static getAlwaysFinishActivitiesGlobalSettingsValue(device: IDevice): boolean { const prefix = AndroidController.gettokenPrefix(device.type); - return executeCommand(AndroidController.ADB + " -s " + `${prefix}${device.token}` + " shell settings get global always_finish_activities").trim() === "1"; + const command = `${AndroidController.ADB} -s ${prefix}${device.token} shell settings get global always_finish_activities`; + const result = executeCommand(command).trim() === "1"; + return result; } public static setDontKeepActivities(value: boolean, device: IDevice) { From 464970864a451cc59c639d39bb44f42a332b9c98 Mon Sep 17 00:00:00 2001 From: vchimev Date: Tue, 27 Feb 2018 21:29:24 +0200 Subject: [PATCH 4/6] refactor(android-controller): add executeAdbShellCommand method --- lib/android-controller.d.ts | 5 ++-- lib/android-controller.ts | 54 ++++++++++++++++++++----------------- 2 files changed, 32 insertions(+), 27 deletions(-) diff --git a/lib/android-controller.d.ts b/lib/android-controller.d.ts index fbe6786..743fc75 100644 --- a/lib/android-controller.d.ts +++ b/lib/android-controller.d.ts @@ -57,8 +57,9 @@ export declare class AndroidController { private static sendKeyCommand; private static checkAndroid(); private static executeAdbCommand(device, command); - private static gettokenPrefix(type); - private static getAlwaysFinishActivitiesGlobalSettingsValue(device); + private static executeAdbShellCommand(device, command); + private static getTokenPrefix(type); + private static getAlwaysFinishActivitiesGlobalSettingValue(device); static setDontKeepActivities(value: boolean, device: IDevice): void; } export declare class AndroidDevice extends Device { diff --git a/lib/android-controller.ts b/lib/android-controller.ts index 3b6f933..cdb0fd4 100644 --- a/lib/android-controller.ts +++ b/lib/android-controller.ts @@ -36,7 +36,7 @@ export class AndroidController { } public static getPhysicalDensity(device: IDevice) { - return parseInt(AndroidController.executeAdbCommand(device, "shell wm density").split(":")[1]) * 0.01; + return parseInt(AndroidController.executeAdbShellCommand(device, "wm density").split(":")[1]) * 0.01; } public static getPixelsOffset(device: IDevice) { @@ -147,7 +147,7 @@ export class AndroidController { } public isAppRunning(device: IDevice, appId: string) { - const result = AndroidController.executeAdbCommand(device, "shell ps"); + const result = AndroidController.executeAdbShellCommand(device, "ps"); if (result.includes(appId)) { return true; } else { @@ -157,12 +157,12 @@ export class AndroidController { public static startApplication(device: IDevice, fullAppName: string) { const appId = AndroidController.installApp(device, fullAppName); - let command = "shell monkey -p " + appId + " 1"; - Promise.resolve(AndroidController.executeAdbCommand(device, command)); + const commandToExecute = "monkey -p " + appId + " 1"; + Promise.resolve(AndroidController.executeAdbShellCommand(device, commandToExecute)); } public static getInstalledApps(device) { - const list = AndroidController.executeAdbCommand(device, `shell pm list packages -3`).split("\n"); + const list = AndroidController.executeAdbShellCommand(device, `pm list packages -3`).split("\n"); return list; } @@ -208,13 +208,13 @@ export class AndroidController { } public static stopApp(device: IDevice, appId) { - AndroidController.executeAdbCommand(device, `shell am force-stop ${appId}`); + AndroidController.executeAdbShellCommand(device, `am force-stop ${appId}`); } public static async getScreenshot(device: IDevice, dir, fileName) { fileName = fileName.endsWith(".pne") ? fileName : `${fileName}.png`; const pathToScreenshotPng = `/sdcard/${fileName}`; - AndroidController.executeAdbCommand(device, `shell screencap ${pathToScreenshotPng}`); + AndroidController.executeAdbShellCommand(device, `screencap ${pathToScreenshotPng}`); const fullFileName = resolve(dir, fileName); AndroidController.pullFile(device, pathToScreenshotPng, fullFileName); return fullFileName; @@ -238,9 +238,8 @@ export class AndroidController { const videoFileName = `${fileName}.mp4`; const pathToVideo = resolve(dir, videoFileName); const devicePath = `/sdcard/${videoFileName}`; - const prefix = AndroidController.gettokenPrefix(device.type); + const prefix = AndroidController.getTokenPrefix(device.type); const videoRecoringProcess = spawn(AndroidController.ADB, ['-s', `${prefix}${device.token}`, 'shell', 'screenrecord', `${devicePath}`]); - return { pathToVideo: pathToVideo, devicePath: devicePath, videoRecoringProcess: videoRecoringProcess }; } @@ -252,7 +251,7 @@ export class AndroidController { const destinationFolder = dirname(destinationFile); // Verify remotePath const remoteBasePath = remotePath.substring(0, remotePath.lastIndexOf("/")); - const sdcardFiles = AndroidController.executeAdbCommand(device, " shell ls -la " + remoteBasePath); + const sdcardFiles = AndroidController.executeAdbShellCommand(device, "ls -la " + remoteBasePath); if (sdcardFiles.includes("No such file or directory")) { const error = remoteBasePath + " does not exist."; console.log(error); @@ -282,11 +281,11 @@ export class AndroidController { public static pushFile(device: IDevice, fileName, deviceParh) { - let output = AndroidController.executeAdbCommand(device, "shell mount -o rw,remount -t rootfs /"); + let output = AndroidController.executeAdbShellCommand(device, "mount -o rw,remount -t rootfs /"); // Verify remotePath const remoteBasePath = deviceParh.substring(0, deviceParh.lastIndexOf("/")); - const sdcardFiles = AndroidController.executeAdbCommand(device, "shell ls -la " + remoteBasePath); + const sdcardFiles = AndroidController.executeAdbShellCommand(device, "ls -la " + remoteBasePath); if (sdcardFiles.includes("No such file or directory")) { const error = remoteBasePath + " does not exist."; console.log(error); @@ -576,28 +575,33 @@ export class AndroidController { } private static executeAdbCommand(device: IDevice, command: string) { - const prefix = AndroidController.gettokenPrefix(device.type); - return executeCommand(`${AndroidController.ADB} -s ${prefix}${device.token} ${command}`); + const prefix = AndroidController.getTokenPrefix(device.type); + const commandToExecute = `${AndroidController.ADB} -s ${prefix}${device.token} ${command}`; + const result = executeCommand(commandToExecute); + return result; + } + + private static executeAdbShellCommand(device: IDevice, command: string) { + const commandToExecute = `shell ${command}`; + const result = AndroidController.executeAdbCommand(device, commandToExecute); + return result; } - private static gettokenPrefix(type: DeviceType) { + private static getTokenPrefix(type: DeviceType) { return type === DeviceType.DEVICE ? "" : "emulator-"; } - private static getAlwaysFinishActivitiesGlobalSettingsValue(device: IDevice): boolean { - const prefix = AndroidController.gettokenPrefix(device.type); - const command = `${AndroidController.ADB} -s ${prefix}${device.token} shell settings get global always_finish_activities`; - const result = executeCommand(command).trim() === "1"; + private static getAlwaysFinishActivitiesGlobalSettingValue(device: IDevice): boolean { + const commandToExecute = `settings get global always_finish_activities`; + const result = AndroidController.executeAdbShellCommand(device, commandToExecute).trim() === "1"; return result; } public static setDontKeepActivities(value: boolean, device: IDevice) { - const status = value ? 0 : 1; - const prefix = AndroidController.gettokenPrefix(device.type); - const command = `${AndroidController.ADB} -s ${prefix}${device.token} shell service call activity 43 i32 ${status}`; - - executeCommand(command); - if (this.getAlwaysFinishActivitiesGlobalSettingsValue(device) !== value) { + const status = value ? 1 : 0; + const commandToExecute = `service call activity 43 i32 ${status}`; + AndroidController.executeAdbShellCommand(device, commandToExecute); + if (AndroidController.getAlwaysFinishActivitiesGlobalSettingValue(device) !== value) { throw new Error(`Failed to set "Don't keep activities" to ${value}!`); } } From d64efd158a3cbdd524f102192ed53a304153f9b6 Mon Sep 17 00:00:00 2001 From: vchimev Date: Wed, 28 Feb 2018 09:22:40 +0200 Subject: [PATCH 5/6] refactor(android-controller): rebase on origin/master --- lib/android-controller.d.ts | 2 +- lib/android-controller.ts | 13 ++++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/lib/android-controller.d.ts b/lib/android-controller.d.ts index 743fc75..d25b54c 100644 --- a/lib/android-controller.d.ts +++ b/lib/android-controller.d.ts @@ -58,7 +58,7 @@ export declare class AndroidController { private static checkAndroid(); private static executeAdbCommand(device, command); private static executeAdbShellCommand(device, command); - private static getTokenPrefix(type); + private static getTokenPrefix(device); private static getAlwaysFinishActivitiesGlobalSettingValue(device); static setDontKeepActivities(value: boolean, device: IDevice): void; } diff --git a/lib/android-controller.ts b/lib/android-controller.ts index cdb0fd4..9a46cf5 100644 --- a/lib/android-controller.ts +++ b/lib/android-controller.ts @@ -72,7 +72,7 @@ export class AndroidController { public static reboot(emulator: IDevice) { AndroidController.executeAdbCommand(emulator, 'reboot bootloader'); - AndroidController.waitUntilEmulatorBoot(emulator, AndroidController.DEFAULT_BOOT_TIME); + AndroidController.waitUntilEmulatorBoot(emulator.token, AndroidController.DEFAULT_BOOT_TIME); } public static unlock(token, password = undefined) { @@ -238,7 +238,7 @@ export class AndroidController { const videoFileName = `${fileName}.mp4`; const pathToVideo = resolve(dir, videoFileName); const devicePath = `/sdcard/${videoFileName}`; - const prefix = AndroidController.getTokenPrefix(device.type); + const prefix = AndroidController.getTokenPrefix(device); const videoRecoringProcess = spawn(AndroidController.ADB, ['-s', `${prefix}${device.token}`, 'shell', 'screenrecord', `${devicePath}`]); return { pathToVideo: pathToVideo, devicePath: devicePath, videoRecoringProcess: videoRecoringProcess }; } @@ -575,7 +575,7 @@ export class AndroidController { } private static executeAdbCommand(device: IDevice, command: string) { - const prefix = AndroidController.getTokenPrefix(device.type); + const prefix = AndroidController.getTokenPrefix(device); const commandToExecute = `${AndroidController.ADB} -s ${prefix}${device.token} ${command}`; const result = executeCommand(commandToExecute); return result; @@ -587,8 +587,11 @@ export class AndroidController { return result; } - private static getTokenPrefix(type: DeviceType) { - return type === DeviceType.DEVICE ? "" : "emulator-"; + private static getTokenPrefix(device: IDevice) { + if (device.type === DeviceType.EMULATOR && !device.token.startsWith("emulator")) { + return "emulator-"; + } + return ""; } private static getAlwaysFinishActivitiesGlobalSettingValue(device: IDevice): boolean { From 1057c2fbfafd94f5c5599828127b5c7bf96aec71 Mon Sep 17 00:00:00 2001 From: vchimev Date: Wed, 28 Feb 2018 09:47:25 +0200 Subject: [PATCH 6/6] refactor(android-controller): getTokenPrefix method --- lib/android-controller.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/android-controller.ts b/lib/android-controller.ts index 9a46cf5..0ebb275 100644 --- a/lib/android-controller.ts +++ b/lib/android-controller.ts @@ -588,10 +588,8 @@ export class AndroidController { } private static getTokenPrefix(device: IDevice) { - if (device.type === DeviceType.EMULATOR && !device.token.startsWith("emulator")) { - return "emulator-"; - } - return ""; + const result = device.type === DeviceType.EMULATOR && !device.token.startsWith("emulator") ? "emulator-" : ""; + return result; } private static getAlwaysFinishActivitiesGlobalSettingValue(device: IDevice): boolean {