Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
Podium
Async Rust library for driving Android (and eventually iOS) devices in tests. Wraps Maestro's on-device gRPC server behind a clean async/await API — no YAML, no separate CLI process.
How it works
DeviceBuilder::build() connects to a running Android emulator or device via ADB:
- Installs the Maestro driver APKs (
maestro-app.apk+maestro-server.apk) if not already present. - Forwards the gRPC port over ADB (
tcp:7001). - Starts the on-device gRPC server via
am instrument(skipped if already running). - Opens a
tonicchannel to127.0.0.1:7001.
All subsequent calls (tap, assert_visible, scroll_until_visible, …) go through that channel.
Quick start
Add to Cargo.toml:
[]
= "0.2"
= { = "1", = ["rt-multi-thread", "macros"] }
use ;
async
serial: None picks the only connected device/emulator. Pass serial: Some("emulator-5554".into()) to target a specific one.
API
DeviceBuilder
default
.platform
.app_id // used for pm clear in launch_app
.build
.await?
PodiumDevice methods
| Method | Description |
|---|---|
launch_app(app_id, clear_state) |
Launch app. If clear_state is true, runs pm clear first. |
tap(selector) |
Tap the center of the matching element. |
input_text(text) |
Type text into the focused field. |
assert_visible(selector) |
Poll until element is visible (10 s timeout). |
assert_not_visible(selector) |
Poll until element is gone (10 s timeout). |
scroll_until_visible(selector) |
Swipe down up to 20 times until element appears. |
swipe(direction) |
Single swipe. Direction: Up, Down, Left, Right. |
back() |
Press the back button (KEYCODE_BACK). |
hide_keyboard() |
Dismiss the soft keyboard (KEYCODE_BACK). |
wait_for_animation() |
Wait for the window to stop updating (up to 10 s). |
take_screenshot(name) |
Write <name>.png to the current directory. |
Selector
text // exact text match
text // regex (wrap in slashes)
id // resource-id suffix match
text.index // second match
Features
| Feature | Description |
|---|---|
mock |
Exports MockTransport for unit-testing code that drives a PodiumDevice. |
integration |
Enables the integration test suite in tests/integration.rs. |
Running integration tests
Requires a running Android emulator:
&
PODIUM_SERIAL=emulator-5554 targets a specific device.
Repository layout
podium/
├── src/
│ ├── lib.rs public API surface
│ ├── device.rs PodiumDevice + DeviceBuilder, retry/poll logic
│ ├── adb.rs AdbTransport: APK install, port-forward, gRPC calls
│ ├── hierarchy.rs XML view-hierarchy parser (quick-xml)
│ ├── transport.rs Transport trait
│ ├── types.rs Selector, Direction, Bounds
│ ├── mock.rs MockTransport (feature = "mock")
│ ├── ios.rs IosTransport stub (not yet implemented)
│ ├── maestro-app.apk bundled Maestro driver v2.6.1
│ └── maestro-server.apk bundled Maestro server v2.6.1
├── proto/
│ └── maestro_android.proto
├── tests/
│ └── integration.rs
└── Cargo.toml
Publishing a new version
The Maestro driver APKs are downloaded at build time from this repo's GitHub releases. When bumping the crate version:
- Update
versioninpodium/Cargo.toml. - Create a GitHub release tagged
v<version>(e.g.v0.1.0). - Upload
maestro-app-2.6.1.apkandmaestro-server-2.6.1.apkas release assets (copy from the previous release if the Maestro version hasn't changed). cargo publish -p podium
The APK asset names encode the Maestro version (MAESTRO_VERSION in build.rs) so they survive across Podium releases without re-upload as long as the Maestro version is unchanged.
Known limitations
- Android only.
IosTransportexists as a stub but returnsNotSupportedfor all calls. input_textreplaces the focused field's content via the gRPCInputTextcall; it does not simulate per-keystroke events.hide_keyboardsendsKEYCODE_BACK; it only works while the keyboard is shown.- Swipe coordinates are hardcoded for a 1080×2400 screen — correct for most emulators, may need adjustment for small or unusual resolutions.