tauri_plugin_android_fs/api/private_storage.rs
1use sync_async::sync_async;
2use crate::*;
3use super::*;
4
5
6/// API of file storage intended for the app’s use only.
7///
8/// # Examples
9/// ```no_run
10/// async fn example(app: &tauri::AppHandle) {
11/// use tauri_plugin_android_fs::AndroidFsExt as _;
12///
13/// let api = app.android_fs_async();
14/// let ps = api.private_storage();
15///
16/// // Resolve the absolute paths.
17/// // Files and directories in these locations can be fully managed using `std::fs`.
18/// let cache_dir_path: std::path::PathBuf = ps.resolve_path(PrivateDir::Cache).await?;
19/// let data_dir_path: std::path::PathBuf = ps.resolve_path(PrivateDir::Data).await?;
20/// let nobackup_data_dir_path: std::path::PathBuf = ps.resolve_path(PrivateDir::NoBackupData).await?;
21///
22/// // These directories may also contain files created by other Tauri plugins
23/// // or the WebView runtime. To avoid conflicts, it is recommended to use
24/// // a uniquely named subdirectory for your application.
25/// let cache_dir_path = cache_dir_path.join("01K6049FVCD4SAGMAB6X20SA5S");
26/// let data_dir_path = data_dir_path.join("01K6049FVCD4SAGMAB6X20SA5S");
27/// let nobackup_data_dir_path = nobackup_data_dir_path.join("01K6049FVCD4SAGMAB6X20SA5S");
28/// }
29/// ```
30#[sync_async]
31pub struct PrivateStorage<'a, R: tauri::Runtime> {
32 #[cfg(target_os = "android")]
33 pub(crate) handle: &'a tauri::plugin::PluginHandle<R>,
34
35 #[cfg(not(target_os = "android"))]
36 #[allow(unused)]
37 pub(crate) handle: &'a std::marker::PhantomData<fn() -> R>,
38}
39
40#[cfg(target_os = "android")]
41#[sync_async(
42 use(if_sync) impls::SyncImpls as Impls;
43 use(if_async) impls::AsyncImpls as Impls;
44)]
45impl<'a, R: tauri::Runtime> PrivateStorage<'a, R> {
46
47 #[always_sync]
48 fn impls(&self) -> Impls<'_, R> {
49 Impls { handle: &self.handle }
50 }
51}
52
53#[sync_async(
54 use(if_async) api_async::{AndroidFs, Opener, Picker, PublicStorage};
55 use(if_sync) api_sync::{AndroidFs, Opener, Picker, PublicStorage};
56)]
57impl<'a, R: tauri::Runtime> PrivateStorage<'a, R> {
58
59 /// Get an absolute path of the app-specific directory on the internal storage.
60 /// App can fully manage entries within this directory via [`std::fs`] and etc.
61 ///
62 /// This function does **not** create any directories; it only constructs the path.
63 ///
64 /// Since these locations may contain files created by other Tauri plugins or webview systems,
65 /// it is recommended to add a subdirectory with a unique name.
66 ///
67 /// These entries will be deleted when the app is uninstalled and may also be deleted at the user’s initialising request.
68 ///
69 /// When using [`PrivateDir::Cache`], the system will automatically delete entries as disk space is needed elsewhere on the device.
70 /// But you should not rely on this. The cache should be explicitly cleared by yourself.
71 ///
72 /// The system prevents other apps and user from accessing these locations.
73 /// In cases where the device is rooted or the user has special permissions, the user may be able to access this.
74 ///
75 /// Since the returned paths can change when the app is moved to an [adopted storage](https://source.android.com/docs/core/storage/adoptable),
76 /// only relative paths should be stored.
77 ///
78 /// # Note
79 /// This provides a separate area for each user in a multi-user environment.
80 ///
81 /// # Support
82 /// All Android versions supported by Tauri.
83 #[maybe_async]
84 pub fn resolve_path(
85 &self,
86 dir: PrivateDir
87 ) -> Result<std::path::PathBuf> {
88
89 #[cfg(not(target_os = "android"))] {
90 Err(Error::NOT_ANDROID)
91 }
92 #[cfg(target_os = "android")] {
93 self.impls().private_dir_path(dir).map(Clone::clone)
94 }
95 }
96
97 /// See [`PrivateStorage::resolve_path`] and [`FileUri::from_path`]
98 #[maybe_async]
99 pub fn resolve_uri(
100 &self,
101 dir: PrivateDir,
102 relative_path: impl AsRef<std::path::Path>
103 ) -> Result<FsUri> {
104
105 #[cfg(not(target_os = "android"))] {
106 Err(Error::NOT_ANDROID)
107 }
108 #[cfg(target_os = "android")] {
109 let mut path = self.resolve_path(dir).await?;
110 path.push(relative_path.as_ref());
111 Ok(path.into())
112 }
113 }
114}