nativeTap function

Future<NativeTapResult> nativeTap(
  1. NativeTapInput input
)

Taps native (non-Flutter) UI elements using platform-specific tools.

On Android this goes through adb shell input tap, which reaches any on-screen UI regardless of process. --text finds the element in a uiautomator dump first (see android_native_tap.dart); --logical scales the coordinates by the device pixel ratio.

On iOS simulator this compiles (once, cached) a small Swift helper that injects the touch through SimulatorKit's HID client, so it reaches every process on screen, including SpringBoard system dialogs ("Allow location access?", "Open in Test App?", etc.). When the helper cannot be used (no Xcode toolchain, unknown device, compile failure...) it falls back to the in-process UIApplication.sendEvent() path (the same one fdb tap --at uses), which cannot reach SpringBoard; the result carries the reason so the CLI adapter can warn. --text reads the simulator's accessibility tree with the same helper and taps the matched element's frame center (see ios_simulator_native_tap.dart); it has no fallback.

Never throws; all error conditions are represented as sealed result cases.

Implementation

Future<NativeTapResult> nativeTap(NativeTapInput input) async {
  final platformInfo = readPlatformInfo();
  if (platformInfo == null) return const NativeTapNoSession();

  final platform = platformInfo.platform;
  final isEmulator = platformInfo.emulator;

  if (platform.startsWith('android')) {
    return nativeTapAndroid(input, deviceId: readDevice());
  }

  if (platform.startsWith('ios') && isEmulator) {
    if (input.text != null) return nativeTapIosSimulatorText(input, udid: readDevice());
    // --logical is a no-op here: iOS coordinates are already points.
    return _tapIosSimulator(x: input.x!, y: input.y!);
  }

  if (platform.startsWith('ios') && !isEmulator) {
    return NativeTapPhysicalIosUnsupported(x: input.x, y: input.y);
  }

  if (platform.startsWith('darwin')) {
    return NativeTapMacosUnsupported(x: input.x, y: input.y);
  }

  return NativeTapPlatformUnsupported(platform);
}