mirror of
https://github.com/tauri-apps/tauri.git
synced 2024-12-19 08:31:35 +03:00
feat(cli): add option to run on specific Android emulator/device (#5093)
This commit is contained in:
parent
e22d21beaf
commit
82e8751ae8
2
tooling/cli/Cargo.lock
generated
2
tooling/cli/Cargo.lock
generated
@ -293,7 +293,7 @@ checksum = "c1db59621ec70f09c5e9b597b220c7a2b43611f4710dc03ceb8748637775692c"
|
||||
[[package]]
|
||||
name = "cargo-mobile"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/tauri-apps/cargo-mobile?branch=dev#228f0eb83ccbc7bfeb0103d2f68b6664691a289d"
|
||||
source = "git+https://github.com/tauri-apps/cargo-mobile?branch=dev#909edf9337ec0cb42c76e0a34af61e99b15ccfe0"
|
||||
dependencies = [
|
||||
"cocoa",
|
||||
"colored 1.9.3",
|
||||
|
@ -28,7 +28,7 @@ name = "cargo-tauri"
|
||||
path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
# cargo-mobile = { path = "../../../cargo-mobile/", default-features = false }
|
||||
#cargo-mobile = { path = "../../../cargo-mobile/", default-features = false }
|
||||
cargo-mobile = { git = "https://github.com/tauri-apps/cargo-mobile", branch = "dev", default-features = false }
|
||||
textwrap = { version = "0.11.0", features = ["term_size"] }
|
||||
interprocess = "1"
|
||||
|
@ -7,6 +7,7 @@ use cargo_mobile::{
|
||||
adb,
|
||||
config::{Config as AndroidConfig, Metadata as AndroidMetadata, Raw as RawAndroidConfig},
|
||||
device::Device,
|
||||
emulator,
|
||||
env::Env,
|
||||
target::Target,
|
||||
},
|
||||
@ -17,7 +18,11 @@ use cargo_mobile::{
|
||||
util::prompt,
|
||||
};
|
||||
use clap::{Parser, Subcommand};
|
||||
use std::env::set_var;
|
||||
use std::{
|
||||
env::set_var,
|
||||
thread::{sleep, spawn},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use super::{
|
||||
ensure_init, get_app,
|
||||
@ -136,19 +141,30 @@ fn delete_codegen_vars() {
|
||||
}
|
||||
}
|
||||
|
||||
fn device_prompt<'a>(env: &'_ Env) -> Result<Device<'a>, PromptError<adb::device_list::Error>> {
|
||||
fn adb_device_prompt<'a>(
|
||||
env: &'_ Env,
|
||||
target: Option<&str>,
|
||||
) -> Result<Device<'a>, PromptError<adb::device_list::Error>> {
|
||||
let device_list =
|
||||
adb::device_list(env).map_err(|cause| PromptError::detection_failed("Android", cause))?;
|
||||
if !device_list.is_empty() {
|
||||
let index = if device_list.len() > 1 {
|
||||
prompt::list(
|
||||
concat!("Detected ", "Android", " devices"),
|
||||
device_list.iter(),
|
||||
"device",
|
||||
None,
|
||||
"Device",
|
||||
)
|
||||
.map_err(|cause| PromptError::prompt_failed("Android", cause))?
|
||||
if let Some(t) = target {
|
||||
let t = t.to_lowercase();
|
||||
device_list
|
||||
.iter()
|
||||
.position(|d| d.name().to_lowercase().starts_with(&t))
|
||||
.unwrap_or_default()
|
||||
} else {
|
||||
prompt::list(
|
||||
concat!("Detected ", "Android", " devices"),
|
||||
device_list.iter(),
|
||||
"device",
|
||||
None,
|
||||
"Device",
|
||||
)
|
||||
.map_err(|cause| PromptError::prompt_failed("Android", cause))?
|
||||
}
|
||||
} else {
|
||||
0
|
||||
};
|
||||
@ -164,8 +180,67 @@ fn device_prompt<'a>(env: &'_ Env) -> Result<Device<'a>, PromptError<adb::device
|
||||
}
|
||||
}
|
||||
|
||||
fn emulator_prompt(
|
||||
env: &'_ Env,
|
||||
target: Option<&str>,
|
||||
) -> Result<emulator::Emulator, PromptError<adb::device_list::Error>> {
|
||||
let emulator_list = emulator::avd_list(env).unwrap_or_default();
|
||||
if emulator_list.is_empty() {
|
||||
Err(PromptError::none_detected("Android emulator"))
|
||||
} else {
|
||||
let index = if emulator_list.len() > 1 {
|
||||
if let Some(t) = target {
|
||||
let t = t.to_lowercase();
|
||||
emulator_list
|
||||
.iter()
|
||||
.position(|d| d.name().to_lowercase().starts_with(&t))
|
||||
.unwrap_or_default()
|
||||
} else {
|
||||
prompt::list(
|
||||
concat!("Detected ", "Android", " emulators"),
|
||||
emulator_list.iter(),
|
||||
"emulator",
|
||||
None,
|
||||
"Emulator",
|
||||
)
|
||||
.map_err(|cause| PromptError::prompt_failed("Android emulator", cause))?
|
||||
}
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
Ok(emulator_list.iter().nth(index).cloned().unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
fn device_prompt<'a>(
|
||||
env: &'_ Env,
|
||||
target: Option<&str>,
|
||||
) -> Result<Device<'a>, PromptError<adb::device_list::Error>> {
|
||||
if let Ok(device) = adb_device_prompt(env, target) {
|
||||
Ok(device)
|
||||
} else {
|
||||
let emulator = emulator_prompt(env, target)?;
|
||||
let handle = emulator.start(env).map_err(|e| {
|
||||
PromptError::prompt_failed(
|
||||
"Android emulator",
|
||||
std::io::Error::new(std::io::ErrorKind::Other, e.to_string()),
|
||||
)
|
||||
})?;
|
||||
spawn(move || {
|
||||
let _ = handle.wait();
|
||||
});
|
||||
loop {
|
||||
sleep(Duration::from_secs(2));
|
||||
if let Ok(device) = adb_device_prompt(env, Some(emulator.name())) {
|
||||
return Ok(device);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn detect_target_ok<'a>(env: &Env) -> Option<&'a Target<'a>> {
|
||||
device_prompt(env).map(|device| device.target()).ok()
|
||||
device_prompt(env, None).map(|device| device.target()).ok()
|
||||
}
|
||||
|
||||
fn open_and_wait(config: &AndroidConfig, env: &Env) -> ! {
|
||||
@ -174,6 +249,6 @@ fn open_and_wait(config: &AndroidConfig, env: &Env) -> ! {
|
||||
log::error!("{}", e);
|
||||
}
|
||||
loop {
|
||||
std::thread::sleep(std::time::Duration::from_secs(24 * 60 * 60));
|
||||
sleep(Duration::from_secs(24 * 60 * 60));
|
||||
}
|
||||
}
|
||||
|
@ -15,13 +15,18 @@ use cargo_mobile::{
|
||||
adb,
|
||||
config::{Config as AndroidConfig, Metadata as AndroidMetadata},
|
||||
device::RunError as DeviceRunError,
|
||||
emulator,
|
||||
env::Env,
|
||||
},
|
||||
config::app::App,
|
||||
opts::{NoiseLevel, Profile},
|
||||
};
|
||||
|
||||
use std::env::set_var;
|
||||
use std::{
|
||||
env::set_var,
|
||||
thread::{sleep, spawn},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
const WEBVIEW_CLIENT_CLASS_EXTENSION: &str = "
|
||||
@android.annotation.SuppressLint(\"WebViewClientOnReceivedSslError\")
|
||||
@ -50,6 +55,8 @@ pub struct Options {
|
||||
/// Open Android Studio instead of trying to run on a connected device
|
||||
#[clap(short, long)]
|
||||
pub open: bool,
|
||||
/// Runs on the given device name
|
||||
pub device: Option<String>,
|
||||
}
|
||||
|
||||
impl From<Options> for crate::dev::Options {
|
||||
@ -112,9 +119,29 @@ fn run_dev(
|
||||
let env = env()?;
|
||||
init_dot_cargo(app, Some((&env, config)))?;
|
||||
|
||||
if let Some(device) = &options.device {
|
||||
let emulators = emulator::avd_list(&env).unwrap_or_default();
|
||||
for emulator in emulators {
|
||||
if emulator
|
||||
.name()
|
||||
.to_lowercase()
|
||||
.starts_with(&device.to_lowercase())
|
||||
{
|
||||
log::info!("Starting emulator {}", emulator.name());
|
||||
let handle = emulator.start(&env)?;
|
||||
spawn(move || {
|
||||
let _ = handle.wait();
|
||||
});
|
||||
sleep(Duration::from_secs(3));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let open = options.open;
|
||||
let exit_on_panic = options.exit_on_panic;
|
||||
let no_watch = options.no_watch;
|
||||
let device = options.device;
|
||||
interface.mobile_dev(
|
||||
MobileOptions {
|
||||
debug: true,
|
||||
@ -135,7 +162,14 @@ fn run_dev(
|
||||
if open {
|
||||
open_and_wait(config, &env)
|
||||
} else {
|
||||
match run(options, config, &env, metadata, noise_level) {
|
||||
match run(
|
||||
device.as_deref(),
|
||||
options,
|
||||
config,
|
||||
&env,
|
||||
metadata,
|
||||
noise_level,
|
||||
) {
|
||||
Ok(c) => {
|
||||
crate::dev::wait_dev_process(c.clone(), move |status, reason| {
|
||||
crate::dev::on_app_exit(status, reason, exit_on_panic, no_watch)
|
||||
@ -162,6 +196,7 @@ enum RunError {
|
||||
}
|
||||
|
||||
fn run(
|
||||
device: Option<&str>,
|
||||
options: MobileOptions,
|
||||
config: &AndroidConfig,
|
||||
env: &Env,
|
||||
@ -176,7 +211,7 @@ fn run(
|
||||
|
||||
let build_app_bundle = metadata.asset_packs().is_some();
|
||||
|
||||
device_prompt(env)
|
||||
device_prompt(env, device)
|
||||
.map_err(RunError::FailedToPromptForDevice)?
|
||||
.run(
|
||||
config,
|
||||
|
Loading…
Reference in New Issue
Block a user