fix: pass off env vars to android apps (#3621)
* fix: pass off env vars to android apps * move to jni_onload * fix clippy
This commit is contained in:
1 parent
ce2b223af9
commit
03c2d6711d
7 files changed
+65
-10
No files matched your search
Generated
+3
-2
@@ -4029,6 +4029,7 @@ dependencies = [
|
|||||||
name = "dioxus-mobile"
|
name = "dioxus-mobile"
|
||||||
version = "0.6.1"
|
version = "0.6.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"dioxus-cli-config",
|
||||||
"dioxus-desktop",
|
"dioxus-desktop",
|
||||||
"dioxus-lib",
|
"dioxus-lib",
|
||||||
"jni",
|
"jni",
|
||||||
@@ -6291,9 +6292,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hstr"
|
name = "hstr"
|
||||||
version = "0.2.12"
|
version = "0.2.15"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dae404c0c5d4e95d4858876ab02eecd6a196bb8caa42050dfa809938833fc412"
|
checksum = "63d6824358c0fd9a68bb23999ed2ef76c84f79408a26ef7ae53d5f370c94ad36"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hashbrown 0.14.5",
|
"hashbrown 0.14.5",
|
||||||
"new_debug_unreachable",
|
"new_debug_unreachable",
|
||||||
|
|||||||
@@ -100,10 +100,8 @@ 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> {
|
||||||
std::env::var(DEVSERVER_RAW_ADDR_ENV)
|
let addr = std::env::var(DEVSERVER_RAW_ADDR_ENV).ok()?;
|
||||||
.unwrap_or_else(|_| "127.0.0.1:8080".to_string())
|
addr.parse().ok()
|
||||||
.parse()
|
|
||||||
.ok()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the address of the devserver for use over a websocket
|
/// Get the address of the devserver for use over a websocket
|
||||||
@@ -288,5 +286,14 @@ pub fn out_dir() -> Option<PathBuf> {
|
|||||||
///
|
///
|
||||||
/// This is designed with desktop executables in mind.
|
/// This is designed with desktop executables in mind.
|
||||||
pub fn session_cache_dir() -> Option<PathBuf> {
|
pub fn session_cache_dir() -> Option<PathBuf> {
|
||||||
|
if cfg!(target_os = "android") {
|
||||||
|
return Some(android_session_cache_dir());
|
||||||
|
}
|
||||||
|
|
||||||
std::env::var(SESSION_CACHE_DIR).ok().map(PathBuf::from)
|
std::env::var(SESSION_CACHE_DIR).ok().map(PathBuf::from)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// The session cache directory for android
|
||||||
|
pub fn android_session_cache_dir() -> PathBuf {
|
||||||
|
PathBuf::from("/data/local/tmp/dx/")
|
||||||
|
}
|
||||||
@@ -292,8 +292,8 @@ impl AppHandle {
|
|||||||
// If the emulator is android, we need to copy the asset to the device with `adb push asset /data/local/tmp/dx/assets/filename.ext`
|
// If the emulator is android, we need to copy the asset to the device with `adb push asset /data/local/tmp/dx/assets/filename.ext`
|
||||||
if self.app.build.build.platform() == Platform::Android {
|
if self.app.build.build.platform() == Platform::Android {
|
||||||
if let Some(bundled_name) = bundled_name.as_ref() {
|
if let Some(bundled_name) = bundled_name.as_ref() {
|
||||||
let target = format!("/data/local/tmp/dx/{}", bundled_name.display());
|
let target = dioxus_cli_config::android_session_cache_dir().join(bundled_name);
|
||||||
tracing::debug!("Pushing asset to device: {target}");
|
tracing::debug!("Pushing asset to device: {target:?}");
|
||||||
let res = tokio::process::Command::new(DioxusCrate::android_adb())
|
let res = tokio::process::Command::new(DioxusCrate::android_adb())
|
||||||
.arg("push")
|
.arg("push")
|
||||||
.arg(&changed_file)
|
.arg(&changed_file)
|
||||||
@@ -699,6 +699,7 @@ We checked the folder: {}
|
|||||||
|
|
||||||
async fn open_android_sim(&self, envs: Vec<(&'static str, String)>) {
|
async fn open_android_sim(&self, 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 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
|
||||||
@@ -717,6 +718,27 @@ We checked the folder: {}
|
|||||||
tracing::error!("Failed to install apk with `adb`: {e}");
|
tracing::error!("Failed to install apk with `adb`: {e}");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Write the env vars to a .env file in our session cache
|
||||||
|
let env_file = session_cache.join(".env");
|
||||||
|
let contents: String = envs
|
||||||
|
.iter()
|
||||||
|
.map(|(key, value)| format!("{key}={value}"))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join("\n");
|
||||||
|
_ = std::fs::write(&env_file, contents);
|
||||||
|
|
||||||
|
// Push the env file to the device
|
||||||
|
if let Err(e) = tokio::process::Command::new(DioxusCrate::android_adb())
|
||||||
|
.arg("push")
|
||||||
|
.arg(env_file)
|
||||||
|
.arg(dioxus_cli_config::android_session_cache_dir().join(".env"))
|
||||||
|
.output()
|
||||||
|
.await
|
||||||
|
.context("Failed to push asset to device")
|
||||||
|
{
|
||||||
|
tracing::error!("Failed to push .env file to device: {e}");
|
||||||
|
}
|
||||||
|
|
||||||
// eventually, use the user's MainAcitivty, not our MainAcitivty
|
// eventually, use the user's MainAcitivty, not our MainAcitivty
|
||||||
// adb shell am start -n dev.dioxus.main/dev.dioxus.main.MainActivity
|
// adb shell am start -n dev.dioxus.main/dev.dioxus.main.MainActivity
|
||||||
let activity_name = format!("{}/dev.dioxus.main.MainActivity", full_mobile_app_name,);
|
let activity_name = format!("{}/dev.dioxus.main.MainActivity", full_mobile_app_name,);
|
||||||
@@ -727,7 +749,6 @@ We checked the folder: {}
|
|||||||
.arg("start")
|
.arg("start")
|
||||||
.arg("-n")
|
.arg("-n")
|
||||||
.arg(activity_name)
|
.arg(activity_name)
|
||||||
.envs(envs)
|
|
||||||
.stderr(Stdio::piped())
|
.stderr(Stdio::piped())
|
||||||
.stdout(Stdio::piped())
|
.stdout(Stdio::piped())
|
||||||
.output()
|
.output()
|
||||||
|
|||||||
@@ -355,6 +355,9 @@ impl WebServer {
|
|||||||
pub fn displayed_address(&self) -> Option<SocketAddr> {
|
pub fn displayed_address(&self) -> Option<SocketAddr> {
|
||||||
let mut address = self.server_address()?;
|
let mut address = self.server_address()?;
|
||||||
|
|
||||||
|
// Set the port to the devserver port since that's usually what people expect
|
||||||
|
address.set_port(self.devserver_port);
|
||||||
|
|
||||||
if self.devserver_bind_ip == IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)) {
|
if self.devserver_bind_ip == IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)) {
|
||||||
address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), address.port());
|
address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), address.port());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -282,7 +282,7 @@ pub(crate) fn to_java_load_asset(filepath: &str) -> Option<Vec<u8>> {
|
|||||||
// in debug mode, the asset might be under `/data/local/tmp/dx/` - attempt to read it from there if it exists
|
// in debug mode, the asset might be under `/data/local/tmp/dx/` - attempt to read it from there if it exists
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
{
|
{
|
||||||
let path = std::path::PathBuf::from("/data/local/tmp/dx/").join(normalized);
|
let path = dioxus_cli_config::android_session_cache_dir().join(normalized);
|
||||||
if path.exists() {
|
if path.exists() {
|
||||||
return std::fs::read(path).ok();
|
return std::fs::read(path).ok();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ license = "MIT OR Apache-2.0"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
dioxus-desktop = { workspace = true }
|
dioxus-desktop = { workspace = true }
|
||||||
dioxus-lib = { workspace = true }
|
dioxus-lib = { workspace = true }
|
||||||
|
dioxus-cli-config = { workspace = true }
|
||||||
libc = "0.2.159"
|
libc = "0.2.159"
|
||||||
once_cell.workspace = true
|
once_cell.workspace = true
|
||||||
|
|
||||||
|
|||||||
@@ -128,9 +128,31 @@ pub extern "C" fn JNI_OnLoad(
|
|||||||
panic!("Failed to find main symbol");
|
panic!("Failed to find main symbol");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set the env vars that rust code might expect, passed off to us by the android app
|
||||||
|
// Doing this before main emulates the behavior of a regular executable
|
||||||
|
if cfg!(target_os = "android") && cfg!(debug_assertions) {
|
||||||
|
load_env_file_from_session_cache();
|
||||||
|
}
|
||||||
|
|
||||||
let main_fn: extern "C" fn() = std::mem::transmute(main_fn_ptr);
|
let main_fn: extern "C" fn() = std::mem::transmute(main_fn_ptr);
|
||||||
main_fn();
|
main_fn();
|
||||||
};
|
};
|
||||||
|
|
||||||
jni::sys::JNI_VERSION_1_6
|
jni::sys::JNI_VERSION_1_6
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Load the env file from the session cache if we're in debug mode and on android
|
||||||
|
///
|
||||||
|
/// This is a slightly hacky way of being able to use std::env::var code in android apps without
|
||||||
|
/// going through their custom java-based system.
|
||||||
|
#[cfg(target_os = "android")]
|
||||||
|
fn load_env_file_from_session_cache() {
|
||||||
|
let env_file = dioxus_cli_config::android_session_cache_dir().join(".env");
|
||||||
|
if let Some(env_file) = std::fs::read_to_string(&env_file).ok() {
|
||||||
|
for line in env_file.lines() {
|
||||||
|
if let Some((key, value)) = line.trim().split_once('=') {
|
||||||
|
std::env::set_var(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user