Allow to connect to the dev server from a physical Android device (#3634)
* fix(android): now dev server just works on devices * fix: allow custom port for Android app development * refactor: simplified URL creation in LaunchBuilder
This commit is contained in:
1 parent
d7e64d5d24
commit
67515ce812
4 files changed
+55
-14
No files matched your search
@@ -59,7 +59,8 @@ use std::{
|
|||||||
pub const CLI_ENABLED_ENV: &str = "DIOXUS_CLI_ENABLED";
|
pub const CLI_ENABLED_ENV: &str = "DIOXUS_CLI_ENABLED";
|
||||||
pub const SERVER_IP_ENV: &str = "IP";
|
pub const SERVER_IP_ENV: &str = "IP";
|
||||||
pub const SERVER_PORT_ENV: &str = "PORT";
|
pub const SERVER_PORT_ENV: &str = "PORT";
|
||||||
pub const DEVSERVER_RAW_ADDR_ENV: &str = "DIOXUS_DEVSERVER_ADDR";
|
pub const DEVSERVER_IP_ENV: &str = "DIOXUS_DEVSERVER_IP";
|
||||||
|
pub const DEVSERVER_PORT_ENV: &str = "DIOXUS_DEVSERVER_PORT";
|
||||||
pub const ALWAYS_ON_TOP_ENV: &str = "DIOXUS_ALWAYS_ON_TOP";
|
pub const ALWAYS_ON_TOP_ENV: &str = "DIOXUS_ALWAYS_ON_TOP";
|
||||||
pub const ASSET_ROOT_ENV: &str = "DIOXUS_ASSET_ROOT";
|
pub const ASSET_ROOT_ENV: &str = "DIOXUS_ASSET_ROOT";
|
||||||
pub const APP_TITLE_ENV: &str = "DIOXUS_APP_TITLE";
|
pub const APP_TITLE_ENV: &str = "DIOXUS_APP_TITLE";
|
||||||
@@ -100,8 +101,16 @@ macro_rules! read_env_config {
|
|||||||
/// For reference, the devserver typically lives on `127.0.0.1:8080` and serves the devserver websocket
|
/// For reference, the devserver typically lives on `127.0.0.1:8080` and serves the devserver websocket
|
||||||
/// on `127.0.0.1:8080/_dioxus`.
|
/// on `127.0.0.1:8080/_dioxus`.
|
||||||
pub fn devserver_raw_addr() -> Option<SocketAddr> {
|
pub fn devserver_raw_addr() -> Option<SocketAddr> {
|
||||||
let addr = std::env::var(DEVSERVER_RAW_ADDR_ENV).ok()?;
|
let ip = std::env::var(DEVSERVER_IP_ENV).ok()?;
|
||||||
addr.parse().ok()
|
let port = std::env::var(DEVSERVER_PORT_ENV).ok()?;
|
||||||
|
|
||||||
|
if cfg!(target_os = "android") {
|
||||||
|
// Since `adb reverse` is used for Android, the 127.0.0.1 will always be
|
||||||
|
// the correct IP address.
|
||||||
|
return Some(format!("127.0.0.1:{}", port).parse().unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
format!("{}:{}", ip, port).parse().ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the address of the devserver for use over a websocket
|
/// Get the address of the devserver for use over a websocket
|
||||||
|
|||||||
@@ -86,8 +86,12 @@ impl AppHandle {
|
|||||||
),
|
),
|
||||||
("RUST_BACKTRACE", "1".to_string()),
|
("RUST_BACKTRACE", "1".to_string()),
|
||||||
(
|
(
|
||||||
dioxus_cli_config::DEVSERVER_RAW_ADDR_ENV,
|
dioxus_cli_config::DEVSERVER_IP_ENV,
|
||||||
devserver_ip.to_string(),
|
devserver_ip.ip().to_string(),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
dioxus_cli_config::DEVSERVER_PORT_ENV,
|
||||||
|
devserver_ip.port().to_string(),
|
||||||
),
|
),
|
||||||
// unset the cargo dirs in the event we're running `dx` locally
|
// unset the cargo dirs in the event we're running `dx` locally
|
||||||
// since the child process will inherit the env vars, we don't want to confuse the downstream process
|
// since the child process will inherit the env vars, we don't want to confuse the downstream process
|
||||||
@@ -145,7 +149,7 @@ impl AppHandle {
|
|||||||
|
|
||||||
// https://developer.android.com/studio/run/emulator-commandline
|
// https://developer.android.com/studio/run/emulator-commandline
|
||||||
Platform::Android => {
|
Platform::Android => {
|
||||||
self.open_android_sim(envs).await;
|
self.open_android_sim(devserver_ip, envs).await;
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -697,13 +701,30 @@ We checked the folder: {}
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn open_android_sim(&self, envs: Vec<(&'static str, String)>) {
|
async fn open_android_sim(
|
||||||
|
&self,
|
||||||
|
devserver_socket: SocketAddr,
|
||||||
|
envs: Vec<(&'static str, String)>,
|
||||||
|
) {
|
||||||
let apk_path = self.app.apk_path();
|
let apk_path = self.app.apk_path();
|
||||||
let session_cache = self.app.build.krate.session_cache_dir();
|
let session_cache = self.app.build.krate.session_cache_dir();
|
||||||
let full_mobile_app_name = self.app.build.krate.full_mobile_app_name();
|
let full_mobile_app_name = self.app.build.krate.full_mobile_app_name();
|
||||||
|
|
||||||
// Start backgrounded since .open() is called while in the arm of the top-level match
|
// Start backgrounded since .open() is called while in the arm of the top-level match
|
||||||
tokio::task::spawn(async move {
|
tokio::task::spawn(async move {
|
||||||
|
let port = devserver_socket.port();
|
||||||
|
if let Err(e) = Command::new("adb")
|
||||||
|
.arg("reverse")
|
||||||
|
.arg(format!("tcp:{}", port))
|
||||||
|
.arg(format!("tcp:{}", port))
|
||||||
|
.stderr(Stdio::piped())
|
||||||
|
.stdout(Stdio::piped())
|
||||||
|
.output()
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
tracing::error!("failed to forward port {port}: {e}");
|
||||||
|
}
|
||||||
|
|
||||||
// Install
|
// Install
|
||||||
// adb install -r app-debug.apk
|
// adb install -r app-debug.apk
|
||||||
if let Err(e) = Command::new(DioxusCrate::android_adb())
|
if let Err(e) = Command::new(DioxusCrate::android_adb())
|
||||||
|
|||||||
@@ -193,6 +193,23 @@ impl WebServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn shutdown(&mut self) {
|
pub(crate) async fn shutdown(&mut self) {
|
||||||
|
if matches!(self.platform, Platform::Android) {
|
||||||
|
use std::process::{Command, Stdio};
|
||||||
|
if let Err(err) = Command::new("adb")
|
||||||
|
.arg("reverse")
|
||||||
|
.arg("--remove")
|
||||||
|
.arg(format!("tcp:{}", self.devserver_port))
|
||||||
|
.stderr(Stdio::piped())
|
||||||
|
.stdout(Stdio::piped())
|
||||||
|
.output()
|
||||||
|
{
|
||||||
|
tracing::error!(
|
||||||
|
"failed to remove forwarded port {}: {err}",
|
||||||
|
self.devserver_port
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self.send_shutdown().await;
|
self.send_shutdown().await;
|
||||||
for socket in self.hot_reload_sockets.drain(..) {
|
for socket in self.hot_reload_sockets.drain(..) {
|
||||||
_ = socket.close().await;
|
_ = socket.close().await;
|
||||||
|
|||||||
@@ -162,14 +162,8 @@ impl LaunchBuilder {
|
|||||||
{
|
{
|
||||||
use dioxus_fullstack::prelude::server_fn::client::{get_server_url, set_server_url};
|
use dioxus_fullstack::prelude::server_fn::client::{get_server_url, set_server_url};
|
||||||
if get_server_url().is_empty() {
|
if get_server_url().is_empty() {
|
||||||
let ip = if cfg!(target_os = "android") {
|
|
||||||
"10.0.2.2"
|
|
||||||
} else {
|
|
||||||
"127.0.0.1"
|
|
||||||
};
|
|
||||||
|
|
||||||
let serverurl = format!(
|
let serverurl = format!(
|
||||||
"http://{ip}:{}",
|
"http://127.0.0.1:{}",
|
||||||
std::env::var("PORT").unwrap_or_else(|_| "8080".to_string())
|
std::env::var("PORT").unwrap_or_else(|_| "8080".to_string())
|
||||||
)
|
)
|
||||||
.leak();
|
.leak();
|
||||||
|
|||||||
Reference in new issue
Block a user