diff --git a/examples/storage/Cargo.toml b/examples/storage/Cargo.toml index 5fd0a60..fac52e5 100644 --- a/examples/storage/Cargo.toml +++ b/examples/storage/Cargo.toml @@ -14,3 +14,4 @@ web = ["dioxus/web"] desktop = ["dioxus/desktop"] fullstack = ["dioxus/fullstack"] server = ["dioxus/server"] +mobile = ["dioxus/mobile"] diff --git a/packages/storage/Cargo.toml b/packages/storage/Cargo.toml index e9e5b74..3bd1340 100644 --- a/packages/storage/Cargo.toml +++ b/packages/storage/Cargo.toml @@ -32,3 +32,7 @@ directories = "4.0.1" [target.'cfg(target_family = "wasm")'.dependencies] web-sys = { workspace = true, features = ["Window", "Storage", "StorageEvent"] } wasm-bindgen = { workspace = true } + +[target.'cfg(target_os = "android")'.dependencies] +jni = "0.21.1" +ndk-context = "0.1.1" \ No newline at end of file diff --git a/packages/storage/src/client_storage/fs.rs b/packages/storage/src/client_storage/fs.rs index f7fd110..20b4763 100644 --- a/packages/storage/src/client_storage/fs.rs +++ b/packages/storage/src/client_storage/fs.rs @@ -9,6 +9,62 @@ use tokio::sync::watch::{Receiver, channel}; use crate::{StorageBacking, StorageSubscriber, serde_to_string, try_serde_from_string}; +/// Get the default data directory for the current platform. +/// +/// # Example +/// ```rust +/// use dioxus_sdk_storage::{data_directory, set_dir}; +/// +/// // Set the storage directory to a folder named "my_app" in the default data directory. +/// set_dir!(data_directory().join("my_app")); +/// ``` +pub fn data_directory() -> std::path::PathBuf { + #[cfg(target_os = "android")] + { + android_data_directory() + } + + #[cfg(not(target_os = "android"))] + { + directories::BaseDirs::new() + .unwrap() + .data_local_dir() + .to_path_buf() + } +} + +#[cfg(target_os = "android")] +fn android_data_directory() -> std::path::PathBuf { + use jni::JNIEnv; + use jni::objects::{JObject, JString}; + use std::sync::mpsc::channel; + + let (tx, rx) = channel(); + + dioxus::mobile::wry::prelude::dispatch( + move |env: &mut JNIEnv, activity: &JObject, _webview| { + let files_dir = env + .call_method(activity, "getFilesDir", "()Ljava/io/File;", &[]) + .unwrap() + .l() + .unwrap(); + + let abs_path = env + .call_method(files_dir, "getAbsolutePath", "()Ljava/lang/String;", &[]) + .unwrap() + .l() + .unwrap(); + + let abs_path: JString = abs_path.into(); + let abs_path: String = env.get_string(&abs_path).unwrap().into(); + + tx.send(std::path::PathBuf::from(abs_path)).unwrap(); + }, + ); + + rx.recv().unwrap() +} + #[doc(hidden)] /// Sets the directory where the storage files are located. pub fn set_directory(path: std::path::PathBuf) { @@ -17,12 +73,7 @@ pub fn set_directory(path: std::path::PathBuf) { #[doc(hidden)] pub fn set_dir_name(name: &str) { - set_directory( - directories::BaseDirs::new() - .unwrap() - .data_local_dir() - .join(name), - ) + set_directory(data_directory().join(name)) } /// The location where the storage files are located. diff --git a/packages/storage/src/lib.rs b/packages/storage/src/lib.rs index 51020dd..46be68c 100644 --- a/packages/storage/src/lib.rs +++ b/packages/storage/src/lib.rs @@ -51,7 +51,7 @@ use tokio::sync::watch::error::SendError; use tokio::sync::watch::{Receiver, Sender}; #[cfg(not(target_family = "wasm"))] -pub use client_storage::{set_dir_name, set_directory}; +pub use client_storage::{data_directory, set_dir_name, set_directory}; /// A storage hook that can be used to store data that will persist across application reloads. This hook is generic over the storage location which can be useful for other hooks. ///