Skip to main content
AndroidAutomator provides Android-specific methods for native UI automation. Access it through $.platform.android in your Patrol tests.

Accessing AndroidAutomator

patrolTest('android test', ($) async {
  // Access via platform.android
  await $.platform.android.pressBack();
  
  // Platform-specific action helper
  await $.platform.action(
    android: $.platform.android.enableLocation,
  );
});

Android-Specific Methods

System Navigation

pressBack()
Future<void>
Presses the Android back button.Not available on iOS.Reference: UiDevice.pressBack
await $.platform.android.pressBack();
pressDoubleRecentApps()
Future<void>
Quickly double-presses the recent apps button.
await $.platform.android.pressDoubleRecentApps();

Location Services

enableLocation()
Future<void>
Enables location services on Android.Opens the location settings screen and toggles the switch. If location is already enabled, does nothing.
await $.platform.android.enableLocation();
disableLocation()
Future<void>
Disables location services on Android.Opens the location settings screen and toggles the switch.
await $.platform.android.disableLocation();

Initialization

initialize()
Future<void>
Initializes the Android native automator.Used internally to initialize android.app.UiAutomation before Flutter tests start. This method is idempotent.Reference: Flutter Issue #129231
configure()
Future<void>
Configures the Android automator with settings from AndroidAutomatorConfig.

Element Interaction

Tapping

tap(AndroidSelector selector, {...})
Future<void>
Taps on a native Android UI element.Parameters:
  • selector - AndroidSelector to locate the element
  • timeout - Max time to wait (defaults to findTimeout from config)
await $.platform.android.tap(
  AndroidSelector(text: 'Allow'),
);

await $.platform.android.tap(
  AndroidSelector(
    resourceName: 'com.example:id/submit_button',
  ),
);
doubleTap(AndroidSelector selector, {...})
Future<void>
Double taps on a native element.Parameters:
  • selector - Element to tap
  • timeout - Max wait time
  • delayBetweenTaps - Time between taps (default: 300ms)
await $.platform.android.doubleTap(
  AndroidSelector(className: 'android.widget.ImageView'),
  delayBetweenTaps: Duration(milliseconds: 500),
);
tapAt(Offset location)
Future<void>
Taps at specific screen coordinates.Location values must be in the 0-1 range (normalized coordinates).
// Tap at center of screen
await $.platform.android.tapAt(Offset(0.5, 0.5));

// Tap at top-right corner
await $.platform.android.tapAt(Offset(0.9, 0.1));

Text Entry

enterText(AndroidSelector selector, {...})
Future<void>
Enters text into a native Android text field.The element must be an EditText or AutoCompleteTextView.Parameters:
  • selector - The text field to target
  • text - Text to enter (required)
  • keyboardBehavior - How to handle the keyboard
  • timeout - Max wait time
  • tapLocation - Where to tap before entering text
await $.platform.android.enterText(
  AndroidSelector(resourceName: 'com.google:id/username'),
  text: '[email protected]',
);
enterTextByIndex(String text, {...})
Future<void>
Enters text into the nth visible text field.Parameters:
  • text - Text to enter
  • index - Index of the text field (required)
  • keyboardBehavior - Keyboard handling
  • timeout - Max wait time
// Enter into first text field
await $.platform.android.enterTextByIndex(
  'username',
  index: 0,
);

// Enter into second text field
await $.platform.android.enterTextByIndex(
  'password',
  index: 1,
);

Gestures

swipe({required Offset from, required Offset to, ...})
Future<void>
Performs a swipe gesture.Parameters:
  • from - Starting point (0-1 range)
  • to - Ending point (0-1 range)
  • steps - Speed control (default: 12, one step = 5ms)
  • enablePatrolLog - Whether to log action
// Swipe from bottom to top (scroll up)
await $.platform.android.swipe(
  from: Offset(0.5, 0.8),
  to: Offset(0.5, 0.2),
  steps: 20, // Slower swipe
);
swipeBack({double dy})
Future<void>
Performs a back swipe gesture (left to right).Parameters:
  • dy - Vertical position (0-1 range, default: 0.5)
await $.platform.android.swipeBack();

// Swipe at top of screen
await $.platform.android.swipeBack(dy: 0.2);
pullToRefresh({...})
Future<void>
Simulates a pull-to-refresh gesture.Parameters:
  • from - Starting point (default: center)
  • to - Ending point (default: bottom-center)
  • steps - Gesture speed (default: 50)
await $.platform.android.pullToRefresh();

// Custom gesture
await $.platform.android.pullToRefresh(
  from: Offset(0.5, 0.3),
  to: Offset(0.5, 0.8),
  steps: 30,
);

Notification Handling

tapOnNotificationByIndex(int index, {...})
Future<void>
Taps on a notification by its index.Notification shade must be opened first with openNotifications().
await $.platform.mobile.openNotifications();
await $.platform.android.tapOnNotificationByIndex(0);
tapOnNotificationBySelector(AndroidSelector selector, {...})
Future<void>
Taps on a notification using a selector.
await $.platform.mobile.openNotifications();
await $.platform.android.tapOnNotificationBySelector(
  AndroidSelector(textContains: 'New message'),
);

UI Inspection

getNativeViews(AndroidSelector? selector)
Future<AndroidGetNativeViewsResponse>
Returns the native Android UI tree.If selector is null, returns the entire UI tree.
// Get entire UI tree
final views = await $.platform.android.getNativeViews(null);

// Get specific elements
final buttons = await $.platform.android.getNativeViews(
  AndroidSelector(className: 'android.widget.Button'),
);
waitUntilVisible(AndroidSelector selector, {...})
Future<void>
Waits until an element becomes visible.
await $.platform.android.waitUntilVisible(
  AndroidSelector(text: 'Submit'),
  timeout: Duration(seconds: 10),
);
takeCameraPhoto({...})
Future<void>
Takes and confirms a photo using the device camera.Parameters:
  • shutterButtonSelector - Custom shutter button selector
  • doneButtonSelector - Custom done button selector
  • timeout - Max wait time
await $.platform.android.takeCameraPhoto();

// With custom selectors
await $.platform.android.takeCameraPhoto(
  shutterButtonSelector: AndroidSelector(
    resourceName: 'com.android.camera2:id/shutter_button',
  ),
);
Picks a single image from the gallery.
await $.platform.android.pickImageFromGallery();

// Pick specific image by index
await $.platform.android.pickImageFromGallery(index: 5);
Picks multiple images from the gallery.
await $.platform.android.pickMultipleImagesFromGallery(
  imageIndexes: [0, 1, 2, 5],
);

AndroidSelector

The selector class for locating Android UI elements:
AndroidSelector({
  String? className,
  bool? isCheckable,
  bool? isChecked,
  bool? isClickable,
  bool? isEnabled,
  bool? isFocusable,
  bool? isFocused,
  bool? isLongClickable,
  bool? isScrollable,
  bool? isSelected,
  String? applicationPackage,
  String? contentDescription,
  String? contentDescriptionStartsWith,
  String? contentDescriptionContains,
  String? text,
  String? textStartsWith,
  String? textContains,
  String? resourceName,
  int? instance,
})

Examples

// By text
AndroidSelector(text: 'Submit')

// By resource ID
AndroidSelector(resourceName: 'com.example:id/button')

// By class and state
AndroidSelector(
  className: 'android.widget.Button',
  isEnabled: true,
)

// Complex selector
AndroidSelector(
  textContains: 'Continue',
  isClickable: true,
  instance: 0,
)

Usage Examples

Complete Login Flow

patrolTest('login with Google on Android', ($) async {
  await $.pumpWidgetAndSettle(MyApp());
  
  // Tap Flutter button
  await $('Sign in with Google').tap();
  
  // Interact with native Google Sign-In
  await $.platform.android.tap(
    AndroidSelector(text: '[email protected]'),
  );
  
  await $.platform.android.tap(
    AndroidSelector(
      resourceName: 'com.google.android.gms:id/continue_button',
    ),
  );
  
  // Back in Flutter
  await $(Text('Welcome')).waitUntilVisible();
});

Handle System Settings

patrolTest('enable location', ($) async {
  await $.pumpWidgetAndSettle(MyApp());
  
  // Enable location via system settings
  await $.platform.android.enableLocation();
  
  // Verify in app
  await $('Request Location').tap();
  await $(Text('Location Enabled')).waitUntilVisible();
});

See Also

Build docs developers (and LLMs) love