tauri_plugin_android_fs/api/
private_storage.rs

1use crate::*;
2
3
4/// API of file storage intended for the app’s use only.  
5/// 
6/// # Examples
7/// ```
8/// fn example(app: &tauri::AppHandle) {
9///     use tauri_plugin_android_fs::AndroidFsExt as _;
10/// 
11///     let api = app.android_fs();
12///     let private_storage = api.private_storage();
13/// }
14/// ```
15pub struct PrivateStorage<'a, R: tauri::Runtime>(pub(crate) &'a AndroidFs<R>);
16
17impl<'a, R: tauri::Runtime> PrivateStorage<'a, R> {
18
19    /// Get the absolute path of the specified directory.  
20    /// App can fully manage entries within this directory without any permission via std::fs.   
21    ///
22    /// These files will be deleted when the app is uninstalled and may also be deleted at the user’s initialising request.  
23    /// When using [`PrivateDir::Cache`], the system will automatically delete files in this directory as disk space is needed elsewhere on the device.   
24    /// 
25    /// The returned path may change over time if the calling app is moved to an adopted storage device, 
26    /// so only relative paths should be persisted.   
27    /// 
28    /// # Examples
29    /// ```no_run
30    /// use tauri_plugin_android_fs::{AndroidFs, AndroidFsExt, PrivateDir, PrivateStorage};
31    /// 
32    /// fn example(app: tauri::AppHandle) {
33    ///     let api = app.android_fs().private_storage();
34    /// 
35    ///     let dir_path = api.resolve_path(PrivateDir::Data).unwrap();
36    ///     let file_path = dir_path.join("2025-2-12/data.txt");
37    ///     
38    ///     // Write file
39    ///     std::fs::create_dir_all(file_path.parent().unwrap()).unwrap();
40    ///     std::fs::write(&file_path, "aaaa").unwrap();
41    /// 
42    ///     // Read file
43    ///     let _ = std::fs::read_to_string(&file_path).unwrap();
44    /// 
45    ///     // Remove file
46    ///     std::fs::remove_file(&file_path).unwrap();
47    /// }
48    /// ```
49    /// 
50    /// # Support
51    /// All.
52    pub fn resolve_path(&self, dir: PrivateDir) -> crate::Result<std::path::PathBuf> {
53        on_android!({
54            impl_de!(struct Paths { data: String, cache: String });
55        
56            static PATHS: std::sync::OnceLock<Paths> = std::sync::OnceLock::new();
57
58            if PATHS.get().is_none() {
59                let paths = self.0.api
60                    .run_mobile_plugin::<Paths>("getPrivateBaseDirAbsolutePaths", "")?;
61
62                // The cell is guaranteed to contain a value when set returns
63                let _ = PATHS.set(paths);
64            }
65
66            let paths = PATHS.get().unwrap();
67
68            Ok(match dir {
69                PrivateDir::Data => std::path::PathBuf::from(paths.data.to_owned()),
70                PrivateDir::Cache => std::path::PathBuf::from(paths.cache.to_owned()),
71            })
72        })
73    }
74
75    /// Get the absolute path of the specified relative path and base directory.  
76    /// App can fully manage entries of this path without any permission via std::fs.   
77    ///
78    /// See [`PrivateStorage::resolve_path`] for details.  
79    /// 
80    /// # Support
81    /// All.
82    pub fn resolve_path_with(
83        &self,
84        dir: PrivateDir,
85        relative_path: impl AsRef<str>
86    ) -> crate::Result<std::path::PathBuf> {
87
88        on_android!({
89            let relative_path = relative_path.as_ref().trim_start_matches('/');
90            let path = self.resolve_path(dir)?.join(relative_path);
91            Ok(path)
92        })
93    }
94
95    pub fn resolve_uri(&self, dir: PrivateDir) -> crate::Result<FileUri> {
96        on_android!({
97            self.resolve_path(dir).map(Into::into)
98        })
99    }
100
101    pub fn resolve_uri_with(&self, dir: PrivateDir, relative_path: impl AsRef<str>) -> crate::Result<FileUri> {
102        on_android!({
103            self.resolve_path_with(dir, relative_path).map(Into::into)
104        })
105    }
106
107    /// Writes a slice as the entire contents of a file.  
108    /// 
109    /// This function will create a file if it does not exist, and will entirely replace its contents if it does.  
110    /// Recursively create parent directories if they are missing.  
111    /// 
112    /// This internally uses [`PrivateStorage::resolve_path`] , [`std::fs::create_dir_all`], and [`std::fs::write`].  
113    /// See [`PrivateStorage::resolve_path`] for details.  
114    /// 
115    /// # Support
116    /// All.
117    pub fn write(
118        &self, 
119        base_dir: PrivateDir, 
120        relative_path: impl AsRef<str>, 
121        contents: impl AsRef<[u8]>
122    ) -> crate::Result<()> {
123
124        on_android!({
125            let path = self.resolve_path_with(base_dir, relative_path)?;
126
127            if let Some(parent_dir) = path.parent() {
128                std::fs::create_dir_all(parent_dir)?;
129            }
130
131            std::fs::write(path, contents)?;
132            Ok(())
133        })
134    }
135
136    /// Open a file in read-only mode.  
137    /// 
138    /// If you only need to read the entire file contents, consider using [`PrivateStorage::read`]  or [`PrivateStorage::read_to_string`] instead.  
139    /// 
140    /// This internally uses [`PrivateStorage::resolve_path`] and [`std::fs::File::open`].  
141    /// See [`PrivateStorage::resolve_path`] for details.  
142    /// 
143    /// # Support
144    /// All.
145    pub fn open_file(
146        &self,
147        base_dir: PrivateDir, 
148        relative_path: impl AsRef<str>, 
149    ) -> crate::Result<std::fs::File> {
150
151        on_android!({
152            let path = self.resolve_path_with(base_dir, relative_path)?;
153            Ok(std::fs::File::open(path)?)
154        })
155    }
156
157    /// Opens a file in write-only mode.  
158    /// This function will create a file if it does not exist, and will truncate it if it does.
159    /// 
160    /// If you only need to write the contents, consider using [`PrivateStorage::write`]  instead.  
161    /// 
162    /// This internally uses [`PrivateStorage::resolve_path`] and [`std::fs::File::create`].  
163    /// See [`PrivateStorage::resolve_path`] for details.  
164    /// 
165    /// # Support
166    /// All.
167    pub fn create_file(
168        &self,
169        base_dir: PrivateDir, 
170        relative_path: impl AsRef<str>, 
171    ) -> crate::Result<std::fs::File> {
172
173        on_android!({
174            let path = self.resolve_path_with(base_dir, relative_path)?;
175            Ok(std::fs::File::create(path)?)
176        })
177    }
178
179    /// Creates a new file in read-write mode; error if the file exists. 
180    /// 
181    /// This internally uses [`PrivateStorage::resolve_path`] and [`std::fs::File::create_new`].  
182    /// See [`PrivateStorage::resolve_path`] for details.  
183    /// 
184    /// # Support
185    /// All.
186    pub fn create_new_file(
187        &self,
188        base_dir: PrivateDir, 
189        relative_path: impl AsRef<str>, 
190    ) -> crate::Result<std::fs::File> {
191
192        on_android!({
193            let path = self.resolve_path_with(base_dir, relative_path)?;
194            Ok(std::fs::File::create_new(path)?)
195        })
196    }
197
198    /// Reads the entire contents of a file into a bytes vector.  
199    /// 
200    /// If you need [`std::fs::File`], use [`PrivateStorage::open_file`] insted.  
201    /// 
202    /// This internally uses [`PrivateStorage::resolve_path`] and [`std::fs::read`].  
203    /// See [`PrivateStorage::resolve_path`] for details.  
204    /// 
205    /// # Support
206    /// All.
207    pub fn read(
208        &self,
209        base_dir: PrivateDir, 
210        relative_path: impl AsRef<str>, 
211    ) -> crate::Result<Vec<u8>> {
212
213        on_android!({
214            let path = self.resolve_path_with(base_dir, relative_path)?;
215            Ok(std::fs::read(path)?)
216        })
217    }
218
219    /// Reads the entire contents of a file into a string.  
220    /// 
221    /// If you need [`std::fs::File`], use [`PrivateStorage::open_file`] insted.  
222    /// 
223    /// This internally uses [`PrivateStorage::resolve_path`] and [`std::fs::read_to_string`].  
224    /// See [`PrivateStorage::resolve_path`] for details.  
225    /// 
226    /// # Support
227    /// All.
228    pub fn read_to_string(
229        &self,
230        base_dir: PrivateDir,
231        relative_path: impl AsRef<str>, 
232    ) -> crate::Result<String> {
233
234        on_android!({
235            let path = self.resolve_path_with(base_dir, relative_path)?;
236            Ok(std::fs::read_to_string(path)?)
237        })
238    }
239
240    /// Returns an iterator over the entries within a directory.
241    /// 
242    /// This internally uses [`PrivateStorage::resolve_path`] and [`std::fs::read_dir`].  
243    /// See [`PrivateStorage::resolve_path`] for details.  
244    /// 
245    /// # Support
246    /// All.
247    pub fn read_dir(
248        &self,
249        base_dir: PrivateDir,
250        relative_path: Option<&str>,
251    ) -> crate::Result<std::fs::ReadDir> {
252
253        on_android!({
254            let path = match relative_path {
255                Some(relative_path) => self.resolve_path_with(base_dir, relative_path)?,
256                None => self.resolve_path(base_dir)?,
257            };
258    
259            Ok(std::fs::read_dir(path)?)
260        })
261    }
262
263    /// Removes a file from the filesystem.  
264    /// 
265    /// This internally uses [`PrivateStorage::resolve_path`] and [`std::fs::remove_file`].  
266    /// See [`PrivateStorage::resolve_path`] for details.  
267    /// 
268    /// # Support
269    /// All.
270    pub fn remove_file(
271        &self,
272        base_dir: PrivateDir,
273        relative_path: impl AsRef<str>,
274    ) -> crate::Result<()> {
275
276        on_android!({
277            let path = self.resolve_path_with(base_dir, relative_path)?;
278            Ok(std::fs::remove_file(path)?)
279        })
280    }
281
282    /// Removes an empty directory.  
283    /// If you want to remove a directory that is not empty, as well as all of its contents recursively, consider using [`PrivateStorage::remove_dir_all`] instead.  
284    /// 
285    /// This internally uses [`PrivateStorage::resolve_path`] and [`std::fs::remove_dir`].  
286    /// See [`PrivateStorage::resolve_path`] for details.  
287    /// 
288    /// # Support
289    /// All.
290    pub fn remove_dir(
291        &self,
292        base_dir: PrivateDir,
293        relative_path: Option<&str>,
294    ) -> crate::Result<()> {
295
296        on_android!({
297            let path = match relative_path {
298                Some(relative_path) => self.resolve_path_with(base_dir, relative_path)?,
299                None => self.resolve_path(base_dir)?,
300            };
301    
302            std::fs::remove_dir(path)?;
303            Ok(())
304        })
305    }
306
307    /// Removes a directory at this path, after removing all its contents. Use carefully!  
308    /// 
309    /// This internally uses [`PrivateStorage::resolve_path`] and [`std::fs::remove_dir_all`].  
310    /// See [`PrivateStorage::resolve_path`] for details.  
311    /// 
312    /// # Support
313    /// All.
314    pub fn remove_dir_all(
315        &self,
316        base_dir: PrivateDir,
317        relative_path: Option<&str>,
318    ) -> crate::Result<()> {
319
320        on_android!({
321            let path = match relative_path {
322                Some(relative_path) => self.resolve_path_with(base_dir, relative_path)?,
323                None => self.resolve_path(base_dir)?,
324            };
325    
326            std::fs::remove_dir_all(path)?;
327            Ok(())
328        })
329    }
330
331    /// Returns Ok(true) if the path points at an existing entity.  
332    /// 
333    /// This internally uses [`PrivateStorage::resolve_path`] and [`std::fs::exists`].  
334    /// See [`PrivateStorage::resolve_path`] for details.  
335    /// 
336    /// # Support
337    /// All.
338    pub fn exists(
339        &self,
340        base_dir: PrivateDir,
341        relative_path: impl AsRef<str>
342    ) -> crate::Result<bool> {
343
344        on_android!({
345            let path = self.resolve_path_with(base_dir, relative_path)?;
346            Ok(std::fs::exists(path)?)
347        })
348    }
349
350    /// Queries the file system to get information about a file, directory.  
351    /// 
352    /// This internally uses [`PrivateStorage::resolve_path`] and [`std::fs::metadata`].  
353    /// See [`PrivateStorage::resolve_path`] for details.  
354    /// 
355    /// # Support
356    /// All.
357    pub fn metadata(
358        &self,
359        base_dir: PrivateDir,
360        relative_path: Option<&str>,
361    ) -> crate::Result<std::fs::Metadata> {
362
363        on_android!({
364            let path = match relative_path {
365                Some(relative_path) => self.resolve_path_with(base_dir, relative_path)?,
366                None => self.resolve_path(base_dir)?,
367            };
368    
369            Ok(std::fs::metadata(path)?)
370        })
371    }
372}