From 9f75d06228fcb7036cf7a4e215abc7bc8d1a0a56 Mon Sep 17 00:00:00 2001 From: Lucas Fernandes Nogueira Date: Tue, 13 Aug 2024 22:07:02 -0300 Subject: [PATCH] fix(cli): adb port forward error handling, add logs, closes #9509 (#10604) --- .changes/android-port-forward-fixes.md | 6 ++ tooling/cli/Cargo.lock | 4 +- tooling/cli/Cargo.toml | 2 +- .../mobile/android/android_studio_script.rs | 61 +++++++++++++++++-- tooling/cli/src/mobile/android/build.rs | 1 + tooling/cli/src/mobile/android/dev.rs | 6 +- tooling/cli/src/mobile/ios/build.rs | 1 + tooling/cli/src/mobile/ios/dev.rs | 1 + tooling/cli/src/mobile/mod.rs | 8 +++ 9 files changed, 80 insertions(+), 10 deletions(-) create mode 100644 .changes/android-port-forward-fixes.md diff --git a/.changes/android-port-forward-fixes.md b/.changes/android-port-forward-fixes.md new file mode 100644 index 000000000..97b205d7e --- /dev/null +++ b/.changes/android-port-forward-fixes.md @@ -0,0 +1,6 @@ +--- +"tauri-cli": patch:bug +"@tauri-apps/cli": patch:bug +--- + +Fixes `android dev` port forward failing under some conditions, add better logging and error handling. diff --git a/tooling/cli/Cargo.lock b/tooling/cli/Cargo.lock index 006e17afb..a1db74a29 100644 --- a/tooling/cli/Cargo.lock +++ b/tooling/cli/Cargo.lock @@ -557,9 +557,9 @@ dependencies = [ [[package]] name = "cargo-mobile2" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a375de334eab8b47e0f02421509c3fb6910499ec8353d36e4d977c2b5d7646b" +checksum = "ebaedf7b7e292b7f41f892f5c96ee15544e21814e89d0b6b8dc06740a69dabe5" dependencies = [ "colored", "core-foundation", diff --git a/tooling/cli/Cargo.toml b/tooling/cli/Cargo.toml index fc00a5e04..556271a6c 100644 --- a/tooling/cli/Cargo.toml +++ b/tooling/cli/Cargo.toml @@ -39,7 +39,7 @@ name = "cargo-tauri" path = "src/main.rs" [dependencies] -cargo-mobile2 = { version = "0.13.1", default-features = false } +cargo-mobile2 = { version = "0.13.2", default-features = false } jsonrpsee = { version = "0.24", features = [ "server" ] } jsonrpsee-core = "0.24" jsonrpsee-client-transport = { version = "0.24", features = [ "ws" ] } diff --git a/tooling/cli/src/mobile/android/android_studio_script.rs b/tooling/cli/src/mobile/android/android_studio_script.rs index bd6e02797..169d3fbf5 100644 --- a/tooling/cli/src/mobile/android/android_studio_script.rs +++ b/tooling/cli/src/mobile/android/android_studio_script.rs @@ -85,12 +85,35 @@ pub fn command(options: Options) -> Result<()> { if let Some(port) = dev_url.and_then(|url| url.port_or_known_default()) { let forward = format!("tcp:{port}"); - // ignore errors in case we do not have a device available - let _ = adb::adb(&env, ["reverse", &forward, &forward]) - .stdin_file(os_pipe::dup_stdin().unwrap()) - .stdout_file(os_pipe::dup_stdout().unwrap()) - .stderr_capture() - .run(); + log::info!("Forwarding port {port} with adb"); + + let devices = adb::device_list(&env).unwrap_or_default(); + + // clear port forwarding for all devices + for device in &devices { + remove_adb_reverse(&env, device.serial_no(), &forward); + } + + // if there's a known target, we should force use it + if let Some(target_device) = &cli_options.target_device { + run_adb_reverse(&env, &target_device.id, &forward, &forward).with_context(|| { + format!( + "failed to forward port with adb, is the {} device connected?", + target_device.name, + ) + })?; + } else if devices.len() == 1 { + let device = devices.first().unwrap(); + run_adb_reverse(&env, device.serial_no(), &forward, &forward).with_context(|| { + format!( + "failed to forward port with adb, is the {} device connected?", + device.name(), + ) + })?; + } else { + anyhow::bail!("Multiple Android devices are connected ({}), please disconnect devices you do not intend to use so Tauri can determine which to use", + devices.iter().map(|d| d.name()).collect::>().join(", ")); + } } } @@ -152,3 +175,29 @@ fn validate_lib(path: &Path) -> Result<()> { Ok(()) } + +fn run_adb_reverse( + env: &cargo_mobile2::android::env::Env, + device_serial_no: &str, + remote: &str, + local: &str, +) -> std::io::Result { + adb::adb(env, ["-s", device_serial_no, "reverse", remote, local]) + .stdin_file(os_pipe::dup_stdin().unwrap()) + .stdout_file(os_pipe::dup_stdout().unwrap()) + .stderr_file(os_pipe::dup_stdout().unwrap()) + .run() +} + +fn remove_adb_reverse( + env: &cargo_mobile2::android::env::Env, + device_serial_no: &str, + remote: &str, +) { + // ignore errors in case the port is not forwarded + let _ = adb::adb(env, ["-s", device_serial_no, "reverse", "--remove", remote]) + .stdin_file(os_pipe::dup_stdin().unwrap()) + .stdout_file(os_pipe::dup_stdout().unwrap()) + .stderr_file(os_pipe::dup_stdout().unwrap()) + .run(); +} diff --git a/tooling/cli/src/mobile/android/build.rs b/tooling/cli/src/mobile/android/build.rs index 8962a51dd..ad29b1de3 100644 --- a/tooling/cli/src/mobile/android/build.rs +++ b/tooling/cli/src/mobile/android/build.rs @@ -202,6 +202,7 @@ fn run_build( noise_level, vars: Default::default(), config: build_options.config.clone(), + target_device: None, }; let handle = write_options( &tauri_config.lock().unwrap().as_ref().unwrap().identifier, diff --git a/tooling/cli/src/mobile/android/dev.rs b/tooling/cli/src/mobile/android/dev.rs index 6400314ec..bb22c3fde 100644 --- a/tooling/cli/src/mobile/android/dev.rs +++ b/tooling/cli/src/mobile/android/dev.rs @@ -14,7 +14,7 @@ use crate::{ flock, }, interface::{AppInterface, AppSettings, Interface, MobileOptions, Options as InterfaceOptions}, - mobile::{write_options, CliOptions, DevChild, DevProcess}, + mobile::{write_options, CliOptions, DevChild, DevProcess, TargetDevice}, ConfigValue, Result, }; use clap::{ArgAction, Parser}; @@ -233,6 +233,10 @@ fn run_dev( noise_level, vars: Default::default(), config: dev_options.config.clone(), + target_device: device.as_ref().map(|d| TargetDevice { + id: d.serial_no().to_string(), + name: d.name().to_string(), + }), }; let _handle = write_options( diff --git a/tooling/cli/src/mobile/ios/build.rs b/tooling/cli/src/mobile/ios/build.rs index f53cb9205..74e1a3ef9 100644 --- a/tooling/cli/src/mobile/ios/build.rs +++ b/tooling/cli/src/mobile/ios/build.rs @@ -284,6 +284,7 @@ fn run_build( noise_level, vars: Default::default(), config: build_options.config.clone(), + target_device: None, }; let handle = write_options( &tauri_config.lock().unwrap().as_ref().unwrap().identifier, diff --git a/tooling/cli/src/mobile/ios/dev.rs b/tooling/cli/src/mobile/ios/dev.rs index b11637c80..80ff552c9 100644 --- a/tooling/cli/src/mobile/ios/dev.rs +++ b/tooling/cli/src/mobile/ios/dev.rs @@ -392,6 +392,7 @@ fn run_dev( noise_level, vars: Default::default(), config: dev_options.config.clone(), + target_device: None, }; let _handle = write_options( &tauri_config.lock().unwrap().as_ref().unwrap().identifier, diff --git a/tooling/cli/src/mobile/mod.rs b/tooling/cli/src/mobile/mod.rs index b1c746e51..a92d57c54 100644 --- a/tooling/cli/src/mobile/mod.rs +++ b/tooling/cli/src/mobile/mod.rs @@ -135,6 +135,12 @@ impl Target { } } +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct TargetDevice { + id: String, + name: String, +} + #[derive(Debug, Clone, Serialize, Deserialize)] pub struct CliOptions { pub dev: bool, @@ -143,6 +149,7 @@ pub struct CliOptions { pub noise_level: NoiseLevel, pub vars: HashMap, pub config: Option, + pub target_device: Option, } impl Default for CliOptions { @@ -154,6 +161,7 @@ impl Default for CliOptions { noise_level: Default::default(), vars: Default::default(), config: None, + target_device: None, } } }