run method

  1. @override
Future<StepResult> run(
  1. BuildContext ctx,
  2. PipelineState state
)
override

Executes the step. Read upstream values from state, write this step's outputs back into it, and return StepResult.success or StepResult.failure. Throw only for programming errors — expected tool/build failures are reported via the result.

Implementation

@override
Future<StepResult> run(
  BuildContext ctx,
  PipelineState state,
) async {
  final apk = state[apkPath.id]! as String;
  final String adb;
  try {
    adb = adbPath ??
        await _resolveToolchain(toolchain, state).findAdb();
  } on ToolchainException {
    return StepResult.failure(
      'adb not found — install platform-tools (oka get android-sdk)',
    );
  }

  print('šŸ“² Installing ${p.basename(apk)}');
  final install = await Process.run(
    adb,
    adbInstallArgs(apk, serial: deviceId),
  );
  if (install.exitCode != 0 ||
      '${install.stdout}${install.stderr}'.contains('Failure')) {
    final output = '${install.stdout}${install.stderr}'.trim();
    if (output.contains('INCOMPATIBLE')) {
      print(
        '\nāŒ Signing-key mismatch: the device already has this app '
        'installed with a different key. Never uninstall an app with '
        'user data — sign with the same key instead '
        '(android/key.properties).',
      );
    } else if (output.contains('not found') ||
        output.contains('no devices')) {
      print('\nāŒ No device connected. Reconnect the phone and re-run.');
    } else {
      print('\nāŒ Install failed:\n$output');
    }
    return StepResult.failure('adb install failed for ${p.basename(apk)}');
  }
  print('āœ… Installed');
  return StepResult.success();
}