Skip to content

Commit 2748bba

Browse files
Merge pull request #4483 from NativeScript/vladimirov/device-detections-fixes
Device/emulator detection fixes
2 parents 4971447 + 59eb28c commit 2748bba

15 files changed

+270
-94
lines changed

PublicAPI.md

+57
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ const tns = require("nativescript");
5858
* [devicesService](#devicesservice)
5959
* [getEmulatorImages](#getemulatorimages)
6060
* [startEmulator](#startemulator)
61+
* [startDeviceDetectionInterval](#startdevicedetectioninterval)
62+
* [stopDeviceDetectionInterval](#stopdevicedetectioninterval)
63+
* [startEmulatorDetectionInterval](#startemulatordetectioninterval)
64+
* [stopEmulatorDetectionInterval](#stopemulatordetectioninterval)
6165
* [deviceEmitter](#deviceemitter)
6266
* [events](#deviceemitterevents)
6367
* [previewDevicesService](#previewdevicesservice)
@@ -1287,6 +1291,59 @@ tns.devicesService.startEmulator({imageIdentifier: "my emulator imageIdentifier"
12871291
.then(errors => { });
12881292
```
12891293
1294+
### startDeviceDetectionInterval
1295+
Starts device detection interval, which is run on specified number of seconds. This allows detection of new attached devices, started emulators/simulators, detection when device/emulator/simulator is disconnected, etc.
1296+
> NOTE: The interval is started automatically when you call `devicesService.initialize` without passing `skipDeviceDetectionInterval: true`.
1297+
1298+
> NOTE: iOS Device detection interval cannot be stopped, so once started, it will always report connected/disconnected devices.
1299+
1300+
* Definition
1301+
```TypeScript
1302+
startDeviceDetectionInterval({ detectionInterval?: number, platform?: string }): void
1303+
```
1304+
1305+
* Usage
1306+
```JavaScript
1307+
tns.devicesService.startDeviceDetectionInterval({ detectionInterval: 1000 });
1308+
```
1309+
1310+
### stopDeviceDetectionInterval
1311+
Stops device detection interval started by `devicesService.initialize` or `devicesService.startDeviceDetectionInterval`.
1312+
* Definition
1313+
```TypeScript
1314+
stopDeviceDetectionInterval(): void
1315+
```
1316+
1317+
* Usage
1318+
```JavaScript
1319+
tns.devicesService.stopDeviceDetectionInterval();
1320+
```
1321+
1322+
### startEmulatorDetectionInterval
1323+
Starts emulator images detection interval, which is run on specified number of seconds. This allows detection of new installed emulator/simulator images.
1324+
1325+
* Definition
1326+
```TypeScript
1327+
startEmulatorDetectionInterval({ detectionInterval?: number }): void
1328+
```
1329+
1330+
* Usage
1331+
```JavaScript
1332+
tns.devicesService.startEmulatorDetectionInterval({ detectionInterval: 1000 });
1333+
```
1334+
1335+
### stopEmulatorDetectionInterval
1336+
Stops device detection interval started by `devicesService.startEmulatorDetectionInterval`.
1337+
* Definition
1338+
```TypeScript
1339+
stopEmulatorDetectionInterval(): void
1340+
```
1341+
1342+
* Usage
1343+
```JavaScript
1344+
tns.devicesService.stopEmulatorDetectionInterval();
1345+
```
1346+
12901347
## deviceEmitter
12911348
This module is used to emit information for devices, applications on them, etc.
12921349

lib/common/bootstrap.ts

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ $injector.require("errors", "./errors");
66
$injector.requirePublic("fs", "./file-system");
77
$injector.require("hostInfo", "./host-info");
88
$injector.require("osInfo", "./os-info");
9+
$injector.require("timers", "./timers");
910

1011
$injector.require("dispatcher", "./dispatchers");
1112
$injector.require("commandDispatcher", "./dispatchers");

lib/common/declarations.d.ts

+12
Original file line numberDiff line numberDiff line change
@@ -992,6 +992,18 @@ interface ISysInfo {
992992
*/
993993
getJavaCompilerVersion(): Promise<string>;
994994

995+
/**
996+
* Gets JAVA version based on the executable in PATH.
997+
* @return {Promise<string>}
998+
*/
999+
getJavaVersionFromPath(): Promise<string>;
1000+
1001+
/**
1002+
* Gets JAVA version based on the JAVA from JAVA_HOME.
1003+
* @return {Promise<string>}
1004+
*/
1005+
getJavaVersionFromJavaHome(): Promise<string>;
1006+
9951007
/**
9961008
* Gets all global warnings for the current environment, for example Node.js version compatibility, OS compatibility, etc.
9971009
* @return {Promise<ISystemWarning[]>} All warnings. Empty array is returned in case the system is setup correctly.

lib/common/definitions/mobile.d.ts

+6-10
Original file line numberDiff line numberDiff line change
@@ -387,11 +387,7 @@ declare module Mobile {
387387
/**
388388
* Describes options that can be passed to devices service's initialization method.
389389
*/
390-
interface IDevicesServicesInitializationOptions {
391-
/**
392-
* The platform for which to initialize. If passed will detect only devices belonging to said platform.
393-
*/
394-
platform?: string;
390+
interface IDevicesServicesInitializationOptions extends Partial<IDeviceLookingOptions> {
395391
/**
396392
* If passed will start an emulator if necesasry.
397393
*/
@@ -412,10 +408,6 @@ declare module Mobile {
412408
* Specifies whether we should skip the emulator starting.
413409
*/
414410
skipEmulatorStart?: boolean;
415-
/**
416-
* Defines if the initialization should await the whole iOS detection to finish or it can just start the detection.
417-
*/
418-
shouldReturnImmediateResult?: boolean;
419411
/**
420412
* Currently available only for iOS. Specifies the sdk version of the iOS simulator.
421413
* In case when `tns run ios --device "iPhone 6"` command is executed, the user can specify the sdk of the simulator because it is possible to have more than one device with the same name but with different sdk versions.
@@ -1029,7 +1021,11 @@ declare module Mobile {
10291021
resolveProductName(deviceType: string): string;
10301022
}
10311023

1032-
interface IDeviceLookingOptions extends IHasEmulatorOption {
1024+
interface IHasDetectionInterval {
1025+
detectionInterval?: number;
1026+
}
1027+
1028+
interface IDeviceLookingOptions extends IHasEmulatorOption, IHasDetectionInterval {
10331029
shouldReturnImmediateResult: boolean;
10341030
platform: string;
10351031
}

lib/common/definitions/timers.d.ts

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
interface ITimers {
2+
setInterval(callback: (...args: any[]) => void, ms: number, ...args: any[]): NodeJS.Timer;
3+
clearInterval(intervalId: NodeJS.Timer): void;
4+
}

lib/common/mobile/android/android-virtual-device-service.ts

+22-1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export class AndroidVirtualDeviceService implements Mobile.IAndroidVirtualDevice
1616
private $emulatorHelper: Mobile.IEmulatorHelper,
1717
private $fs: IFileSystem,
1818
private $hostInfo: IHostInfo,
19+
private $sysInfo: ISysInfo,
1920
private $logger: ILogger) {
2021
this.androidHome = process.env.ANDROID_HOME;
2122
}
@@ -152,8 +153,12 @@ export class AndroidVirtualDeviceService implements Mobile.IAndroidVirtualDevice
152153
let result: ISpawnResult = null;
153154
let devices: Mobile.IDeviceInfo[] = [];
154155
let errors: string[] = [];
156+
const canExecuteAvdManagerCommand = await this.canExecuteAvdManagerCommand();
157+
if (!canExecuteAvdManagerCommand) {
158+
errors = ["Unable to execute avdmanager, ensure JAVA_HOME is set and points to correct directory"];
159+
}
155160

156-
if (this.pathToAvdManagerExecutable && this.$fs.exists(this.pathToAvdManagerExecutable)) {
161+
if (canExecuteAvdManagerCommand) {
157162
result = await this.$childProcess.trySpawnFromCloseEvent(this.pathToAvdManagerExecutable, ["list", "avds"]);
158163
} else if (this.pathToAndroidExecutable && this.$fs.exists(this.pathToAndroidExecutable)) {
159164
result = await this.$childProcess.trySpawnFromCloseEvent(this.pathToAndroidExecutable, ["list", "avd"]);
@@ -169,6 +174,22 @@ export class AndroidVirtualDeviceService implements Mobile.IAndroidVirtualDevice
169174
return { devices, errors };
170175
}
171176

177+
@cache()
178+
private async canExecuteAvdManagerCommand(): Promise<boolean> {
179+
let canExecute = false;
180+
if (this.pathToAvdManagerExecutable && this.$fs.exists(this.pathToAvdManagerExecutable)) {
181+
if (process.env.JAVA_HOME) {
182+
// In case JAVA_HOME is set, but it points to incorrect directory (i.e. there's no java in $JAVA_HOME/bin/java), avdmanager will fail
183+
// no matter if you have correct java in PATH.
184+
canExecute = !!(await this.$sysInfo.getJavaVersionFromJavaHome());
185+
} else {
186+
canExecute = !!(await this.$sysInfo.getJavaVersionFromPath());
187+
}
188+
}
189+
190+
return canExecute;
191+
}
192+
172193
private async getRunningEmulatorData(runningEmulatorId: string, availableEmulators: Mobile.IDeviceInfo[]): Promise<Mobile.IDeviceInfo> {
173194
const imageIdentifier = await this.getRunningEmulatorImageIdentifier(runningEmulatorId);
174195
const runningEmulator = this.$emulatorHelper.getEmulatorByImageIdentifier(imageIdentifier, availableEmulators);

0 commit comments

Comments
 (0)