Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Device/emulator detection fixes #4483

Merged
merged 5 commits into from
Mar 29, 2019
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions PublicAPI.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ const tns = require("nativescript");
* [devicesService](#devicesservice)
* [getEmulatorImages](#getemulatorimages)
* [startEmulator](#startemulator)
* [startDeviceDetectionInterval](#startdevicedetectioninterval)
* [stopDeviceDetectionInterval](#stopdevicedetectioninterval)
* [startEmulatorDetectionInterval](#startemulatordetectioninterval)
* [stopEmulatorDetectionInterval](#stopemulatordetectioninterval)
* [deviceEmitter](#deviceemitter)
* [events](#deviceemitterevents)
* [previewDevicesService](#previewdevicesservice)
Expand Down Expand Up @@ -1287,6 +1291,59 @@ tns.devicesService.startEmulator({imageIdentifier: "my emulator imageIdentifier"
.then(errors => { });
```

### startDeviceDetectionInterval
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.
> NOTE: The interval is started automatically when you call `devicesService.initialize` without passing `skipDeviceDetectionInterval: true`.

> NOTE: iOS Device detection interval cannot be stopped, so once started, it will always report connected/disconnected devices.

* Definition
```TypeScript
startDeviceDetectionInterval({ detectionInterval?: number, platform?: string }): void
```

* Usage
```JavaScript
tns.devicesService.startDeviceDetectionInterval({ detectionInterval: 1000 });
```

### stopDeviceDetectionInterval
Stops device detection interval started by `devicesService.initialize` or `devicesService.startDeviceDetectionInterval`.
* Definition
```TypeScript
stopDeviceDetectionInterval(): void
```

* Usage
```JavaScript
tns.devicesService.stopDeviceDetectionInterval();
```

### startEmulatorDetectionInterval
Starts emulator images detection interval, which is run on specified number of seconds. This allows detection of new installed emulator/simulator images.

* Definition
```TypeScript
startEmulatorDetectionInterval({ detectionInterval?: number }): void
```

* Usage
```JavaScript
tns.devicesService.startEmulatorDetectionInterval({ detectionInterval: 1000 });
```

### stopEmulatorDetectionInterval
Stops device detection interval started by `devicesService.startEmulatorDetectionInterval`.
* Definition
```TypeScript
stopEmulatorDetectionInterval(): void
```

* Usage
```JavaScript
tns.devicesService.stopEmulatorDetectionInterval();
```

## deviceEmitter
This module is used to emit information for devices, applications on them, etc.

Expand Down
1 change: 1 addition & 0 deletions lib/common/bootstrap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ $injector.require("errors", "./errors");
$injector.requirePublic("fs", "./file-system");
$injector.require("hostInfo", "./host-info");
$injector.require("osInfo", "./os-info");
$injector.require("timers", "./timers");

$injector.require("dispatcher", "./dispatchers");
$injector.require("commandDispatcher", "./dispatchers");
Expand Down
12 changes: 12 additions & 0 deletions lib/common/declarations.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -992,6 +992,18 @@ interface ISysInfo {
*/
getJavaCompilerVersion(): Promise<string>;

/**
* Gets JAVA version based on the executable in PATH.
* @return {Promise<string>}
*/
getJavaVersionFromPath(): Promise<string>;

/**
* Gets JAVA version based on the JAVA from JAVA_HOME.
* @return {Promise<string>}
*/
getJavaVersionFromJavaHome(): Promise<string>;

/**
* Gets all global warnings for the current environment, for example Node.js version compatibility, OS compatibility, etc.
* @return {Promise<ISystemWarning[]>} All warnings. Empty array is returned in case the system is setup correctly.
Expand Down
16 changes: 6 additions & 10 deletions lib/common/definitions/mobile.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -387,11 +387,7 @@ declare module Mobile {
/**
* Describes options that can be passed to devices service's initialization method.
*/
interface IDevicesServicesInitializationOptions {
/**
* The platform for which to initialize. If passed will detect only devices belonging to said platform.
*/
platform?: string;
interface IDevicesServicesInitializationOptions extends Partial<IDeviceLookingOptions> {
/**
* If passed will start an emulator if necesasry.
*/
Expand All @@ -412,10 +408,6 @@ declare module Mobile {
* Specifies whether we should skip the emulator starting.
*/
skipEmulatorStart?: boolean;
/**
* Defines if the initialization should await the whole iOS detection to finish or it can just start the detection.
*/
shouldReturnImmediateResult?: boolean;
/**
* Currently available only for iOS. Specifies the sdk version of the iOS simulator.
* 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.
Expand Down Expand Up @@ -1029,7 +1021,11 @@ declare module Mobile {
resolveProductName(deviceType: string): string;
}

interface IDeviceLookingOptions extends IHasEmulatorOption {
interface IHasDetectionInterval {
detectionInterval?: number;
}

interface IDeviceLookingOptions extends IHasEmulatorOption, IHasDetectionInterval {
shouldReturnImmediateResult: boolean;
platform: string;
}
Expand Down
3 changes: 3 additions & 0 deletions lib/common/definitions/timers.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
interface ITimers {
setInterval(callback: (...args: any[]) => void, ms: number, ...args: any[]): NodeJS.Timer;
}
23 changes: 22 additions & 1 deletion lib/common/mobile/android/android-virtual-device-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export class AndroidVirtualDeviceService implements Mobile.IAndroidVirtualDevice
private $emulatorHelper: Mobile.IEmulatorHelper,
private $fs: IFileSystem,
private $hostInfo: IHostInfo,
private $sysInfo: ISysInfo,
private $logger: ILogger) {
this.androidHome = process.env.ANDROID_HOME;
}
Expand Down Expand Up @@ -152,8 +153,12 @@ export class AndroidVirtualDeviceService implements Mobile.IAndroidVirtualDevice
let result: ISpawnResult = null;
let devices: Mobile.IDeviceInfo[] = [];
let errors: string[] = [];
const canExecuteAvdManagerCommand = await this.canExecuteAvdManagerCommand();
if (!canExecuteAvdManagerCommand) {
errors = ["Unable to execute avdmanager, ensure JAVA_HOME is set and points to correct directory"];
}

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

@cache()
private async canExecuteAvdManagerCommand(): Promise<boolean> {
let canExecute = false;
if (this.pathToAvdManagerExecutable && this.$fs.exists(this.pathToAvdManagerExecutable)) {
if (process.env.JAVA_HOME) {
// 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
// no matter if you have correct java in PATH.
canExecute = !!(await this.$sysInfo.getJavaVersionFromJavaHome());
} else {
canExecute = !!(await this.$sysInfo.getJavaVersionFromPath());
}
}

return canExecute;
}

private async getRunningEmulatorData(runningEmulatorId: string, availableEmulators: Mobile.IDeviceInfo[]): Promise<Mobile.IDeviceInfo> {
const imageIdentifier = await this.getRunningEmulatorImageIdentifier(runningEmulatorId);
const runningEmulator = this.$emulatorHelper.getEmulatorByImageIdentifier(imageIdentifier, availableEmulators);
Expand Down
Loading