@rock-js/platform-android 0.8.13
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/README.md +7 -0
- package/dist/src/index.d.ts +3 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +4 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/lib/commands/aar/packageAar.d.ts +14 -0
- package/dist/src/lib/commands/aar/packageAar.d.ts.map +1 -0
- package/dist/src/lib/commands/aar/packageAar.js +34 -0
- package/dist/src/lib/commands/aar/packageAar.js.map +1 -0
- package/dist/src/lib/commands/aar/publishLocalAar.d.ts +6 -0
- package/dist/src/lib/commands/aar/publishLocalAar.d.ts.map +1 -0
- package/dist/src/lib/commands/aar/publishLocalAar.js +17 -0
- package/dist/src/lib/commands/aar/publishLocalAar.js.map +1 -0
- package/dist/src/lib/commands/buildAndroid/buildAndroid.d.ts +21 -0
- package/dist/src/lib/commands/buildAndroid/buildAndroid.d.ts.map +1 -0
- package/dist/src/lib/commands/buildAndroid/buildAndroid.js +68 -0
- package/dist/src/lib/commands/buildAndroid/buildAndroid.js.map +1 -0
- package/dist/src/lib/commands/buildAndroid/command.d.ts +3 -0
- package/dist/src/lib/commands/buildAndroid/command.d.ts.map +1 -0
- package/dist/src/lib/commands/buildAndroid/command.js +14 -0
- package/dist/src/lib/commands/buildAndroid/command.js.map +1 -0
- package/dist/src/lib/commands/generateKeystore.d.ts +13 -0
- package/dist/src/lib/commands/generateKeystore.d.ts.map +1 -0
- package/dist/src/lib/commands/generateKeystore.js +80 -0
- package/dist/src/lib/commands/generateKeystore.js.map +1 -0
- package/dist/src/lib/commands/getValidProjectConfig.d.ts +2 -0
- package/dist/src/lib/commands/getValidProjectConfig.d.ts.map +1 -0
- package/dist/src/lib/commands/getValidProjectConfig.js +10 -0
- package/dist/src/lib/commands/getValidProjectConfig.js.map +1 -0
- package/dist/src/lib/commands/runAndroid/adb.d.ts +5 -0
- package/dist/src/lib/commands/runAndroid/adb.d.ts.map +1 -0
- package/dist/src/lib/commands/runAndroid/adb.js +38 -0
- package/dist/src/lib/commands/runAndroid/adb.js.map +1 -0
- package/dist/src/lib/commands/runAndroid/command.d.ts +3 -0
- package/dist/src/lib/commands/runAndroid/command.d.ts.map +1 -0
- package/dist/src/lib/commands/runAndroid/command.js +15 -0
- package/dist/src/lib/commands/runAndroid/command.js.map +1 -0
- package/dist/src/lib/commands/runAndroid/findOutputFile.d.ts +2 -0
- package/dist/src/lib/commands/runAndroid/findOutputFile.d.ts.map +1 -0
- package/dist/src/lib/commands/runAndroid/findOutputFile.js +67 -0
- package/dist/src/lib/commands/runAndroid/findOutputFile.js.map +1 -0
- package/dist/src/lib/commands/runAndroid/listAndroidDevices.d.ts +7 -0
- package/dist/src/lib/commands/runAndroid/listAndroidDevices.d.ts.map +1 -0
- package/dist/src/lib/commands/runAndroid/listAndroidDevices.js +69 -0
- package/dist/src/lib/commands/runAndroid/listAndroidDevices.js.map +1 -0
- package/dist/src/lib/commands/runAndroid/listAndroidUsers.d.ts +7 -0
- package/dist/src/lib/commands/runAndroid/listAndroidUsers.d.ts.map +1 -0
- package/dist/src/lib/commands/runAndroid/listAndroidUsers.js +42 -0
- package/dist/src/lib/commands/runAndroid/listAndroidUsers.js.map +1 -0
- package/dist/src/lib/commands/runAndroid/runAndroid.d.ts +31 -0
- package/dist/src/lib/commands/runAndroid/runAndroid.d.ts.map +1 -0
- package/dist/src/lib/commands/runAndroid/runAndroid.js +178 -0
- package/dist/src/lib/commands/runAndroid/runAndroid.js.map +1 -0
- package/dist/src/lib/commands/runAndroid/tryInstallAppOnDevice.d.ts +3 -0
- package/dist/src/lib/commands/runAndroid/tryInstallAppOnDevice.d.ts.map +1 -0
- package/dist/src/lib/commands/runAndroid/tryInstallAppOnDevice.js +63 -0
- package/dist/src/lib/commands/runAndroid/tryInstallAppOnDevice.js.map +1 -0
- package/dist/src/lib/commands/runAndroid/tryLaunchAppOnDevice.d.ts +7 -0
- package/dist/src/lib/commands/runAndroid/tryLaunchAppOnDevice.d.ts.map +1 -0
- package/dist/src/lib/commands/runAndroid/tryLaunchAppOnDevice.js +51 -0
- package/dist/src/lib/commands/runAndroid/tryLaunchAppOnDevice.js.map +1 -0
- package/dist/src/lib/commands/runAndroid/tryLaunchEmulator.d.ts +2 -0
- package/dist/src/lib/commands/runAndroid/tryLaunchEmulator.d.ts.map +1 -0
- package/dist/src/lib/commands/runAndroid/tryLaunchEmulator.js +120 -0
- package/dist/src/lib/commands/runAndroid/tryLaunchEmulator.js.map +1 -0
- package/dist/src/lib/commands/runAndroid/tryRunAdbReverse.d.ts +1 -0
- package/dist/src/lib/commands/runAndroid/tryRunAdbReverse.d.ts.map +1 -0
- package/dist/src/lib/commands/runAndroid/tryRunAdbReverse.js +21 -0
- package/dist/src/lib/commands/runAndroid/tryRunAdbReverse.js.map +1 -0
- package/dist/src/lib/commands/runGradle.d.ts +18 -0
- package/dist/src/lib/commands/runGradle.d.ts.map +1 -0
- package/dist/src/lib/commands/runGradle.js +124 -0
- package/dist/src/lib/commands/runGradle.js.map +1 -0
- package/dist/src/lib/commands/signAndroid/bundle.d.ts +8 -0
- package/dist/src/lib/commands/signAndroid/bundle.d.ts.map +1 -0
- package/dist/src/lib/commands/signAndroid/bundle.js +58 -0
- package/dist/src/lib/commands/signAndroid/bundle.js.map +1 -0
- package/dist/src/lib/commands/signAndroid/command.d.ts +14 -0
- package/dist/src/lib/commands/signAndroid/command.d.ts.map +1 -0
- package/dist/src/lib/commands/signAndroid/command.js +67 -0
- package/dist/src/lib/commands/signAndroid/command.js.map +1 -0
- package/dist/src/lib/commands/signAndroid/signAndroid.d.ts +12 -0
- package/dist/src/lib/commands/signAndroid/signAndroid.d.ts.map +1 -0
- package/dist/src/lib/commands/signAndroid/signAndroid.js +163 -0
- package/dist/src/lib/commands/signAndroid/signAndroid.js.map +1 -0
- package/dist/src/lib/commands/toPascalCase.d.ts +1 -0
- package/dist/src/lib/commands/toPascalCase.d.ts.map +1 -0
- package/dist/src/lib/commands/toPascalCase.js +4 -0
- package/dist/src/lib/commands/toPascalCase.js.map +1 -0
- package/dist/src/lib/paths.d.ts +7 -0
- package/dist/src/lib/paths.d.ts.map +1 -0
- package/dist/src/lib/paths.js +60 -0
- package/dist/src/lib/paths.js.map +1 -0
- package/dist/src/lib/platformAndroid.d.ts +5 -0
- package/dist/src/lib/platformAndroid.d.ts.map +1 -0
- package/dist/src/lib/platformAndroid.js +23 -0
- package/dist/src/lib/platformAndroid.js.map +1 -0
- package/package.json +35 -0
- package/react-native.config.ts +13 -0
- package/template/.github/workflows/remote-build-android.yml +64 -0
- package/template/android/app/build.gradle +127 -0
- package/template/android/app/debug.keystore +0 -0
- package/template/android/app/proguard-rules.pro +10 -0
- package/template/android/app/src/debug/AndroidManifest.xml +9 -0
- package/template/android/app/src/main/AndroidManifest.xml +26 -0
- package/template/android/app/src/main/java/com/helloworld/MainActivity.kt +22 -0
- package/template/android/app/src/main/java/com/helloworld/MainApplication.kt +38 -0
- package/template/android/app/src/main/res/drawable/rn_edit_text_material.xml +37 -0
- package/template/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
- package/template/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png +0 -0
- package/template/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
- package/template/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png +0 -0
- package/template/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
- package/template/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png +0 -0
- package/template/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
- package/template/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png +0 -0
- package/template/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
- package/template/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png +0 -0
- package/template/android/app/src/main/res/values/strings.xml +3 -0
- package/template/android/app/src/main/res/values/styles.xml +9 -0
- package/template/android/build.gradle +21 -0
- package/template/android/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/template/android/gradle/wrapper/gradle-wrapper.properties +7 -0
- package/template/android/gradle.properties +46 -0
- package/template/android/gradlew +251 -0
- package/template/android/gradlew.bat +99 -0
- package/template/android/settings.gradle +6 -0
- package/template/package.json +9 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import os from 'node:os';
|
|
2
|
+
import { spawn } from '@rock-js/tools';
|
|
3
|
+
import { getAdbPath, getDevices } from './adb.js';
|
|
4
|
+
import { getEmulators } from './tryLaunchEmulator.js';
|
|
5
|
+
/**
|
|
6
|
+
*
|
|
7
|
+
* @param deviceId string
|
|
8
|
+
* @returns name of Android emulator
|
|
9
|
+
*/
|
|
10
|
+
async function getEmulatorName(deviceId) {
|
|
11
|
+
const adbPath = getAdbPath();
|
|
12
|
+
const { output } = await spawn(adbPath, ['-s', deviceId, 'emu', 'avd', 'name'], { stdio: 'pipe' });
|
|
13
|
+
// 1st line should get us emu name
|
|
14
|
+
return output
|
|
15
|
+
.split(os.EOL)[0]
|
|
16
|
+
.replace(/(\r\n|\n|\r)/gm, '')
|
|
17
|
+
.trim();
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
*
|
|
21
|
+
* @param deviceId string
|
|
22
|
+
* @returns Android device name in readable format
|
|
23
|
+
*/
|
|
24
|
+
async function getPhoneName(deviceId) {
|
|
25
|
+
const adbPath = getAdbPath();
|
|
26
|
+
const { output } = await spawn(adbPath, ['-s', deviceId, 'shell', 'getprop', 'ro.product.model'], { stdio: 'pipe' });
|
|
27
|
+
return output.replace(/\[ro\.product\.model\]:\s*\[(.*)\]/, '$1').trim();
|
|
28
|
+
}
|
|
29
|
+
export async function listAndroidDevices() {
|
|
30
|
+
const devices = await getDevices();
|
|
31
|
+
let allDevices = [];
|
|
32
|
+
for (const deviceId of devices) {
|
|
33
|
+
if (deviceId.includes('emulator')) {
|
|
34
|
+
const emulatorData = {
|
|
35
|
+
deviceId,
|
|
36
|
+
readableName: await getEmulatorName(deviceId),
|
|
37
|
+
connected: true,
|
|
38
|
+
type: 'emulator',
|
|
39
|
+
};
|
|
40
|
+
allDevices = [...allDevices, emulatorData];
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
const phoneData = {
|
|
44
|
+
deviceId,
|
|
45
|
+
readableName: await getPhoneName(deviceId),
|
|
46
|
+
type: 'phone',
|
|
47
|
+
connected: true,
|
|
48
|
+
};
|
|
49
|
+
allDevices = [...allDevices, phoneData];
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
const emulators = await getEmulators();
|
|
53
|
+
// Find not booted ones:
|
|
54
|
+
emulators.forEach((emulatorName) => {
|
|
55
|
+
// skip those already booted
|
|
56
|
+
if (allDevices.some((device) => device.readableName === emulatorName)) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const emulatorData = {
|
|
60
|
+
deviceId: undefined,
|
|
61
|
+
readableName: emulatorName,
|
|
62
|
+
type: 'emulator',
|
|
63
|
+
connected: false,
|
|
64
|
+
};
|
|
65
|
+
allDevices = [...allDevices, emulatorData];
|
|
66
|
+
});
|
|
67
|
+
return allDevices;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=listAndroidDevices.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"listAndroidDevices.js","sourceRoot":"","sources":["../../../../../src/lib/commands/runAndroid/listAndroidDevices.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAStD;;;;GAIG;AACH,KAAK,UAAU,eAAe,CAAC,QAAgB;IAC7C,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,KAAK,CAC5B,OAAO,EACP,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,CAAC,EACtC,EAAE,KAAK,EAAE,MAAM,EAAE,CAClB,CAAC;IAEF,kCAAkC;IAClC,OAAO,MAAM;SACV,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;SAChB,OAAO,CAAC,gBAAgB,EAAE,EAAE,CAAC;SAC7B,IAAI,EAAE,CAAC;AACZ,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,YAAY,CAAC,QAAgB;IAC1C,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,KAAK,CAC5B,OAAO,EACP,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,kBAAkB,CAAC,EACxD,EAAE,KAAK,EAAE,MAAM,EAAE,CAClB,CAAC;IACF,OAAO,MAAM,CAAC,OAAO,CAAC,oCAAoC,EAAE,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;AAC3E,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB;IACtC,MAAM,OAAO,GAAG,MAAM,UAAU,EAAE,CAAC;IAEnC,IAAI,UAAU,GAAsB,EAAE,CAAC;IAEvC,KAAK,MAAM,QAAQ,IAAI,OAAO,EAAE,CAAC;QAC/B,IAAI,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;YAClC,MAAM,YAAY,GAAe;gBAC/B,QAAQ;gBACR,YAAY,EAAE,MAAM,eAAe,CAAC,QAAQ,CAAC;gBAC7C,SAAS,EAAE,IAAI;gBACf,IAAI,EAAE,UAAU;aACjB,CAAC;YACF,UAAU,GAAG,CAAC,GAAG,UAAU,EAAE,YAAY,CAAC,CAAC;QAC7C,CAAC;aAAM,CAAC;YACN,MAAM,SAAS,GAAe;gBAC5B,QAAQ;gBACR,YAAY,EAAE,MAAM,YAAY,CAAC,QAAQ,CAAC;gBAC1C,IAAI,EAAE,OAAO;gBACb,SAAS,EAAE,IAAI;aAChB,CAAC;YACF,UAAU,GAAG,CAAC,GAAG,UAAU,EAAE,SAAS,CAAC,CAAC;QAC1C,CAAC;IACH,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,YAAY,EAAE,CAAC;IAEvC,wBAAwB;IACxB,SAAS,CAAC,OAAO,CAAC,CAAC,YAAY,EAAE,EAAE;QACjC,4BAA4B;QAC5B,IAAI,UAAU,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,YAAY,KAAK,YAAY,CAAC,EAAE,CAAC;YACtE,OAAO;QACT,CAAC;QACD,MAAM,YAAY,GAAe;YAC/B,QAAQ,EAAE,SAAS;YACnB,YAAY,EAAE,YAAY;YAC1B,IAAI,EAAE,UAAU;YAChB,SAAS,EAAE,KAAK;SACjB,CAAC;QACF,UAAU,GAAG,CAAC,GAAG,UAAU,EAAE,YAAY,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,OAAO,UAAU,CAAC;AACpB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"listAndroidUsers.d.ts","sourceRoot":"","sources":["../../../../../src/lib/commands/runAndroid/listAndroidUsers.ts"],"names":[],"mappings":"AAGA,KAAK,IAAI,GAAG;IACV,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAMF,wBAAsB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAgChE;AAED,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,wBAenD"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { logger, promptSelect, spawn } from '@rock-js/tools';
|
|
2
|
+
import { getAdbPath } from './adb.js';
|
|
3
|
+
const regex = new RegExp(/^\s*UserInfo\{(?<userId>\d+):(?<userName>.*):(?<userFlags>[0-9a-f]*)}/);
|
|
4
|
+
export async function checkUsers(device) {
|
|
5
|
+
const adbPath = getAdbPath();
|
|
6
|
+
const adbArgs = ['-s', device, 'shell', 'pm', 'list', 'users'];
|
|
7
|
+
try {
|
|
8
|
+
const { stdout, stderr } = await spawn(adbPath, adbArgs, { stdio: 'pipe' });
|
|
9
|
+
if (stderr) {
|
|
10
|
+
logger.debug(`Failed to check users on the device. ${stderr}`, 1);
|
|
11
|
+
return [];
|
|
12
|
+
}
|
|
13
|
+
const lines = stdout.split('\n');
|
|
14
|
+
const users = [];
|
|
15
|
+
for (const line of lines) {
|
|
16
|
+
const res = regex.exec(line);
|
|
17
|
+
if (res?.groups) {
|
|
18
|
+
users.push({ id: res.groups['userId'], name: res.groups['userName'] });
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return users;
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
logger.debug(`Unexpected error while checking users on the device. Continuing without user selection. Error details: ${error.message}.`, 1);
|
|
25
|
+
return [];
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export async function promptForUser(deviceId) {
|
|
29
|
+
const users = await checkUsers(deviceId);
|
|
30
|
+
if (users.length > 1) {
|
|
31
|
+
const selectedUser = await promptSelect({
|
|
32
|
+
message: 'Which user profile would you like to launch your app into?',
|
|
33
|
+
options: users.map((user) => ({
|
|
34
|
+
label: user.name,
|
|
35
|
+
value: user,
|
|
36
|
+
})),
|
|
37
|
+
});
|
|
38
|
+
return selectedUser;
|
|
39
|
+
}
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=listAndroidUsers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"listAndroidUsers.js","sourceRoot":"","sources":["../../../../../src/lib/commands/runAndroid/listAndroidUsers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAOtC,MAAM,KAAK,GAAG,IAAI,MAAM,CACtB,uEAAuE,CACxE,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,MAAc;IAC7C,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,OAAO,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IAE/D,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QAE5E,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,CAAC,KAAK,CAAC,wCAAwC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC;YAClE,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACjC,MAAM,KAAK,GAAG,EAAE,CAAC;QAEjB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC7B,IAAI,GAAG,EAAE,MAAM,EAAE,CAAC;gBAChB,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;YACzE,CAAC;QACH,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CACV,0GACG,KAA6B,CAAC,OACjC,GAAG,EACH,CAAC,CACF,CAAC;QACF,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,QAAgB;IAClD,MAAM,KAAK,GAAG,MAAM,UAAU,CAAC,QAAQ,CAAC,CAAC;IACzC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,MAAM,YAAY,GAAG,MAAM,YAAY,CAAC;YACtC,OAAO,EAAE,4DAA4D;YACrE,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;gBAC5B,KAAK,EAAE,IAAI,CAAC,IAAI;gBAChB,KAAK,EAAE,IAAI;aACZ,CAAC,CAAC;SACJ,CAAC,CAAC;QAEH,OAAO,YAAY,CAAC;IACtB,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { AndroidProjectConfig, Config } from '@react-native-community/cli-types';
|
|
2
|
+
import type { FingerprintSources, RemoteBuildCache } from '@rock-js/tools';
|
|
3
|
+
import type { BuildFlags } from '../buildAndroid/buildAndroid.js';
|
|
4
|
+
export interface Flags extends BuildFlags {
|
|
5
|
+
appId: string;
|
|
6
|
+
appIdSuffix: string;
|
|
7
|
+
mainActivity?: string;
|
|
8
|
+
port: string;
|
|
9
|
+
device?: string;
|
|
10
|
+
binaryPath?: string;
|
|
11
|
+
user?: string;
|
|
12
|
+
local?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export type AndroidProject = NonNullable<Config['project']['android']>;
|
|
15
|
+
/**
|
|
16
|
+
* Starts the app on a connected Android emulator or device.
|
|
17
|
+
*/
|
|
18
|
+
export declare function runAndroid(androidProject: AndroidProjectConfig, args: Flags, projectRoot: string, remoteCacheProvider: null | (() => RemoteBuildCache) | undefined, fingerprintOptions: FingerprintSources): Promise<void>;
|
|
19
|
+
export declare const runOptions: ({
|
|
20
|
+
name: string;
|
|
21
|
+
description: string;
|
|
22
|
+
parse?: undefined;
|
|
23
|
+
} | {
|
|
24
|
+
name: string;
|
|
25
|
+
description: string;
|
|
26
|
+
parse: (val: string) => string[];
|
|
27
|
+
} | {
|
|
28
|
+
name: string;
|
|
29
|
+
description: string;
|
|
30
|
+
default: string;
|
|
31
|
+
})[];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runAndroid.d.ts","sourceRoot":"","sources":["../../../../../src/lib/commands/runAndroid/runAndroid.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,oBAAoB,EACpB,MAAM,EACP,MAAM,mCAAmC,CAAC;AAC3C,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAaxE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAWlE,MAAM,WAAW,KAAM,SAAQ,UAAU;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,MAAM,cAAc,GAAG,WAAW,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;AAEvE;;GAEG;AACH,wBAAsB,UAAU,CAC9B,cAAc,EAAE,oBAAoB,EACpC,IAAI,EAAE,KAAK,EACX,WAAW,EAAE,MAAM,EACnB,mBAAmB,EAAE,IAAI,GAAG,CAAC,MAAM,gBAAgB,CAAC,GAAG,SAAS,EAChE,kBAAkB,EAAE,kBAAkB,iBA4DvC;AAmID,eAAO,MAAM,UAAU;;;;;;;;;;;;IAoCtB,CAAC"}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { color, formatArtifactName, intro, isInteractive, logger, outro, promptSelect, RockError, spinner, } from '@rock-js/tools';
|
|
4
|
+
import { getBinaryPath } from '@rock-js/tools';
|
|
5
|
+
import { options } from '../buildAndroid/buildAndroid.js';
|
|
6
|
+
import { runGradle } from '../runGradle.js';
|
|
7
|
+
import { toPascalCase } from '../toPascalCase.js';
|
|
8
|
+
import { getDevices } from './adb.js';
|
|
9
|
+
import { listAndroidDevices } from './listAndroidDevices.js';
|
|
10
|
+
import { tryInstallAppOnDevice } from './tryInstallAppOnDevice.js';
|
|
11
|
+
import { tryLaunchAppOnDevice } from './tryLaunchAppOnDevice.js';
|
|
12
|
+
import { tryLaunchEmulator } from './tryLaunchEmulator.js';
|
|
13
|
+
/**
|
|
14
|
+
* Starts the app on a connected Android emulator or device.
|
|
15
|
+
*/
|
|
16
|
+
export async function runAndroid(androidProject, args, projectRoot, remoteCacheProvider, fingerprintOptions) {
|
|
17
|
+
intro('Running Android app');
|
|
18
|
+
normalizeArgs(args, projectRoot);
|
|
19
|
+
const devices = await listAndroidDevices();
|
|
20
|
+
const device = await selectDevice(devices, args);
|
|
21
|
+
const mainTaskType = device ? 'assemble' : 'install';
|
|
22
|
+
const tasks = args.tasks ?? [`${mainTaskType}${toPascalCase(args.variant)}`];
|
|
23
|
+
const artifactName = await formatArtifactName({
|
|
24
|
+
platform: 'android',
|
|
25
|
+
traits: [args.variant],
|
|
26
|
+
root: projectRoot,
|
|
27
|
+
fingerprintOptions,
|
|
28
|
+
});
|
|
29
|
+
const binaryPath = await getBinaryPath({
|
|
30
|
+
artifactName,
|
|
31
|
+
binaryPathFlag: args.binaryPath,
|
|
32
|
+
localFlag: args.local,
|
|
33
|
+
remoteCacheProvider,
|
|
34
|
+
fingerprintOptions,
|
|
35
|
+
sourceDir: androidProject.sourceDir,
|
|
36
|
+
});
|
|
37
|
+
if (device) {
|
|
38
|
+
if (!(await getDevices()).find((d) => d === device.deviceId)) {
|
|
39
|
+
// deviceId is undefined until it's launched, hence overwriting it here
|
|
40
|
+
device.deviceId = await tryLaunchEmulator(device.readableName);
|
|
41
|
+
}
|
|
42
|
+
if (device.deviceId) {
|
|
43
|
+
if (!binaryPath) {
|
|
44
|
+
await runGradle({ tasks, androidProject, args, artifactName });
|
|
45
|
+
}
|
|
46
|
+
await runOnDevice({ device, androidProject, args, tasks, binaryPath });
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
if ((await getDevices()).length === 0) {
|
|
51
|
+
if (isInteractive()) {
|
|
52
|
+
await selectAndLaunchDevice();
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
logger.debug('No booted devices or emulators found. Launching first available emulator.');
|
|
56
|
+
await tryLaunchEmulator();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (!binaryPath) {
|
|
60
|
+
await runGradle({ tasks, androidProject, args, artifactName });
|
|
61
|
+
}
|
|
62
|
+
for (const device of await listAndroidDevices()) {
|
|
63
|
+
await runOnDevice({ device, androidProject, args, tasks, binaryPath });
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
outro('Success 🎉.');
|
|
67
|
+
}
|
|
68
|
+
async function selectAndLaunchDevice() {
|
|
69
|
+
const allDevices = await listAndroidDevices();
|
|
70
|
+
const device = await promptForDeviceSelection(allDevices);
|
|
71
|
+
if (!device.connected) {
|
|
72
|
+
await tryLaunchEmulator(device.readableName);
|
|
73
|
+
// list devices once again when emulator is booted
|
|
74
|
+
const allDevices = await listAndroidDevices();
|
|
75
|
+
const newDevice = allDevices.find((d) => d.readableName === device.readableName) ?? device;
|
|
76
|
+
return newDevice;
|
|
77
|
+
}
|
|
78
|
+
return device;
|
|
79
|
+
}
|
|
80
|
+
async function selectDevice(devices, args) {
|
|
81
|
+
const device = args.device ? matchingDevice(devices, args.device) : undefined;
|
|
82
|
+
if (!device && args.device) {
|
|
83
|
+
logger.warn(`No devices or emulators found matching "${args.device}". Using available one instead.`);
|
|
84
|
+
}
|
|
85
|
+
return device;
|
|
86
|
+
}
|
|
87
|
+
function matchingDevice(devices, deviceArg) {
|
|
88
|
+
const deviceByName = devices.find((device) => device.readableName === deviceArg);
|
|
89
|
+
const deviceById = devices.find((d) => d.deviceId === deviceArg);
|
|
90
|
+
return deviceByName || deviceById;
|
|
91
|
+
}
|
|
92
|
+
function normalizeArgs(args, projectRoot) {
|
|
93
|
+
if (args.tasks && args.variant) {
|
|
94
|
+
logger.warn('Both "--tasks" and "--variant" parameters were passed. Using "--tasks" for building the app.');
|
|
95
|
+
}
|
|
96
|
+
if (!args.variant) {
|
|
97
|
+
args.variant = 'debug';
|
|
98
|
+
}
|
|
99
|
+
// turn on activeArchOnly for debug to speed up local builds
|
|
100
|
+
if (args.variant !== 'release' &&
|
|
101
|
+
!args.variant.endsWith('Release') &&
|
|
102
|
+
args.activeArchOnly === undefined &&
|
|
103
|
+
isInteractive()) {
|
|
104
|
+
args.activeArchOnly = true;
|
|
105
|
+
}
|
|
106
|
+
if (args.binaryPath) {
|
|
107
|
+
if (args.tasks) {
|
|
108
|
+
throw new RockError('Both "--binary-path" and "--tasks" flags were specified, which are incompatible. Please specify only one.');
|
|
109
|
+
}
|
|
110
|
+
args.binaryPath = path.isAbsolute(args.binaryPath)
|
|
111
|
+
? args.binaryPath
|
|
112
|
+
: path.join(projectRoot, args.binaryPath);
|
|
113
|
+
if (args.binaryPath && !fs.existsSync(args.binaryPath)) {
|
|
114
|
+
throw new RockError(`"--binary-path" was specified, but the file was not found at "${args.binaryPath}".`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
async function promptForDeviceSelection(allDevices) {
|
|
119
|
+
if (!allDevices.length) {
|
|
120
|
+
throw new RockError('No devices and/or emulators connected. Please create emulator with Android Studio or connect Android device.');
|
|
121
|
+
}
|
|
122
|
+
const selected = await promptSelect({
|
|
123
|
+
message: 'Select the device / emulator you want to use',
|
|
124
|
+
options: allDevices.map((d) => ({
|
|
125
|
+
label: `${d.readableName}${d.type === 'phone' ? ' - (physical device)' : ''}${d.connected ? ' (connected)' : ''}`,
|
|
126
|
+
value: d,
|
|
127
|
+
})),
|
|
128
|
+
});
|
|
129
|
+
return selected;
|
|
130
|
+
}
|
|
131
|
+
async function runOnDevice({ device, androidProject, args, tasks, binaryPath, }) {
|
|
132
|
+
const loader = spinner();
|
|
133
|
+
loader.start('Installing the app');
|
|
134
|
+
await tryInstallAppOnDevice(device, androidProject, args, tasks, binaryPath);
|
|
135
|
+
loader.message('Launching the app');
|
|
136
|
+
const { applicationIdWithSuffix } = await tryLaunchAppOnDevice(device, androidProject, args);
|
|
137
|
+
if (applicationIdWithSuffix) {
|
|
138
|
+
loader.stop(`Installed and launched the app on ${color.bold(device.readableName)}`);
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
loader.stop(`Failed: installing and launching the app on ${color.bold(device.readableName)}`);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
export const runOptions = [
|
|
145
|
+
...options,
|
|
146
|
+
{
|
|
147
|
+
name: '--port <number>',
|
|
148
|
+
description: 'Part for packager.',
|
|
149
|
+
default: process.env['RCT_METRO_PORT'] || '8081',
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
name: '--app-id <string>',
|
|
153
|
+
description: 'Specify an applicationId to launch after build. If not specified, `package` from AndroidManifest.xml will be used.',
|
|
154
|
+
default: '',
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
name: '--app-id-suffix <string>',
|
|
158
|
+
description: 'Specify an applicationIdSuffix to launch after build.',
|
|
159
|
+
default: '',
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
name: '--main-activity <string>',
|
|
163
|
+
description: 'Name of the activity to start',
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
name: '--device <string>',
|
|
167
|
+
description: 'Explicitly set the device or emulator to use by name or ID (if launched).',
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
name: '--binary-path <string>',
|
|
171
|
+
description: 'Path relative to project root where pre-built .apk binary lives.',
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
name: '--user <number>',
|
|
175
|
+
description: 'Id of the User Profile you want to install the app on.',
|
|
176
|
+
},
|
|
177
|
+
];
|
|
178
|
+
//# sourceMappingURL=runAndroid.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runAndroid.js","sourceRoot":"","sources":["../../../../../src/lib/commands/runAndroid/runAndroid.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { DeviceData } from './listAndroidDevices.js';
|
|
2
|
+
import type { AndroidProject, Flags } from './runAndroid.js';
|
|
3
|
+
export declare function tryInstallAppOnDevice(device: DeviceData, androidProject: AndroidProject, args: Flags, tasks: string[], binaryPath: string | undefined): Promise<void>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tryInstallAppOnDevice.d.ts","sourceRoot":"","sources":["../../../../../src/lib/commands/runAndroid/tryInstallAppOnDevice.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAE1D,OAAO,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAE7D,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,UAAU,EAClB,cAAc,EAAE,cAAc,EAC9B,IAAI,EAAE,KAAK,EACX,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,MAAM,GAAG,SAAS,iBAyE/B"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { color, logger, RockError, spawn, } from '@rock-js/tools';
|
|
2
|
+
import { getAdbPath } from './adb.js';
|
|
3
|
+
import { findOutputFile } from './findOutputFile.js';
|
|
4
|
+
import { promptForUser } from './listAndroidUsers.js';
|
|
5
|
+
export async function tryInstallAppOnDevice(device, androidProject, args, tasks, binaryPath) {
|
|
6
|
+
let deviceId;
|
|
7
|
+
if (!device.deviceId) {
|
|
8
|
+
logger.debug(`No device with id "${device.deviceId}", skipping launching the app.`);
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
else {
|
|
12
|
+
deviceId = device.deviceId;
|
|
13
|
+
}
|
|
14
|
+
logger.debug(`Connected to device ${color.bold(device.readableName)}`);
|
|
15
|
+
let pathToApk;
|
|
16
|
+
if (!binaryPath) {
|
|
17
|
+
const outputFilePath = await findOutputFile(androidProject, tasks, deviceId);
|
|
18
|
+
if (!outputFilePath) {
|
|
19
|
+
logger.warn("Skipping installation because there's no build output file.");
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
pathToApk = outputFilePath;
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
pathToApk = binaryPath;
|
|
26
|
+
}
|
|
27
|
+
const adbArgs = ['-s', deviceId, 'install', '-r', '-d'];
|
|
28
|
+
const user = args.user ?? (await promptForUser(deviceId))?.id;
|
|
29
|
+
if (user !== undefined) {
|
|
30
|
+
adbArgs.push('--user', `${user}`);
|
|
31
|
+
}
|
|
32
|
+
adbArgs.push(pathToApk);
|
|
33
|
+
const adbPath = getAdbPath();
|
|
34
|
+
try {
|
|
35
|
+
await spawn(adbPath, adbArgs, { stdio: 'pipe' });
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
logger.debug(`Failed: Installing the app`, error);
|
|
39
|
+
const errorMessage = error.stderr || error.stdout;
|
|
40
|
+
const isInsufficientStorage = errorMessage.includes('INSTALL_FAILED_INSUFFICIENT_STORAGE');
|
|
41
|
+
const isUpdateIncompatible = errorMessage.includes('INSTALL_FAILED_UPDATE_INCOMPATIBLE');
|
|
42
|
+
if (isInsufficientStorage || isUpdateIncompatible) {
|
|
43
|
+
try {
|
|
44
|
+
const message = isInsufficientStorage
|
|
45
|
+
? 'Recovery: Trying to re-install the app due to insufficient storage'
|
|
46
|
+
: 'Recovery: Trying to re-install the app due to binary incompatibility';
|
|
47
|
+
logger.debug(message);
|
|
48
|
+
const appId = args.appId || androidProject.applicationId;
|
|
49
|
+
await spawn(adbPath, ['-s', deviceId, 'uninstall', appId]);
|
|
50
|
+
await spawn(adbPath, adbArgs);
|
|
51
|
+
logger.debug(`Recovery: Re-installed the app`);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
const errorMessage = error.stderr ||
|
|
56
|
+
error.stdout;
|
|
57
|
+
throw new RockError(`The "adb" command failed with: ${errorMessage}.`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
throw new RockError(`The "adb" command failed with: ${errorMessage}.`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=tryInstallAppOnDevice.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tryInstallAppOnDevice.js","sourceRoot":"","sources":["../../../../../src/lib/commands/runAndroid/tryInstallAppOnDevice.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { DeviceData } from './listAndroidDevices.js';
|
|
2
|
+
import type { AndroidProject, Flags } from './runAndroid.js';
|
|
3
|
+
export declare function tryLaunchAppOnDevice(device: DeviceData, androidProject: AndroidProject, args: Flags): Promise<{
|
|
4
|
+
applicationIdWithSuffix?: undefined;
|
|
5
|
+
} | {
|
|
6
|
+
applicationIdWithSuffix: string;
|
|
7
|
+
}>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tryLaunchAppOnDevice.d.ts","sourceRoot":"","sources":["../../../../../src/lib/commands/runAndroid/tryLaunchAppOnDevice.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAG7D,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,UAAU,EAClB,cAAc,EAAE,cAAc,EAC9B,IAAI,EAAE,KAAK;;;;GAsDZ"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { logger, RockError, spawn } from '@rock-js/tools';
|
|
2
|
+
import { getAdbPath } from './adb.js';
|
|
3
|
+
import { tryRunAdbReverse } from './tryRunAdbReverse.js';
|
|
4
|
+
export async function tryLaunchAppOnDevice(device, androidProject, args) {
|
|
5
|
+
let deviceId;
|
|
6
|
+
if (!device.deviceId) {
|
|
7
|
+
logger.debug(`No device with id "${device.deviceId}", skipping launching the app.`);
|
|
8
|
+
return {};
|
|
9
|
+
}
|
|
10
|
+
else {
|
|
11
|
+
deviceId = device.deviceId;
|
|
12
|
+
}
|
|
13
|
+
await tryRunAdbReverse(args.port, deviceId);
|
|
14
|
+
const { appId, appIdSuffix } = args;
|
|
15
|
+
const { packageName, mainActivity, applicationId } = androidProject;
|
|
16
|
+
const applicationIdWithSuffix = [appId || applicationId, appIdSuffix]
|
|
17
|
+
.filter(Boolean)
|
|
18
|
+
.join('.');
|
|
19
|
+
const activity = args.mainActivity ?? mainActivity;
|
|
20
|
+
const activityToLaunch = activity.startsWith(packageName) ||
|
|
21
|
+
(!activity.startsWith('.') && activity.includes('.'))
|
|
22
|
+
? activity
|
|
23
|
+
: activity.startsWith('.')
|
|
24
|
+
? [packageName, activity].join('')
|
|
25
|
+
: [packageName, activity].filter(Boolean).join('.');
|
|
26
|
+
// Here we're using the same flags as Android Studio to launch the app
|
|
27
|
+
const adbArgs = [
|
|
28
|
+
'shell',
|
|
29
|
+
'am',
|
|
30
|
+
'start',
|
|
31
|
+
'-n',
|
|
32
|
+
`${applicationIdWithSuffix}/${activityToLaunch}`,
|
|
33
|
+
'-a',
|
|
34
|
+
'android.intent.action.MAIN',
|
|
35
|
+
'-c',
|
|
36
|
+
'android.intent.category.LAUNCHER',
|
|
37
|
+
];
|
|
38
|
+
adbArgs.unshift('-s', deviceId);
|
|
39
|
+
const adbPath = getAdbPath();
|
|
40
|
+
logger.debug(`Running ${adbPath} ${adbArgs.join(' ')}.`);
|
|
41
|
+
try {
|
|
42
|
+
await spawn(adbPath, adbArgs);
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
throw new RockError(`Failed to launch the app on ${device.readableName}`, {
|
|
46
|
+
cause: error.stderr,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
return { applicationIdWithSuffix };
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=tryLaunchAppOnDevice.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tryLaunchAppOnDevice.js","sourceRoot":"","sources":["../../../../../src/lib/commands/runAndroid/tryLaunchAppOnDevice.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAwB,MAAM,gBAAgB,CAAC;AAChF,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAGtC,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzD,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,MAAkB,EAClB,cAA8B,EAC9B,IAAW;IAEX,IAAI,QAAQ,CAAC;IACb,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;QACrB,MAAM,CAAC,KAAK,CACV,sBAAsB,MAAM,CAAC,QAAQ,gCAAgC,CACtE,CAAC;QACF,OAAO,EAAE,CAAC;IACZ,CAAC;SAAM,CAAC;QACN,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;IAC7B,CAAC;IACD,MAAM,gBAAgB,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC5C,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC;IACpC,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,aAAa,EAAE,GAAG,cAAc,CAAC;IAEpE,MAAM,uBAAuB,GAAG,CAAC,KAAK,IAAI,aAAa,EAAE,WAAW,CAAC;SAClE,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,GAAG,CAAC,CAAC;IAEb,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,IAAI,YAAY,CAAC;IAEnD,MAAM,gBAAgB,GACpB,QAAQ,CAAC,UAAU,CAAC,WAAW,CAAC;QAChC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QACnD,CAAC,CAAC,QAAQ;QACV,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC;YACxB,CAAC,CAAC,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;YAClC,CAAC,CAAC,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAE1D,sEAAsE;IACtE,MAAM,OAAO,GAAG;QACd,OAAO;QACP,IAAI;QACJ,OAAO;QACP,IAAI;QACJ,GAAG,uBAAuB,IAAI,gBAAgB,EAAE;QAChD,IAAI;QACJ,4BAA4B;QAC5B,IAAI;QACJ,kCAAkC;KACnC,CAAC;IAEF,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAEhC,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,CAAC,KAAK,CAAC,WAAW,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACzD,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAChC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,SAAS,CAAC,+BAA+B,MAAM,CAAC,YAAY,EAAE,EAAE;YACxE,KAAK,EAAG,KAAyB,CAAC,MAAM;SACzC,CAAC,CAAC;IACL,CAAC;IACD,OAAO,EAAE,uBAAuB,EAAE,CAAC;AACrC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tryLaunchEmulator.d.ts","sourceRoot":"","sources":["../../../../../src/lib/commands/runAndroid/tryLaunchEmulator.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,YAAY,yBAexB,CAAC;AA2EF,wBAAsB,iBAAiB,CAAC,IAAI,CAAC,EAAE,MAAM,+BAsCpD"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import os from 'node:os';
|
|
2
|
+
import { color, RockError, spawn, spinner } from '@rock-js/tools';
|
|
3
|
+
import { getAdbPath, getDevices } from './adb.js';
|
|
4
|
+
const emulatorCommand = process.env['ANDROID_HOME']
|
|
5
|
+
? `${process.env['ANDROID_HOME']}/emulator/emulator`
|
|
6
|
+
: 'emulator';
|
|
7
|
+
export const getEmulators = async () => {
|
|
8
|
+
try {
|
|
9
|
+
const { output } = await spawn(emulatorCommand, ['-list-avds'], {
|
|
10
|
+
stdio: 'pipe',
|
|
11
|
+
});
|
|
12
|
+
// The `name` is AVD ID which is expected to not contain whitespace.
|
|
13
|
+
// The `emulator` command, however, can occasionally return verbose
|
|
14
|
+
// information about crashes or similar. Hence filtering out anything
|
|
15
|
+
// that has basic whitespace.
|
|
16
|
+
return output
|
|
17
|
+
.split(os.EOL)
|
|
18
|
+
.filter((name) => name !== '' && !name.includes(' '));
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return [];
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
const launchEmulator = async ({ emulatorName, port, onConnected, }) => {
|
|
25
|
+
const manualCommand = `${emulatorCommand} @${emulatorName}`;
|
|
26
|
+
const cp = spawn(emulatorCommand, [`@${emulatorName}`, '-port', `${port}`], {
|
|
27
|
+
detached: true,
|
|
28
|
+
stdio: 'ignore',
|
|
29
|
+
});
|
|
30
|
+
(await cp.nodeChildProcess).unref();
|
|
31
|
+
const timeout = 120;
|
|
32
|
+
return new Promise((resolve, reject) => {
|
|
33
|
+
const bootCheckInterval = setInterval(async () => {
|
|
34
|
+
const devices = await getDevices();
|
|
35
|
+
const connected = port
|
|
36
|
+
? devices.find((d) => d.includes(`${port}`))
|
|
37
|
+
: false;
|
|
38
|
+
if (connected) {
|
|
39
|
+
onConnected();
|
|
40
|
+
if (await isEmulatorBooted(connected)) {
|
|
41
|
+
cleanup();
|
|
42
|
+
resolve(connected);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}, 1000);
|
|
46
|
+
// Reject command after timeout
|
|
47
|
+
const rejectTimeout = setTimeout(() => {
|
|
48
|
+
stopWaitingAndReject(`It took too long to start and connect with Android emulator: ${emulatorName}. You can try starting the emulator manually from the terminal with: ${manualCommand}`);
|
|
49
|
+
}, timeout * 1000);
|
|
50
|
+
const cleanup = () => {
|
|
51
|
+
clearTimeout(rejectTimeout);
|
|
52
|
+
clearInterval(bootCheckInterval);
|
|
53
|
+
};
|
|
54
|
+
const stopWaitingAndReject = (message) => {
|
|
55
|
+
cleanup();
|
|
56
|
+
reject(new Error(message));
|
|
57
|
+
};
|
|
58
|
+
cp.nodeChildProcess.catch((error) => {
|
|
59
|
+
stopWaitingAndReject(error);
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
};
|
|
63
|
+
const defaultPort = 5552;
|
|
64
|
+
async function getAvailableDevicePort(port = defaultPort) {
|
|
65
|
+
/**
|
|
66
|
+
* The default value is 5554 for the first virtual device instance running on your machine. A virtual device normally occupies a pair of adjacent ports: a console port and an adb port. The console of the first virtual device running on a particular machine uses console port 5554 and adb port 5555. Subsequent instances use port numbers increasing by two. For example, 5556/5557, 5558/5559, and so on. The range is 5554 to 5682, allowing for 64 concurrent virtual devices.
|
|
67
|
+
*/
|
|
68
|
+
const devices = await getDevices();
|
|
69
|
+
if (port > 5682) {
|
|
70
|
+
throw new RockError('Failed to launch emulator');
|
|
71
|
+
}
|
|
72
|
+
if (devices.some((d) => d.includes(port.toString()))) {
|
|
73
|
+
return await getAvailableDevicePort(port + 2);
|
|
74
|
+
}
|
|
75
|
+
return port;
|
|
76
|
+
}
|
|
77
|
+
export async function tryLaunchEmulator(name) {
|
|
78
|
+
const port = await getAvailableDevicePort();
|
|
79
|
+
const loader = spinner();
|
|
80
|
+
loader.start(`Looking for available emulators"`);
|
|
81
|
+
const emulators = await getEmulators();
|
|
82
|
+
const emulatorName = name ?? emulators[0];
|
|
83
|
+
const displayEmulatorName = color.bold(emulatorName);
|
|
84
|
+
let deviceId;
|
|
85
|
+
if (emulators.length > 0) {
|
|
86
|
+
try {
|
|
87
|
+
loader.message(`Launching emulator ${displayEmulatorName}`);
|
|
88
|
+
deviceId = await launchEmulator({
|
|
89
|
+
emulatorName,
|
|
90
|
+
port,
|
|
91
|
+
onConnected: () => {
|
|
92
|
+
loader.message(`Emulator ${color.bold(emulatorName)} is connected. Waiting for boot`);
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
loader.stop(`Launched ${displayEmulatorName} emulator.`);
|
|
96
|
+
}
|
|
97
|
+
catch (error) {
|
|
98
|
+
loader.stop(`Failed to launch ${displayEmulatorName} emulator. ${error.message}`, 1);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
loader.stop('No emulators found as an output of `emulator -list-avds`. Please launch an emulator manually or connect a device', 1);
|
|
103
|
+
}
|
|
104
|
+
return deviceId;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Check if emulator is booted
|
|
108
|
+
*/
|
|
109
|
+
async function isEmulatorBooted(device) {
|
|
110
|
+
const adbPath = getAdbPath();
|
|
111
|
+
const adbArgs = ['-s', device, 'shell', 'getprop', 'sys.boot_completed'];
|
|
112
|
+
try {
|
|
113
|
+
const { output } = await spawn(adbPath, adbArgs, { stdio: 'pipe' });
|
|
114
|
+
return output.trim() === '1';
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=tryLaunchEmulator.js.map
|