use droidrun_core::driver::android::AndroidDriver;
use droidrun_core::driver::DeviceDriver;
use droidrun_core::ui::filter::ConciseFilter;
use droidrun_core::ui::formatter::IndexedFormatter;
use droidrun_core::ui::provider::AndroidStateProvider;
use droidrun_core::ui::search::{clickable, get_element_center, text_matches};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
tracing_subscriber::fmt()
.with_env_filter("info")
.with_target(false)
.init();
let mut driver = AndroidDriver::new(None, true);
driver.connect().await?;
println!("Connected!");
driver.press_key(3).await?;
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
let apps = driver.get_apps(false).await?;
println!("\nAvailable apps:");
for (i, app) in apps.iter().enumerate() {
println!(" {}. {} ({})", i + 1, app.label, app.package);
}
let target_package = "com.android.settings";
println!("\nOpening {target_package}...");
let result = driver.start_app(target_package, None).await?;
println!("Result: {}", result.trim());
tokio::time::sleep(std::time::Duration::from_secs(2)).await;
let provider = AndroidStateProvider::new(ConciseFilter, IndexedFormatter, false);
let state = provider.get_state(&driver).await?;
println!("\nCurrent app: {} ({})", state.phone_state.current_app, state.phone_state.package_name);
println!("Elements on screen: {}", state.elements.len());
println!("\n{}", state.formatted_text);
let tree = driver.get_ui_tree().await?;
let a11y = tree.get("a11y_tree").unwrap_or(&tree);
let clickables = clickable()(&[a11y.clone()]);
let with_text: Vec<_> = clickables
.iter()
.filter(|n| {
n.get("text")
.and_then(|v| v.as_str())
.map(|s| !s.is_empty())
.unwrap_or(false)
})
.collect();
println!("\nClickable items with text:");
for (i, node) in with_text.iter().take(10).enumerate() {
let text = node.get("text").and_then(|v| v.as_str()).unwrap_or("");
let (cx, cy) = get_element_center(node);
println!(" {}. '{}' at ({}, {})", i + 1, text, cx, cy);
}
let search_terms = ["Network", "Wi-Fi", "Display", "Battery", "About"];
for term in search_terms {
let filter = text_matches(term);
let results = filter(&[a11y.clone()]);
if !results.is_empty() {
let (cx, cy) = get_element_center(&results[0]);
println!("\nFound '{term}' at ({cx}, {cy})");
println!("Tapping...");
driver.tap(cx, cy).await?;
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
let new_state = provider.get_state(&driver).await?;
println!("Now in: {} ({})", new_state.phone_state.current_app, new_state.phone_state.package_name);
println!("Elements: {}", new_state.elements.len());
break;
}
}
println!("\nGoing back...");
driver.press_key(4).await?; tokio::time::sleep(std::time::Duration::from_millis(500)).await;
driver.press_key(3).await?; println!("Done!");
Ok(())
}