@@ -157,7 +157,9 @@ export class DevicesService extends EventEmitter implements Mobile.IDevicesServi
157
157
/**
158
158
* Starts looking for devices. Any found devices are pushed to "_devices" variable.
159
159
*/
160
- public async detectCurrentlyAttachedDevices ( options ?: Mobile . IDeviceLookingOptions ) : Promise < void > {
160
+ protected async detectCurrentlyAttachedDevices ( deviceInitOpts ?: Mobile . IDevicesServicesInitializationOptions ) : Promise < void > {
161
+ const options = this . getDeviceLookingOptions ( deviceInitOpts ) ;
162
+
161
163
for ( const deviceDiscovery of this . _allDeviceDiscoveries ) {
162
164
try {
163
165
await deviceDiscovery . startLookingForDevices ( options ) ;
@@ -167,49 +169,42 @@ export class DevicesService extends EventEmitter implements Mobile.IDevicesServi
167
169
}
168
170
}
169
171
170
- public async startDeviceDetectionInterval ( ) : Promise < void > {
172
+ protected async startDeviceDetectionInterval ( deviceInitOpts : Mobile . IDevicesServicesInitializationOptions = { } ) : Promise < void > {
171
173
this . $processService . attachToProcessExitSignals ( this , this . clearDeviceDetectionInterval ) ;
172
174
173
175
if ( this . deviceDetectionInterval ) {
174
176
this . $logger . trace ( "Device detection interval is already started. New Interval will not be started." ) ;
175
- } else {
176
- let isFirstExecution = true ;
177
+ return ;
178
+ }
179
+ let isFirstExecution = true ;
177
180
178
- return new Promise < void > ( ( resolve , reject ) => {
179
- this . deviceDetectionInterval = setInterval ( async ( ) => {
180
- if ( this . isDeviceDetectionIntervalInProgress ) {
181
- return ;
182
- }
181
+ return new Promise < void > ( ( resolve , reject ) => {
182
+ this . deviceDetectionInterval = setInterval ( async ( ) => {
183
+ if ( this . isDeviceDetectionIntervalInProgress ) {
184
+ return ;
185
+ }
183
186
184
- this . isDeviceDetectionIntervalInProgress = true ;
187
+ this . isDeviceDetectionIntervalInProgress = true ;
185
188
186
- for ( const deviceDiscovery of this . _allDeviceDiscoveries ) {
187
- try {
188
- const deviceLookingOptions = this . getDeviceLookingOptions ( ) ;
189
- await deviceDiscovery . startLookingForDevices ( deviceLookingOptions ) ;
190
- } catch ( err ) {
191
- this . $logger . trace ( "Error while checking for new devices." , err ) ;
192
- }
193
- }
189
+ await this . detectCurrentlyAttachedDevices ( deviceInitOpts ) ;
194
190
195
- try {
196
- const trustedDevices = _ . filter ( this . _devices , device => device . deviceInfo . status === constants . CONNECTED_STATUS ) ;
197
- await settlePromises ( _ . map ( trustedDevices , device => device . applicationManager . checkForApplicationUpdates ( ) ) ) ;
198
- } catch ( err ) {
199
- this . $logger . trace ( "Error checking for application updates on devices." , err ) ;
200
- }
191
+ try {
192
+ const trustedDevices = _ . filter ( this . _devices , device => device . deviceInfo . status === constants . CONNECTED_STATUS ) ;
193
+ await settlePromises ( _ . map ( trustedDevices , device => device . applicationManager . checkForApplicationUpdates ( ) ) ) ;
194
+ } catch ( err ) {
195
+ this . $logger . trace ( "Error checking for application updates on devices." , err ) ;
196
+ }
201
197
202
- if ( isFirstExecution ) {
203
- isFirstExecution = false ;
204
- resolve ( ) ;
205
- this . deviceDetectionInterval . unref ( ) ;
206
- }
198
+ if ( isFirstExecution ) {
199
+ isFirstExecution = false ;
200
+ resolve ( ) ;
201
+ this . deviceDetectionInterval . unref ( ) ;
202
+ }
207
203
208
- this . isDeviceDetectionIntervalInProgress = false ;
204
+ this . isDeviceDetectionIntervalInProgress = false ;
209
205
210
- } , DevicesService . DEVICE_LOOKING_INTERVAL ) ;
211
- } ) ;
212
- }
206
+ } , DevicesService . DEVICE_LOOKING_INTERVAL ) ;
207
+ } ) ;
213
208
}
214
209
215
210
/**
@@ -234,30 +229,14 @@ export class DevicesService extends EventEmitter implements Mobile.IDevicesServi
234
229
/**
235
230
* Starts looking for running devices. All found devices are pushed to _devices variable.
236
231
*/
237
- private async startLookingForDevices ( options ?: Mobile . IDeviceLookingOptions ) : Promise < void > {
232
+ private startLookingForDevices ( deviceInitOpts ?: Mobile . IDevicesServicesInitializationOptions ) : Promise < void > {
238
233
this . $logger . trace ( "startLookingForDevices; platform is %s" , this . _platform ) ;
239
- if ( ! options ) {
240
- options = this . getDeviceLookingOptions ( ) ;
241
- }
242
- if ( ! this . _platform ) {
243
- await this . detectCurrentlyAttachedDevices ( options ) ;
244
- await this . startDeviceDetectionInterval ( ) ;
245
- } else {
246
- if ( this . $mobileHelper . isiOSPlatform ( this . _platform ) ) {
247
- await this . $iOSDeviceDiscovery . startLookingForDevices ( options ) ;
248
- await this . $iOSSimulatorDiscovery . startLookingForDevices ( options ) ;
249
- } else if ( this . $mobileHelper . isAndroidPlatform ( this . _platform ) ) {
250
- await this . $androidDeviceDiscovery . startLookingForDevices ( options ) ;
251
- }
252
234
253
- for ( const deviceDiscovery of this . _otherDeviceDiscoveries ) {
254
- try {
255
- await deviceDiscovery . startLookingForDevices ( options ) ;
256
- } catch ( err ) {
257
- this . $logger . trace ( "Error while checking for new devices." , err ) ;
258
- }
259
- }
235
+ if ( this . _platform ) {
236
+ return this . detectCurrentlyAttachedDevices ( deviceInitOpts ) ;
260
237
}
238
+
239
+ return this . startDeviceDetectionInterval ( deviceInitOpts ) ;
261
240
}
262
241
263
242
/**
@@ -276,8 +255,6 @@ export class DevicesService extends EventEmitter implements Mobile.IDevicesServi
276
255
* @param identifier parameter passed by the user to --device flag
277
256
*/
278
257
public async getDevice ( deviceOption : string ) : Promise < Mobile . IDevice > {
279
- const deviceLookingOptions = this . getDeviceLookingOptions ( ) ;
280
- await this . detectCurrentlyAttachedDevices ( deviceLookingOptions ) ;
281
258
let device : Mobile . IDevice = null ;
282
259
283
260
let emulatorIdentifier = null ;
@@ -390,34 +367,34 @@ export class DevicesService extends EventEmitter implements Mobile.IDevicesServi
390
367
/**
391
368
* Starts emulator or simulator if necessary depending on --device or --emulator flags.
392
369
* If no options are passed runs default emulator/simulator if no devices are connected.
393
- * @param data mainly contains information about --emulator and --deviceId flags.
370
+ * @param deviceInitOpts mainly contains information about --emulator and --deviceId flags.
394
371
*/
395
- public async startEmulatorIfNecessary ( data ?: Mobile . IDevicesServicesInitializationOptions ) : Promise < void > {
396
- if ( data && data . deviceId && data . emulator ) {
372
+ protected async startEmulatorIfNecessary ( deviceInitOpts ?: Mobile . IDevicesServicesInitializationOptions ) : Promise < void > {
373
+ if ( deviceInitOpts && deviceInitOpts . deviceId && deviceInitOpts . emulator ) {
397
374
this . $errors . failWithoutHelp ( `--device and --emulator are incompatible options.
398
375
If you are trying to run on specific emulator, use "${ this . $staticConfig . CLIENT_NAME } run --device <DeviceID>` ) ;
399
376
}
400
377
401
- if ( data && data . platform && ! data . skipEmulatorStart ) {
378
+ if ( deviceInitOpts && deviceInitOpts . platform && ! deviceInitOpts . skipEmulatorStart ) {
402
379
// are there any running devices
403
- this . _platform = data . platform ;
380
+ this . _platform = deviceInitOpts . platform ;
404
381
try {
405
- await this . startLookingForDevices ( ) ;
382
+ await this . startLookingForDevices ( deviceInitOpts ) ;
406
383
} catch ( err ) {
407
384
this . $logger . trace ( "Error while checking for devices." , err ) ;
408
385
}
409
386
const deviceInstances = this . getDeviceInstances ( ) ;
410
387
411
- if ( ! data . deviceId && _ . isEmpty ( deviceInstances ) ) {
412
- if ( ! this . $hostInfo . isDarwin && this . $mobileHelper . isiOSPlatform ( data . platform ) ) {
388
+ if ( ! deviceInitOpts . deviceId && _ . isEmpty ( deviceInstances ) ) {
389
+ if ( ! this . $hostInfo . isDarwin && this . $mobileHelper . isiOSPlatform ( deviceInitOpts . platform ) ) {
413
390
this . $errors . failWithoutHelp ( constants . ERROR_NO_DEVICES_CANT_USE_IOS_SIMULATOR ) ;
414
391
}
415
392
}
416
393
417
394
try {
418
- await this . _startEmulatorIfNecessary ( data ) ;
395
+ await this . _startEmulatorIfNecessary ( deviceInitOpts ) ;
419
396
} catch ( err ) {
420
- const errorMessage = this . getEmulatorError ( err , data . platform ) ;
397
+ const errorMessage = this . getEmulatorError ( err , deviceInitOpts . platform ) ;
421
398
422
399
this . $errors . failWithoutHelp ( errorMessage ) ;
423
400
}
@@ -429,15 +406,15 @@ export class DevicesService extends EventEmitter implements Mobile.IDevicesServi
429
406
430
407
//if no --device is passed and no devices are found, the default emulator is started
431
408
if ( ! data . deviceId && _ . isEmpty ( deviceInstances ) ) {
432
- return this . startEmulator ( data . platform ) ;
409
+ return this . startEmulator ( data ) ;
433
410
}
434
411
435
412
//check if --device(value) is running, if it's not or it's not the same as is specified, start with name from --device(value)
436
413
if ( data . deviceId ) {
437
414
if ( ! helpers . isNumber ( data . deviceId ) ) {
438
415
const activeDeviceInstance = _ . find ( deviceInstances , ( device : Mobile . IDevice ) => device . deviceInfo . identifier === data . deviceId ) ;
439
416
if ( ! activeDeviceInstance ) {
440
- return this . startEmulator ( data . platform , data . deviceId ) ;
417
+ return this . startEmulator ( data ) ;
441
418
}
442
419
}
443
420
}
@@ -446,11 +423,12 @@ export class DevicesService extends EventEmitter implements Mobile.IDevicesServi
446
423
if ( data . emulator && deviceInstances . length ) {
447
424
const runningDeviceInstance = _ . some ( deviceInstances , ( value ) => value . isEmulator ) ;
448
425
if ( ! runningDeviceInstance ) {
449
- return this . startEmulator ( data . platform ) ;
426
+ return this . startEmulator ( data ) ;
450
427
}
451
428
}
452
429
}
453
430
431
+ private _deviceInitializePromise : Promise < void > ;
454
432
/**
455
433
* Takes care of gathering information about all running devices.
456
434
* Sets "_isInitialized" to true after infomation is present.
@@ -459,46 +437,64 @@ export class DevicesService extends EventEmitter implements Mobile.IDevicesServi
459
437
*/
460
438
@exported ( "devicesService" )
461
439
public async initialize ( data ?: Mobile . IDevicesServicesInitializationOptions ) : Promise < void > {
440
+ if ( ! this . _deviceInitializePromise ) {
441
+ this . _deviceInitializePromise = this . initializeCore ( data ) ;
442
+ }
443
+
444
+ try {
445
+ await this . _deviceInitializePromise ;
446
+ } catch ( err ) {
447
+ // In case the initalization fails, we want to allow calling `initlialize` again with other arguments for example, so remove the cached promise value.
448
+ this . $logger . trace ( `Error while initializing devicesService: ${ err } ` ) ;
449
+ this . _deviceInitializePromise = null ;
450
+ throw err ;
451
+ }
452
+ }
453
+
454
+ private async initializeCore ( deviceInitOpts ?: Mobile . IDevicesServicesInitializationOptions ) : Promise < void > {
462
455
if ( this . _isInitialized ) {
463
456
return ;
464
457
}
465
458
466
459
this . $logger . out ( "Searching for devices..." ) ;
467
460
468
- data = data || { } ;
461
+ deviceInitOpts = deviceInitOpts || { } ;
469
462
470
- if ( ! data . skipEmulatorStart ) {
471
- await this . startEmulatorIfNecessary ( data ) ;
463
+ if ( ! deviceInitOpts . skipEmulatorStart ) {
464
+ // TODO: Remove from here as it calls startLookingForDevices, so we double the calls to specific device detection services
465
+ await this . startEmulatorIfNecessary ( deviceInitOpts ) ;
472
466
}
473
467
474
- this . _data = data ;
475
- const platform = data . platform ;
476
- const deviceOption = data . deviceId ;
468
+ this . _data = deviceInitOpts ;
469
+ const platform = deviceInitOpts . platform ;
470
+ const deviceOption = deviceInitOpts . deviceId ;
477
471
478
472
if ( platform && deviceOption ) {
479
- this . _platform = this . getPlatform ( data . platform ) ;
473
+ this . _platform = this . getPlatform ( deviceInitOpts . platform ) ;
474
+ this . detectCurrentlyAttachedDevices ( deviceInitOpts ) ;
480
475
this . _device = await this . getDevice ( deviceOption ) ;
481
476
if ( this . _device . deviceInfo . platform !== this . _platform ) {
482
477
this . $errors . fail ( constants . ERROR_CANNOT_RESOLVE_DEVICE ) ;
483
478
}
484
479
this . $logger . warn ( "Your application will be deployed only on the device specified by the provided index or identifier." ) ;
485
480
} else if ( ! platform && deviceOption ) {
481
+ this . detectCurrentlyAttachedDevices ( deviceInitOpts ) ;
486
482
this . _device = await this . getDevice ( deviceOption ) ;
487
483
this . _platform = this . _device . deviceInfo . platform ;
488
484
} else if ( platform && ! deviceOption ) {
489
485
this . _platform = this . getPlatform ( platform ) ;
490
- await this . startLookingForDevices ( ) ;
486
+ await this . detectCurrentlyAttachedDevices ( deviceInitOpts ) ;
491
487
} else {
492
488
// platform and deviceId are not specified
493
- if ( data . skipInferPlatform ) {
494
- if ( data . skipDeviceDetectionInterval ) {
495
- await this . detectCurrentlyAttachedDevices ( ) ;
489
+ if ( deviceInitOpts . skipInferPlatform ) {
490
+ if ( deviceInitOpts . skipDeviceDetectionInterval ) {
491
+ await this . detectCurrentlyAttachedDevices ( deviceInitOpts ) ;
496
492
} else {
497
- const deviceLookingOptions = this . getDeviceLookingOptions ( this . _platform , true ) ;
498
- await this . startLookingForDevices ( deviceLookingOptions ) ;
493
+ deviceInitOpts . shouldReturnImmediateResult = true ;
494
+ await this . startLookingForDevices ( deviceInitOpts ) ;
499
495
}
500
496
} else {
501
- await this . detectCurrentlyAttachedDevices ( ) ;
497
+ await this . detectCurrentlyAttachedDevices ( deviceInitOpts ) ;
502
498
503
499
const devices = this . getDeviceInstances ( ) ;
504
500
const platforms = _ ( devices )
@@ -630,17 +626,17 @@ export class DevicesService extends EventEmitter implements Mobile.IDevicesServi
630
626
* @param platform (optional) platform to start emulator/simulator for
631
627
* @param emulatorImage (optional) emulator/simulator image identifier
632
628
*/
633
- public async startEmulator ( platform ?: string , emulatorImage ?: string ) : Promise < void > {
634
-
635
- platform = platform || this . _platform ;
636
- const deviceLookingOptions = this . getDeviceLookingOptions ( platform ) ;
629
+ protected async startEmulator ( deviceInitOpts : Mobile . IDevicesServicesInitializationOptions = { } ) : Promise < void > {
630
+ const { deviceId } = deviceInitOpts ;
631
+ const platform = deviceInitOpts . platform || this . _platform ;
637
632
const emulatorServices = this . resolveEmulatorServices ( platform ) ;
638
633
if ( ! emulatorServices ) {
639
634
this . $errors . failWithoutHelp ( "Unable to detect platform for which to start emulator." ) ;
640
635
}
641
636
642
- await emulatorServices . startEmulator ( emulatorImage ) ;
637
+ await emulatorServices . startEmulator ( deviceId ) ;
643
638
639
+ const deviceLookingOptions = this . getDeviceLookingOptions ( deviceInitOpts ) ;
644
640
if ( this . $mobileHelper . isAndroidPlatform ( platform ) ) {
645
641
await this . $androidDeviceDiscovery . startLookingForDevices ( deviceLookingOptions ) ;
646
642
} else if ( this . $mobileHelper . isiOSPlatform ( platform ) && this . $hostInfo . isDarwin ) {
@@ -697,10 +693,11 @@ export class DevicesService extends EventEmitter implements Mobile.IDevicesServi
697
693
} ;
698
694
}
699
695
700
- private getDeviceLookingOptions ( platform ?: string , shouldReturnImmediateResult ?: boolean ) : Mobile . IDeviceLookingOptions {
701
- platform = platform || this . _platform ;
702
- shouldReturnImmediateResult = shouldReturnImmediateResult || false ;
703
- return { shouldReturnImmediateResult : shouldReturnImmediateResult , platform : platform } ;
696
+ private getDeviceLookingOptions ( deviceInitOpts : Mobile . IDevicesServicesInitializationOptions = { } ) : Mobile . IDeviceLookingOptions {
697
+ const { shouldReturnImmediateResult, emulator } = deviceInitOpts ;
698
+ const platform = deviceInitOpts . platform || this . _platform ;
699
+
700
+ return { platform, shouldReturnImmediateResult : ! ! shouldReturnImmediateResult , emulator : ! ! emulator } ;
704
701
}
705
702
706
703
private getEmulatorError ( error : Error , platform : string ) : string {
0 commit comments