Skip to main content

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/// use tauri_plugin_android_fs::{AndroidFsExt, PrivateDir};
11/// 
12/// async fn example(app: &tauri::AppHandle) {
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    /// Returns the absolute path of an app-specific directory on the internal storage.
60    ///
61    /// Files and directories in this location can be managed directly using [`std::fs`].
62    ///
63    /// This function only constructs the path and does **not** create the directory.
64    ///
65    /// Since these locations may also contain files created by other Tauri
66    /// plugins or by the WebView runtime, it is recommended to create a uniquely
67    /// named subdirectory for your application.
68    ///
69    /// # Notes
70    /// Files in these locations are removed when the app is uninstalled.
71    /// 
72    /// When using [`PrivateDir::Cache`], the system may automatically delete files
73    /// when additional storage space is needed. 
74    /// Applications should not rely on this behavior and should clear cache files explicitly.
75    /// 
76    /// These directories are inaccessible to other apps under normal circumstances.
77    /// On rooted devices or when the user has elevated privileges,
78    /// their contents may still be accessible.
79    /// 
80    /// The returned path may change if the app is moved to adopted storage.
81    /// Persist only relative paths if the path needs to be stored.
82    /// 
83    /// Each Android user has a separate app-specific directory.
84    /// 
85    /// 
86    /// Get an absolute path of the app-specific directory on the internal storage.  
87    /// App can fully manage entries within this directory via [`std::fs`] and etc.   
88    /// 
89    /// This function does **not** create any directories; it only constructs the path.
90    /// 
91    /// Since these locations may contain files created by other Tauri plugins or webview systems, 
92    /// it is recommended to add a subdirectory with a unique name.
93    ///
94    /// These entries will be deleted when the app is uninstalled and may also be deleted at the user’s initialising request.  
95    /// 
96    /// When using [`PrivateDir::Cache`], the system will automatically delete entries as disk space is needed elsewhere on the device. 
97    /// But you should not rely on this. The cache should be explicitly cleared by yourself.
98    /// 
99    /// The system prevents other apps and user from accessing these locations. 
100    /// In cases where the device is rooted or the user has special permissions, the user may be able to access this.   
101    /// 
102    /// Since the returned paths can change when the app is moved to an [adopted storage](https://source.android.com/docs/core/storage/adoptable), 
103    /// only relative paths should be stored.
104    /// 
105    /// # Note
106    /// This provides a separate area for each user in a multi-user environment.
107    /// 
108    /// # Support
109    /// All Android versions supported by Tauri.
110    #[maybe_async]
111    pub fn resolve_path(
112        &self, 
113        dir: PrivateDir
114    ) -> Result<std::path::PathBuf> {
115
116        #[cfg(not(target_os = "android"))] {
117            Err(Error::NOT_ANDROID)
118        }
119        #[cfg(target_os = "android")] {
120            self.impls().private_dir_path(dir).map(Clone::clone)
121        }
122    }
123
124    /// See [`PrivateStorage::resolve_path`] and [`FileUri::from_path`]
125    #[maybe_async]
126    pub fn resolve_uri(
127        &self, 
128        dir: PrivateDir,
129        relative_path: impl AsRef<std::path::Path>
130    ) -> Result<FsUri> {
131
132        #[cfg(not(target_os = "android"))] {
133            Err(Error::NOT_ANDROID)
134        }
135        #[cfg(target_os = "android")] {
136            let mut path = self.resolve_path(dir).await?;
137            path.push(relative_path.as_ref());
138            Ok(path.into())
139        }
140    }
141}