Platforms
Android Emulator
Troupe runs your app on Android Emulators that it creates, boots and deletes itself. This page covers what your machine needs, how Troupe drives an emulator, and what the platform can and cannot do.
The platform's id is android-emulator. A troupe.config.ts may write android.
Requirements
- macOS on Apple silicon. Linux on x86-64 with KVM is planned for Android and is not verified yet.
- An Android SDK with the
emulatorandplatform-toolspackages and a system image for the host's architecture:arm64-v8aon Apple silicon. - Bun 1.4.3 or newer.
- Memory for each emulator: the guest gets 4096 MB by default, and Troupe budgets 3,900 MB more for the emulator around it.
Install a system image with the SDK's own tool:
sdkmanager "system-images;android-36;google_apis;arm64-v8a"Prepare the platform
Run this once in your project:
bunx troupe install androidIt looks for your SDK in ANDROID_HOME, then ANDROID_SDK_ROOT, then ~/Library/Android/sdk, and records
the one it finds in ~/.troupe/host.json. From then on the runtime reads only the recorded path, never the
environment of the command that started it. It then runs the environment checks and starts one emulator to
prove the path. There is nothing to build: the driver ships with the platform package.
A project then names the device and the app:
import { defineConfig } from '@alivelabs/troupe'
export default defineConfig({
projects: [
{
name: 'android',
use: { platform: 'android', deviceType: 'Pixel 8', os: '36', app: './build/shop.apk' },
},
],
})How Troupe drives an emulator
Troupe owns each part: it does not depend on Appium, UiAutomator2 server builds or another driver.
| Part | What it does |
|---|---|
| Troupe's adb client | Speaks the adb server's wire protocol itself: installs and launches apps, runs shell commands, reads logcat |
| The emulator | Troupe writes its own AVDs into $TROUPE_HOME/avd and boots them with the SDK's emulator |
| The instrumentation driver | Two APKs Troupe installs on the emulator. They read the accessibility tree, resolve locators and perform test actions |
| scrcpy | The scrcpy server, version 4.0, captures the screen as H.264 for the live stream and delivers live input |
Devices are Troupe's own
Troupe names its AVDs troupe-… and acts only on an emulator whose console confirms it runs one of them. A
phone you have plugged in, or an emulator you started from Android Studio, is never touched.
Troupe uses the adb server that already runs on your machine. When none runs, it starts one with the SDK's
adb and leaves it running. It never stops or restarts a server that is already running.
Emulators take console and adb ports in adb's usual window, 5554 to 5584. The driver is reached through the adb connection, so it needs no forwarded port.
Apps
Troupe installs .apk files. An Android App Bundle (.aab) is not installable: build an APK from it first.
An APK built for another architecture is refused with APP_INSTALL_FAILED and the reason wrong-arch.
Android apps have no process arguments or environment. Launch arguments reach the app as the string-array
intent extra troupe.args, and each launch environment variable as the string extra troupe.env.<NAME>.
Clearing an app's data and deep links both work.
Capabilities
The runtime reports these through runtime.capabilities,
and refuses a call the platform cannot serve with CAPABILITY_UNSUPPORTED before it touches the device.
| Area | Android Emulator |
|---|---|
| Locators | Role, text, label, placeholder and test id, with regular expressions; system UI through screen.system |
| Test id | resource-id (React Native's testID) |
| Touch | Up to ten contacts: tap, double tap, long press, swipe, drag, pinch, scroll, gestures |
| Keyboard | Key events and text |
| Hardware buttons | home, back, appSwitch, power, volumeUp, volumeDown |
| Rotation, hiding the keyboard | Yes |
| Permissions | calendar, camera, contacts, location, locationAlways, microphone, motion, notifications, photos |
| System settings | Location and appearance |
| Screenshots | Yes |
| Live stream | H.264 |
| Live input | The same touch, keys, buttons and rotation as tests |
| Logs | System log, app log and crash reports |
| Screen recording | No |
Limits
- A Jetpack Compose node has a test id only when the app sets
testTagsAsResourceId. - The clipboard cannot be read or written:
system.getClipboardandsystem.setClipboardare refused. - The permission
remindersis not offered. - The stream does not take frame-rate or bitrate changes while it runs.
- Foldable device types are not offered.
Device types and OS versions
Troupe offers four device types:
deviceType | Name | Screen |
|---|---|---|
pixel_8 | Pixel 8 (the default) | 1080 × 2400 px at 420 dpi |
pixel_9 | Pixel 9 | 1080 × 2424 px at 420 dpi |
medium_phone | Medium Phone | 1080 × 2400 px at 420 dpi |
pixel_tablet | Pixel Tablet | 2560 × 1600 px at 320 dpi |
A spec may name one by id or by name.
osis the API level as a string, such as'36'. Without one, or with'latest', Troupe takes the newest installed image.variantis the system image's tag. The default isgoogle_apis. Name another installed tag, such asgoogle_apis_playstore, to use it.
Troupe lists the images installed in your SDK for the host's architecture. An image that is not installed
fails with ENVIRONMENT_ANDROID_IMAGE_MISSING. Its fix is the sdkmanager command that installs it.
List what a runtime offers with catalog.deviceTypes and
catalog.osVersions:
const { osVersions } = await troupe.call('catalog.osVersions', { platform: 'android-emulator' })Host settings
troupe install android writes platforms.android-emulator in $TROUPE_HOME/host.json. You can edit these
keys:
| Key | Default | What it does |
|---|---|---|
sdkRoot | The SDK troupe install android found | The Android SDK Troupe uses |
maxDevices | 2 | The most emulators running at once |
memoryMb | 4096 | The guest's memory |
enabled | true | false switches the platform off: a request for it fails with ENVIRONMENT_PLATFORM_DISABLED |
Next
- iOS Simulator
- Fixtures and options: launch arguments, permissions and app isolation in tests
- Sessions: how a device is acquired and released