Skip to content

A Rust library for spawning or discovering Android Emulators and controlling them via the gRPC controller protocol

Notifications You must be signed in to change notification settings

rust-mobile/android-emulator-rs

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Android Emulator gRPC Control Library

A Rust library for controlling Android Emulators via gRPC.

Features

  • Discover Emulator AVDs: List available Android Virtual Devices
  • Spawn Emulators: Configure and start emulator instances programmatically
  • Find Running Emulators: Locate existing emulator instances via ADB protocol
  • gRPC Control: Full bindings to the Android Emulator gRPC controller API
  • Authentication Support: No auth, Basic Auth, and JWT authentication for gRPC
  • Export Limited JWT Tokens: Export JWT tokens that can temporarily grant other tools / clients limited access to the emulator.

Usage

List Available AVDs

#[tokio::main]
async fn main() {
    let avds = android_emulator::list_avds().await.expect("Failed to list AVDs");
    println!("Available AVDs: {:?}", avds);
}

Start a Headless Emulator

use android_emulator::{EmulatorConfig, list_avds};
use std::time::Duration;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Get the first available AVD
    let avds = list_avds().await?;
    let avd_name = avds.first().ok_or("No AVDs found")?;

    let config = EmulatorConfig::new(avd_name)
        .with_window(false)
        .with_snapshot_load(false)
        .with_snapshot_save(false)
        .with_boot_animation(false);

    let instance = config.spawn().await?;

    // Connect to the emulator
    let mut client = instance.connect(Some(Duration::from_secs(120)), true).await?;

    // Wait until the emulator is fully booted
    let elapsed = client.wait_until_booted(Duration::from_secs(200), None).await?;

    println!("Emulator ready at: {}", instance.grpc_endpoint());
    println!("Booted in {:.1} seconds", elapsed.as_secs_f64());
    Ok(())
}

Find a Running Emulator

Find an existing emulator instance that's running a particular AVD and connect to it:

use android_emulator::{list_avds, list_emulators};
use std::time::Duration;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Get the first available AVD
    let avds = list_avds().await?;
    let avd_id = avds.first().ok_or("No AVDs found")?;

    // Find a running emulator with that AVD
    let emulators = list_emulators().await?;
    let instance = emulators
        .into_iter()
        .find(|e| e.avd_id().unwrap_or_default() == avd_id)
        .ok_or("No running emulator found")?;

    println!("Found emulator: {}", instance.serial());
    println!("gRPC endpoint: {}", instance.grpc_endpoint());

    // Connect to the emulator
    let mut client = instance.connect(Some(Duration::from_secs(30)), true).await?;

    // Use the client...
    Ok(())
}

Control the Emulator via gRPC

use android_emulator::{EmulatorConfig, list_avds};
use std::time::Duration;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Get the first available AVD
    let avds = list_avds().await?;
    let avd_name = avds.first().ok_or("No AVDs found")?;

    // Start the emulator
    let instance = EmulatorConfig::new(avd_name)
        .with_window(false)
        .spawn()
        .await?;

    let mut client = instance.connect(Some(Duration::from_secs(120)), true).await?;

    // Get emulator status
    let status = client.protocol_mut().get_status(()).await?.into_inner();
    println!("Emulator status: {:?}", status);

    // Set GPS coordinates
    let gps_state = android_emulator::proto::GpsState {
        latitude: 37.7749,
        longitude: -122.4194,
        ..Default::default()
    };

    client.protocol_mut().set_gps(gps_state).await?;
    Ok(())
}

Send Touch Events

use android_emulator::{EmulatorConfig, list_avds};
use android_emulator::proto::{Touch, TouchEvent};
use std::time::Duration;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Get the first available AVD
    let avds = list_avds().await?;
    let avd_name = avds.first().ok_or("No AVDs found")?;

    // Start the emulator
    let instance = EmulatorConfig::new(avd_name)
        .with_window(false)
        .spawn()
        .await?;

    let mut client = instance.connect(Some(Duration::from_secs(120)), true).await?;

    let touch = Touch {
        x: 500,
        y: 1000,
        identifier: 1,
        pressure: 100,
        ..Default::default()
    };

    let touch_event = TouchEvent {
        touches: vec![touch],
        display: 0,
    };

    client.protocol_mut().send_touch(touch_event).await?;
    Ok(())
}

Android SDK

The library depends on finding an Android SDK installation in order to be able to spawn new emulators and will look for the Android SDK as follows:

  1. ANDROID_HOME environment variable
  2. ANDROID_SDK_ROOT environment variable (deprecated)
  3. Platform-specific default locations:
    • Linux: $HOME/Android/sdk or $HOME/Android/Sdk
    • macOS: $HOME/Library/Android/sdk
    • Windows: %LOCALAPPDATA%/Android/Sdk

Emulator AVDs: At least one Android Virtual Device must be created

gRPC Protocol

The library provides complete bindings to the Android Emulator Controller gRPC API, including:

  • Sensor control (accelerometer, GPS, etc.)
  • Physical model control (rotation, position, etc.)
  • Battery state management
  • Screenshot and screen streaming
  • Audio streaming
  • Touch, mouse, and keyboard input
  • Phone calls and SMS
  • VM state management
  • Display configuration
  • And more...

Development

Regenerating Protobuf Bindings

This crate includes pre-generated protobuf bindings, so consumers don't need protoc installed.

If you modify the .proto files, regenerate the bindings by running:

cargo xtask codegen

This will update android-emulator/src/generated/android.emulation.control.rs.

License

Licensed under either of

at your option.

About

A Rust library for spawning or discovering Android Emulators and controlling them via the gRPC controller protocol

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages