@react-native-harness/platform-android 1.1.0-rc.3 → 1.1.0-rc.4

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.
@@ -21,7 +21,7 @@ type AndroidSdkRootOptions = {
21
21
  };
22
22
 
23
23
  const getConfiguredAndroidSdkRoot = (
24
- env: NodeJS.ProcessEnv = process.env
24
+ env: NodeJS.ProcessEnv = process.env,
25
25
  ): string | null => {
26
26
  return env.ANDROID_HOME ?? env.ANDROID_SDK_ROOT ?? null;
27
27
  };
@@ -42,7 +42,7 @@ export const getDefaultUnixAndroidSdkRoot = ({
42
42
  };
43
43
 
44
44
  const canBootstrapAndroidSdk = (
45
- platform: NodeJS.Platform = process.platform
45
+ platform: NodeJS.Platform = process.platform,
46
46
  ) => {
47
47
  return platform === 'darwin' || platform === 'linux';
48
48
  };
@@ -79,8 +79,8 @@ const downloadText = async (url: string): Promise<string> => {
79
79
  response.resume();
80
80
  reject(
81
81
  new Error(
82
- `Failed to download Android repository index from ${url} (status ${statusCode}).`
83
- )
82
+ `Failed to download Android repository index from ${url} (status ${statusCode}).`,
83
+ ),
84
84
  );
85
85
  return;
86
86
  }
@@ -102,7 +102,7 @@ const downloadText = async (url: string): Promise<string> => {
102
102
 
103
103
  const downloadFile = async (
104
104
  url: string,
105
- destinationPath: string
105
+ destinationPath: string,
106
106
  ): Promise<void> => {
107
107
  await new Promise<void>((resolve, reject) => {
108
108
  const request = https.get(url, (response) => {
@@ -122,8 +122,8 @@ const downloadFile = async (
122
122
  response.resume();
123
123
  reject(
124
124
  new Error(
125
- `Failed to download Android command-line tools from ${url} (status ${statusCode}).`
126
- )
125
+ `Failed to download Android command-line tools from ${url} (status ${statusCode}).`,
126
+ ),
127
127
  );
128
128
  return;
129
129
  }
@@ -137,27 +137,27 @@ const downloadFile = async (
137
137
  };
138
138
 
139
139
  const getCommandLineToolsArchiveUrl = async (
140
- platform: NodeJS.Platform = process.platform
140
+ platform: NodeJS.Platform = process.platform,
141
141
  ): Promise<string> => {
142
142
  const archivePlatform =
143
143
  platform === 'darwin' ? 'mac' : platform === 'linux' ? 'linux' : null;
144
144
 
145
145
  if (!archivePlatform) {
146
146
  throw new Error(
147
- 'Automatic Android SDK bootstrap is only supported on macOS and Linux.'
147
+ 'Automatic Android SDK bootstrap is only supported on macOS and Linux.',
148
148
  );
149
149
  }
150
150
 
151
151
  const repositoryIndex = await downloadText(ANDROID_REPOSITORY_INDEX_URL);
152
152
  const archivePattern = new RegExp(
153
153
  `commandlinetools-${archivePlatform}-(\\d+)_latest\\.zip`,
154
- 'g'
154
+ 'g',
155
155
  );
156
156
  const matches = [...repositoryIndex.matchAll(archivePattern)];
157
157
 
158
158
  if (matches.length === 0) {
159
159
  throw new Error(
160
- `Failed to resolve Android command-line tools archive for ${archivePlatform}.`
160
+ `Failed to resolve Android command-line tools archive for ${archivePlatform}.`,
161
161
  );
162
162
  }
163
163
 
@@ -173,7 +173,7 @@ const getCommandLineToolsArchiveUrl = async (
173
173
 
174
174
  const ensureAndroidCommandLineTools = async (
175
175
  sdkRoot: string,
176
- platform: NodeJS.Platform = process.platform
176
+ platform: NodeJS.Platform = process.platform,
177
177
  ): Promise<void> => {
178
178
  if (
179
179
  (await pathExists(getSdkManagerBinaryPath(sdkRoot))) &&
@@ -184,19 +184,19 @@ const ensureAndroidCommandLineTools = async (
184
184
 
185
185
  if (!canBootstrapAndroidSdk(platform)) {
186
186
  throw new Error(
187
- 'Android command-line tools are missing. Set ANDROID_HOME or ANDROID_SDK_ROOT to an initialized SDK.'
187
+ 'Android command-line tools are missing. Set ANDROID_HOME or ANDROID_SDK_ROOT to an initialized SDK.',
188
188
  );
189
189
  }
190
190
 
191
191
  androidEnvironmentLogger.info(
192
192
  'Bootstrapping Android command-line tools in %s',
193
- sdkRoot
193
+ sdkRoot,
194
194
  );
195
195
 
196
196
  await mkdir(sdkRoot, { recursive: true });
197
197
 
198
198
  const temporaryDirectory = await mkdtemp(
199
- path.join(os.tmpdir(), 'android-cmdline-tools-')
199
+ path.join(os.tmpdir(), 'android-cmdline-tools-'),
200
200
  );
201
201
  const archivePath = path.join(temporaryDirectory, 'cmdline-tools.zip');
202
202
  const extractedPath = path.join(temporaryDirectory, 'extracted');
@@ -206,7 +206,7 @@ const ensureAndroidCommandLineTools = async (
206
206
  try {
207
207
  await downloadFile(
208
208
  await getCommandLineToolsArchiveUrl(platform),
209
- archivePath
209
+ archivePath,
210
210
  );
211
211
  await spawn('unzip', ['-q', archivePath, '-d', extractedPath]);
212
212
  await rm(targetDirectory, { force: true, recursive: true });
@@ -225,7 +225,7 @@ const acceptAndroidLicenses = async (sdkRoot: string): Promise<void> => {
225
225
  [
226
226
  '-lc',
227
227
  `yes | ${quoteShell(sdkManagerBinaryPath)} --sdk_root=${quoteShell(
228
- sdkRoot
228
+ sdkRoot,
229
229
  )} --licenses >/dev/null`,
230
230
  ],
231
231
  {
@@ -234,13 +234,13 @@ const acceptAndroidLicenses = async (sdkRoot: string): Promise<void> => {
234
234
  ANDROID_HOME: sdkRoot,
235
235
  ANDROID_SDK_ROOT: sdkRoot,
236
236
  }),
237
- }
237
+ },
238
238
  );
239
239
  };
240
240
 
241
241
  const getPackageVerificationPath = (
242
242
  sdkRoot: string,
243
- packageName: string
243
+ packageName: string,
244
244
  ): string | null => {
245
245
  if (packageName === 'platform-tools') {
246
246
  return getAdbBinaryPath(sdkRoot);
@@ -263,7 +263,7 @@ const getPackageVerificationPath = (
263
263
 
264
264
  const getMissingAndroidSdkPackages = async (
265
265
  sdkRoot: string,
266
- packages: readonly string[]
266
+ packages: readonly string[],
267
267
  ): Promise<string[]> => {
268
268
  const missingPackages: string[] = [];
269
269
 
@@ -284,7 +284,7 @@ const getMissingAndroidSdkPackages = async (
284
284
 
285
285
  const installAndroidSdkPackages = async (
286
286
  sdkRoot: string,
287
- packages: readonly string[]
287
+ packages: readonly string[],
288
288
  ): Promise<void> => {
289
289
  if (packages.length === 0) {
290
290
  return;
@@ -297,7 +297,7 @@ const installAndroidSdkPackages = async (
297
297
 
298
298
  androidEnvironmentLogger.info(
299
299
  'Installing missing Android SDK packages: %s',
300
- packages.join(', ')
300
+ packages.join(', '),
301
301
  );
302
302
 
303
303
  await acceptAndroidLicenses(sdkRoot);
@@ -306,7 +306,7 @@ const installAndroidSdkPackages = async (
306
306
  [
307
307
  '-lc',
308
308
  `yes | ${quoteShell(sdkManagerBinaryPath)} --sdk_root=${quoteShell(
309
- sdkRoot
309
+ sdkRoot,
310
310
  )} ${packageArgs}`,
311
311
  ],
312
312
  {
@@ -315,13 +315,13 @@ const installAndroidSdkPackages = async (
315
315
  ANDROID_HOME: sdkRoot,
316
316
  ANDROID_SDK_ROOT: sdkRoot,
317
317
  }),
318
- }
318
+ },
319
319
  );
320
320
  };
321
321
 
322
322
  export const getAndroidSdkRoot = (
323
323
  env: NodeJS.ProcessEnv = process.env,
324
- options: Omit<AndroidSdkRootOptions, 'env'> = {}
324
+ options: Omit<AndroidSdkRootOptions, 'env'> = {},
325
325
  ): string | null => {
326
326
  return (
327
327
  getConfiguredAndroidSdkRoot(env) ?? getDefaultUnixAndroidSdkRoot(options)
@@ -330,13 +330,13 @@ export const getAndroidSdkRoot = (
330
330
 
331
331
  const getRequiredAndroidSdkRoot = (
332
332
  env: NodeJS.ProcessEnv = process.env,
333
- options: Omit<AndroidSdkRootOptions, 'env'> = {}
333
+ options: Omit<AndroidSdkRootOptions, 'env'> = {},
334
334
  ): string => {
335
335
  const sdkRoot = getAndroidSdkRoot(env, options);
336
336
 
337
337
  if (!sdkRoot) {
338
338
  throw new Error(
339
- 'Android SDK root is not configured. Set ANDROID_HOME or ANDROID_SDK_ROOT.'
339
+ 'Android SDK root is not configured. Set ANDROID_HOME or ANDROID_SDK_ROOT.',
340
340
  );
341
341
  }
342
342
 
@@ -344,7 +344,7 @@ const getRequiredAndroidSdkRoot = (
344
344
  };
345
345
 
346
346
  export const getHostAndroidSystemImageArch = (
347
- architecture: string = process.arch
347
+ architecture: string = process.arch,
348
348
  ): AndroidSystemImageArch => {
349
349
  switch (architecture) {
350
350
  case 'arm64':
@@ -363,7 +363,7 @@ export const getAndroidPlatformPackage = (apiLevel: number): string => {
363
363
 
364
364
  export const getAndroidSystemImagePackage = (
365
365
  apiLevel: number,
366
- architecture: AndroidSystemImageArch = getHostAndroidSystemImageArch()
366
+ architecture: AndroidSystemImageArch = getHostAndroidSystemImageArch(),
367
367
  ): string => {
368
368
  return `system-images;android-${apiLevel};default;${architecture}`;
369
369
  };
@@ -393,71 +393,115 @@ export const getRequiredAndroidSdkPackages = ({
393
393
  return packages;
394
394
  };
395
395
 
396
- export const ensureAndroidSdkPackages = async (
396
+ const getMissingAndroidSdkPackagesForEnvironment = async (
397
397
  packages: readonly string[],
398
398
  {
399
399
  env = process.env,
400
400
  platform = process.platform,
401
401
  homeDirectory = os.homedir(),
402
- }: AndroidSdkRootOptions = {}
403
- ): Promise<string> => {
402
+ }: AndroidSdkRootOptions = {},
403
+ ): Promise<{ sdkRoot: string; missingPackages: string[] }> => {
404
404
  const sdkRoot = getRequiredAndroidSdkRoot(env, { platform, homeDirectory });
405
405
 
406
406
  await mkdir(sdkRoot, { recursive: true });
407
- await ensureAndroidCommandLineTools(sdkRoot, platform);
408
407
 
409
- const missingPackages = await getMissingAndroidSdkPackages(sdkRoot, packages);
408
+ return {
409
+ sdkRoot,
410
+ missingPackages: await getMissingAndroidSdkPackages(sdkRoot, packages),
411
+ };
412
+ };
410
413
 
411
- if (missingPackages.length > 0) {
412
- await installAndroidSdkPackages(sdkRoot, missingPackages);
414
+ export const ensureAndroidSdkPackages = async (
415
+ packages: readonly string[],
416
+ {
417
+ env = process.env,
418
+ platform = process.platform,
419
+ homeDirectory = os.homedir(),
420
+ }: AndroidSdkRootOptions = {},
421
+ ): Promise<string> => {
422
+ const { sdkRoot, missingPackages } =
423
+ await getMissingAndroidSdkPackagesForEnvironment(packages, {
424
+ env,
425
+ platform,
426
+ homeDirectory,
427
+ });
428
+
429
+ if (missingPackages.length === 0) {
430
+ return sdkRoot;
413
431
  }
414
432
 
433
+ await ensureAndroidCommandLineTools(sdkRoot, platform);
434
+
435
+ await installAndroidSdkPackages(sdkRoot, missingPackages);
436
+
415
437
  const unresolvedPackages = await getMissingAndroidSdkPackages(
416
438
  sdkRoot,
417
- packages
439
+ packages,
418
440
  );
419
441
 
420
442
  if (unresolvedPackages.length > 0) {
421
443
  throw new Error(
422
444
  `Android SDK packages are still missing after installation: ${unresolvedPackages.join(
423
- ', '
424
- )}`
445
+ ', ',
446
+ )}`,
425
447
  );
426
448
  }
427
449
 
428
450
  return sdkRoot;
429
451
  };
430
452
 
431
- export const ensureAndroidDiscoveryEnvironment = async (): Promise<string> => {
432
- initializeAndroidProcessEnv();
453
+ export const ensureAndroidAdbAvailable = async (
454
+ options: AndroidSdkRootOptions = {},
455
+ ): Promise<string> => {
456
+ return ensureAndroidSdkPackages(['platform-tools'], options);
457
+ };
433
458
 
459
+ export const ensureAndroidEmulatorAvailable = async (
460
+ options: AndroidSdkRootOptions = {},
461
+ ): Promise<string> => {
462
+ return ensureAndroidSdkPackages(['emulator'], options);
463
+ };
464
+
465
+ export const ensureAndroidAvdProvisioningAvailable = async (
466
+ apiLevel: number,
467
+ architecture: AndroidSystemImageArch = getHostAndroidSystemImageArch(),
468
+ options: AndroidSdkRootOptions = {},
469
+ ): Promise<string> => {
434
470
  return ensureAndroidSdkPackages(
435
- getRequiredAndroidSdkPackages({ includeEmulator: true })
471
+ [
472
+ getAndroidPlatformPackage(apiLevel),
473
+ getAndroidSystemImagePackage(apiLevel, architecture),
474
+ ],
475
+ options,
436
476
  );
437
477
  };
438
478
 
479
+ export const ensureAndroidDiscoveryEnvironment = async (): Promise<string> => {
480
+ initializeAndroidProcessEnv();
481
+
482
+ return ensureAndroidAdbAvailable();
483
+ };
484
+
439
485
  export const ensureAndroidPhysicalDeviceEnvironment =
440
486
  async (): Promise<string> => {
441
487
  initializeAndroidProcessEnv();
442
488
 
443
- return ensureAndroidSdkPackages(getRequiredAndroidSdkPackages());
489
+ return ensureAndroidAdbAvailable();
444
490
  };
445
491
 
446
492
  export const ensureAndroidEmulatorEnvironment = async (
447
- apiLevel: number
493
+ apiLevel: number,
448
494
  ): Promise<string> => {
449
495
  initializeAndroidProcessEnv();
450
496
 
451
- return ensureAndroidSdkPackages(
452
- getRequiredAndroidSdkPackages({
453
- apiLevel,
454
- includeEmulator: true,
455
- })
456
- );
497
+ await ensureAndroidAdbAvailable();
498
+ await ensureAndroidEmulatorAvailable();
499
+
500
+ return ensureAndroidAvdProvisioningAvailable(apiLevel);
457
501
  };
458
502
 
459
503
  export const getAndroidProcessEnv = (
460
- env: NodeJS.ProcessEnv = process.env
504
+ env: NodeJS.ProcessEnv = process.env,
461
505
  ): NodeJS.ProcessEnv => {
462
506
  const sdkRoot = getAndroidSdkRoot(env);
463
507
 
@@ -492,19 +536,19 @@ export const initializeAndroidProcessEnv = (): void => {
492
536
  };
493
537
 
494
538
  export const getAdbBinaryPath = (
495
- sdkRoot: string = getRequiredAndroidSdkRoot()
539
+ sdkRoot: string = getRequiredAndroidSdkRoot(),
496
540
  ): string => path.join(sdkRoot, 'platform-tools', 'adb');
497
541
 
498
542
  export const getEmulatorBinaryPath = (
499
- sdkRoot: string = getRequiredAndroidSdkRoot()
543
+ sdkRoot: string = getRequiredAndroidSdkRoot(),
500
544
  ): string => path.join(sdkRoot, 'emulator', 'emulator');
501
545
 
502
546
  export const getSdkManagerBinaryPath = (
503
- sdkRoot: string = getRequiredAndroidSdkRoot()
547
+ sdkRoot: string = getRequiredAndroidSdkRoot(),
504
548
  ): string =>
505
549
  path.join(sdkRoot, ...CMDLINE_TOOLS_PATH_SEGMENTS, 'bin', 'sdkmanager');
506
550
 
507
551
  export const getAvdManagerBinaryPath = (
508
- sdkRoot: string = getRequiredAndroidSdkRoot()
552
+ sdkRoot: string = getRequiredAndroidSdkRoot(),
509
553
  ): string =>
510
554
  path.join(sdkRoot, ...CMDLINE_TOOLS_PATH_SEGMENTS, 'bin', 'avdmanager');
package/src/instance.ts CHANGED
@@ -27,6 +27,7 @@ import { getDeviceName } from './utils.js';
27
27
  import { createAndroidAppMonitor } from './app-monitor.js';
28
28
  import { HarnessAppPathError, HarnessEmulatorConfigError } from './errors.js';
29
29
  import {
30
+ ensureAndroidEmulatorAvailable,
30
31
  ensureAndroidEmulatorEnvironment,
31
32
  getHostAndroidSystemImageArch,
32
33
  } from './environment.js';
@@ -61,7 +62,7 @@ const getHarnessAppPath = (): string => {
61
62
  const configureAndroidRuntime = async (
62
63
  adbId: string,
63
64
  config: AndroidPlatformConfig,
64
- harnessConfig: HarnessConfig
65
+ harnessConfig: HarnessConfig,
65
66
  ): Promise<number> => {
66
67
  const metroPort = harnessConfig.metroPort;
67
68
 
@@ -84,6 +85,7 @@ const startAndWaitForBoot = async ({
84
85
  signal: AbortSignal;
85
86
  mode?: Parameters<typeof adb.startEmulator>[1];
86
87
  }): Promise<string> => {
88
+ await ensureAndroidEmulatorAvailable();
87
89
  await adb.startEmulator(emulatorName, mode);
88
90
  return adb.waitForBoot(emulatorName, signal);
89
91
  };
@@ -137,14 +139,14 @@ const prepareCachedAvd = async ({
137
139
  hasExistingAvd
138
140
  ? 'Recreating incompatible Android emulator %s...'
139
141
  : 'Creating Android emulator %s...',
140
- emulatorName
142
+ emulatorName,
141
143
  );
142
144
 
143
145
  if (hasExistingAvd && !compatibility.compatible) {
144
146
  androidInstanceLogger.debug(
145
147
  'Android AVD %s is not reusable: %s',
146
148
  emulatorName,
147
- compatibility.reason
149
+ compatibility.reason,
148
150
  );
149
151
  await adb.deleteAvd(emulatorName);
150
152
  }
@@ -174,7 +176,7 @@ const prepareCachedAvd = async ({
174
176
  export const getAndroidEmulatorPlatformInstance = async (
175
177
  config: AndroidPlatformConfig,
176
178
  harnessConfig: HarnessConfig,
177
- init: HarnessPlatformInitOptions
179
+ init: HarnessPlatformInitOptions,
178
180
  ): Promise<HarnessPlatformRunner> => {
179
181
  assertAndroidDeviceEmulator(config.device);
180
182
  const detectNativeCrashes = harnessConfig.detectNativeCrashes ?? true;
@@ -192,7 +194,7 @@ export const getAndroidEmulatorPlatformInstance = async (
192
194
  androidInstanceLogger.debug(
193
195
  'resolved Android emulator %s with adb id %s',
194
196
  emulatorConfig.name,
195
- adbId ?? 'not-found'
197
+ adbId ?? 'not-found',
196
198
  );
197
199
 
198
200
  if (!adbId) {
@@ -212,7 +214,7 @@ export const getAndroidEmulatorPlatformInstance = async (
212
214
  logger.info('Creating Android emulator %s...', emulatorName);
213
215
  androidInstanceLogger.debug(
214
216
  'creating Android AVD %s before startup',
215
- emulatorConfig.name
217
+ emulatorConfig.name,
216
218
  );
217
219
  await recreateAvd({ emulatorConfig });
218
220
  } else {
@@ -221,7 +223,7 @@ export const getAndroidEmulatorPlatformInstance = async (
221
223
 
222
224
  androidInstanceLogger.debug(
223
225
  'starting Android emulator %s',
224
- emulatorConfig.name
226
+ emulatorConfig.name,
225
227
  );
226
228
  return startAndWaitForBoot({
227
229
  emulatorName: emulatorConfig.name,
@@ -234,10 +236,8 @@ export const getAndroidEmulatorPlatformInstance = async (
234
236
  androidInstanceLogger.debug(
235
237
  'Android emulator %s connected as %s',
236
238
  emulatorConfig.name,
237
- adbId
239
+ adbId,
238
240
  );
239
- } else if (emulatorConfig.avd) {
240
- await ensureAndroidEmulatorEnvironment(emulatorConfig.avd.apiLevel);
241
241
  }
242
242
 
243
243
  if (!adbId) {
@@ -246,7 +246,7 @@ export const getAndroidEmulatorPlatformInstance = async (
246
246
 
247
247
  androidInstanceLogger.debug(
248
248
  'waiting for Android emulator %s to finish booting',
249
- adbId
249
+ adbId,
250
250
  );
251
251
 
252
252
  const isInstalled = await adb.isAppInstalled(adbId, config.bundleId);
@@ -265,7 +265,7 @@ export const getAndroidEmulatorPlatformInstance = async (
265
265
  config.bundleId,
266
266
  config.activityName,
267
267
  (options as typeof config.appLaunchOptions | undefined) ??
268
- config.appLaunchOptions
268
+ config.appLaunchOptions,
269
269
  );
270
270
  },
271
271
  restartApp: async (options) => {
@@ -275,7 +275,7 @@ export const getAndroidEmulatorPlatformInstance = async (
275
275
  config.bundleId,
276
276
  config.activityName,
277
277
  (options as typeof config.appLaunchOptions | undefined) ??
278
- config.appLaunchOptions
278
+ config.appLaunchOptions,
279
279
  );
280
280
  },
281
281
  stopApp: async () => {
@@ -311,7 +311,7 @@ export const getAndroidEmulatorPlatformInstance = async (
311
311
 
312
312
  export const getAndroidPhysicalDevicePlatformInstance = async (
313
313
  config: AndroidPlatformConfig,
314
- harnessConfig: HarnessConfig
314
+ harnessConfig: HarnessConfig,
315
315
  ): Promise<HarnessPlatformRunner> => {
316
316
  assertAndroidDevicePhysical(config.device);
317
317
  const detectNativeCrashes = harnessConfig.detectNativeCrashes ?? true;
@@ -327,7 +327,7 @@ export const getAndroidPhysicalDevicePlatformInstance = async (
327
327
  if (!isInstalled) {
328
328
  throw new AppNotInstalledError(
329
329
  config.bundleId,
330
- getDeviceName(config.device)
330
+ getDeviceName(config.device),
331
331
  );
332
332
  }
333
333
 
@@ -340,7 +340,7 @@ export const getAndroidPhysicalDevicePlatformInstance = async (
340
340
  config.bundleId,
341
341
  config.activityName,
342
342
  (options as typeof config.appLaunchOptions | undefined) ??
343
- config.appLaunchOptions
343
+ config.appLaunchOptions,
344
344
  );
345
345
  },
346
346
  restartApp: async (options) => {
@@ -350,7 +350,7 @@ export const getAndroidPhysicalDevicePlatformInstance = async (
350
350
  config.bundleId,
351
351
  config.activityName,
352
352
  (options as typeof config.appLaunchOptions | undefined) ??
353
- config.appLaunchOptions
353
+ config.appLaunchOptions,
354
354
  );
355
355
  },
356
356
  stopApp: async () => {
package/src/runner.ts CHANGED
@@ -13,34 +13,29 @@ import {
13
13
  getAndroidPhysicalDevicePlatformInstance,
14
14
  } from './instance.js';
15
15
  import {
16
- ensureAndroidEmulatorEnvironment,
17
- ensureAndroidPhysicalDeviceEnvironment,
16
+ ensureAndroidAdbAvailable,
18
17
  initializeAndroidProcessEnv,
19
18
  } from './environment.js';
20
19
 
21
20
  const getAndroidRunner = async (
22
21
  config: AndroidPlatformConfig,
23
22
  harnessConfig: HarnessConfig,
24
- init: HarnessPlatformInitOptions
23
+ init: HarnessPlatformInitOptions,
25
24
  ): Promise<HarnessPlatformRunner> => {
26
25
  const parsedConfig = AndroidPlatformConfigSchema.parse(config);
27
26
 
28
27
  initializeAndroidProcessEnv();
29
28
 
30
- if (isAndroidDeviceEmulator(parsedConfig.device)) {
31
- if (parsedConfig.device.avd) {
32
- await ensureAndroidEmulatorEnvironment(parsedConfig.device.avd.apiLevel);
33
- }
29
+ await ensureAndroidAdbAvailable();
34
30
 
31
+ if (isAndroidDeviceEmulator(parsedConfig.device)) {
35
32
  return getAndroidEmulatorPlatformInstance(
36
33
  parsedConfig,
37
34
  harnessConfig,
38
- init
35
+ init,
39
36
  );
40
37
  }
41
38
 
42
- await ensureAndroidPhysicalDeviceEnvironment();
43
-
44
39
  return getAndroidPhysicalDevicePlatformInstance(parsedConfig, harnessConfig);
45
40
  };
46
41
 
package/src/targets.ts CHANGED
@@ -1,9 +1,16 @@
1
1
  import { RunTarget } from '@react-native-harness/platforms';
2
2
  import * as adb from './adb.js';
3
- import { ensureAndroidDiscoveryEnvironment } from './environment.js';
3
+ import {
4
+ ensureAndroidAdbAvailable,
5
+ ensureAndroidEmulatorAvailable,
6
+ initializeAndroidProcessEnv,
7
+ } from './environment.js';
4
8
 
5
9
  export const getRunTargets = async (): Promise<RunTarget[]> => {
6
- await ensureAndroidDiscoveryEnvironment();
10
+ initializeAndroidProcessEnv();
11
+
12
+ await ensureAndroidAdbAvailable();
13
+ await ensureAndroidEmulatorAvailable();
7
14
 
8
15
  const [avds, connectedDevices] = await Promise.all([
9
16
  adb.getAvds(),