1import fs from 'fs';
2import path from 'path';
3
4import { Device, DeviceABI, getDeviceABIsAsync } from '../../start/platforms/android/adb';
5import { GradleProps } from './resolveGradleProps';
6
7const debug = require('debug')('expo:run:android:resolveInstallApkName') as typeof console.log;
8
9export async function resolveInstallApkNameAsync(
10  device: Pick<Device, 'name' | 'pid'>,
11  { appName, buildType, flavors, apkVariantDirectory }: GradleProps
12) {
13  const availableCPUs = await getDeviceABIsAsync(device);
14  availableCPUs.push(DeviceABI.universal);
15
16  debug('Supported ABIs: ' + availableCPUs.join(', '));
17  debug('Searching for APK: ' + apkVariantDirectory);
18
19  // Check for cpu specific builds first
20  for (const availableCPU of availableCPUs) {
21    const apkName = getApkFileName(appName, buildType, flavors, availableCPU);
22    const apkPath = path.join(apkVariantDirectory, apkName);
23    debug('Checking for APK at:', apkPath);
24    if (fs.existsSync(apkPath)) {
25      return apkName;
26    }
27  }
28
29  // Otherwise use the default apk named after the variant: app-debug.apk
30  const apkName = getApkFileName(appName, buildType, flavors);
31  const apkPath = path.join(apkVariantDirectory, apkName);
32  debug('Checking for fallback APK at:', apkPath);
33  if (fs.existsSync(apkPath)) {
34    return apkName;
35  }
36
37  return null;
38}
39
40function getApkFileName(
41  appName: string,
42  buildType: string,
43  flavors?: string[] | null,
44  cpuArch?: string | null
45) {
46  let apkName = `${appName}-`;
47  if (flavors) {
48    apkName += flavors.reduce((rest, flavor) => `${rest}${flavor}-`, '');
49  }
50  if (cpuArch) {
51    apkName += `${cpuArch}-`;
52  }
53  apkName += `${buildType}.apk`;
54
55  return apkName;
56}
57