Skip to main content

source/
source.rs

1use allwright_surface_mobile::{ConnectOptions, LaunchOptions, MobilePlatform};
2use allwright_surface_mobile_android::{connect, dump_source, launch_app};
3use std::env;
4use std::error::Error;
5use std::fs;
6use std::path::PathBuf;
7
8fn main() -> Result<(), Box<dyn Error>> {
9    let args = parse_args(env::args().skip(1).collect())?;
10
11    let session = connect(&ConnectOptions {
12        platform: MobilePlatform::Android,
13        device: args.device,
14        adb_endpoint: args.adb_endpoint,
15        preserve_app_state: false,
16        timeout_ms: Some(10_000),
17    })?;
18
19    let page = launch_app(
20        &session.browser_session,
21        &LaunchOptions {
22            apk_path: Some(args.apk_path),
23            app_id: args.app_id,
24            launch_activity: args.activity,
25            stop_before_launch: args.stop_before_launch,
26            timeout_ms: Some(30_000),
27        },
28    )?;
29
30    let source = dump_source(&session.browser_session, &page.page_session)?;
31    fs::write(&args.output, source.source)?;
32
33    println!("{}", args.output.display());
34    Ok(())
35}
36
37#[derive(Debug)]
38struct SourceArgs {
39    apk_path: String,
40    output: PathBuf,
41    app_id: Option<String>,
42    activity: Option<String>,
43    device: Option<String>,
44    adb_endpoint: Option<String>,
45    stop_before_launch: bool,
46}
47
48fn parse_args(args: Vec<String>) -> Result<SourceArgs, Box<dyn Error>> {
49    let mut apk_path = String::new();
50    let mut output = None;
51    let mut app_id = None;
52    let mut activity = None;
53    let mut device = None;
54    let mut adb_endpoint = None;
55    let mut stop_before_launch = false;
56
57    let mut index = 0usize;
58    while index < args.len() {
59        match args[index].as_str() {
60            "--apk" => {
61                index += 1;
62                apk_path = required_value(&args, index, "--apk")?;
63            }
64            "--out" => {
65                index += 1;
66                output = Some(PathBuf::from(required_value(&args, index, "--out")?));
67            }
68            "--app-id" => {
69                index += 1;
70                app_id = Some(required_value(&args, index, "--app-id")?);
71            }
72            "--activity" => {
73                index += 1;
74                activity = Some(required_value(&args, index, "--activity")?);
75            }
76            "--device" => {
77                index += 1;
78                device = Some(required_value(&args, index, "--device")?);
79            }
80            "--adb-endpoint" => {
81                index += 1;
82                adb_endpoint = Some(required_value(&args, index, "--adb-endpoint")?);
83            }
84            "--stop-before-launch" => stop_before_launch = true,
85            "--help" | "-h" => {
86                print_usage();
87                std::process::exit(0);
88            }
89            other => {
90                return Err(format!("unknown argument `{other}`").into());
91            }
92        }
93        index += 1;
94    }
95
96    if apk_path.trim().is_empty() {
97        return Err("missing required `--apk <path>` argument".into());
98    }
99
100    Ok(SourceArgs {
101        apk_path,
102        output: output.unwrap_or_else(|| PathBuf::from("tmp/mobile-android-source.xml")),
103        app_id,
104        activity,
105        device,
106        adb_endpoint,
107        stop_before_launch,
108    })
109}
110
111fn required_value(args: &[String], index: usize, flag: &str) -> Result<String, Box<dyn Error>> {
112    args.get(index)
113        .cloned()
114        .ok_or_else(|| format!("missing value for `{flag}`").into())
115}
116
117fn print_usage() {
118    eprintln!(
119        "Usage: cargo run -p allwright-surface-mobile-android --example source -- \
120  --apk /path/to/app.apk \
121  --out tmp/mobile-android-source.xml \
122  [--app-id dev.allwright.sample] \
123  [--activity .MainActivity] \
124  [--device emulator-5554] \
125  [--adb-endpoint 192.168.1.10:5555] \
126  [--stop-before-launch]"
127    );
128}