tauri_plugin_android_fs/lib.rs
1//! # Overview
2//!
3//! The Android file system is strict and complex because its behavior and the available APIs vary depending on the version.
4//! This plugin was created to provide explicit and consistent file operations.
5//! No special permission or configuration is required.
6//!
7//! # Setup
8//! All you need to do is register the core plugin with Tauri:
9//!
10//! `src-tauri/src/lib.rs`
11//!
12//! ```no_run
13//! #[cfg_attr(mobile, tauri::mobile_entry_point)]
14//! pub fn run() {
15//! tauri::Builder::default()
16//! .plugin(tauri_plugin_android_fs::init()) // This
17//! .run(tauri::generate_context!())
18//! .expect("error while running tauri application");
19//! }
20//! ```
21//!
22//! # Usage
23//! There are three main ways to manipulate files:
24//!
25//! ### 1. Dialog
26//! Opens the file picker to read and write user-selected files.
27//!
28//! ```no_run
29//! use tauri_plugin_android_fs::{AndroidFs, AndroidFsExt, VisualMediaTarget};
30//!
31//! fn read_files(app: tauri::AppHandle) {
32//! let api = app.android_fs();
33//! let selected_paths = api.show_open_file_dialog(&["*/*"], true).unwrap();
34//!
35//! if selected_paths.is_empty() {
36//! // Handle cancellation
37//! }
38//! else {
39//! for path in selected_paths {
40//! let file_name = api.get_file_name(&path).unwrap();
41//! let file: std::fs::File = api.open_file(&path).unwrap();
42//! }
43//! }
44//! }
45//!
46//! fn write_file(app: tauri::AppHandle) {
47//! let api = app.android_fs();
48//! let selected_path = api.show_save_file_dialog("fileName", Some("image/png")).unwrap();
49//!
50//! if let Some(path) = selected_path {
51//! let mut file: std::fs::File = api.open_file_writable(&path).unwrap();
52//! }
53//! else {
54//! // Handle cancellation
55//! }
56//! }
57//! ```
58//!
59//! ### 2. Public Storage
60//! File storage intended to be shared with other apps and user.
61//!
62//! ```no_run
63//! use tauri_plugin_android_fs::{AndroidFs, AndroidFsExt, PublicImageDir, PublicStorage};
64//!
65//! fn example(app: tauri::AppHandle) {
66//! let api = app.android_fs().public_storage();
67//! let contents: Vec<u8> = todo!();
68//!
69//! api.write_image(
70//! PublicImageDir::Pictures,
71//! "myApp/2025-02-13.png",
72//! Some("image/png"),
73//! &contents
74//! ).unwrap();
75//! }
76//! ```
77//!
78//! ### 3. Private Storage
79//! File storage intended for the app’s use only.
80//!
81//! ```no_run
82//! use tauri_plugin_android_fs::{AndroidFs, AndroidFsExt, PrivateDir, PrivateStorage};
83//!
84//! fn example(app: tauri::AppHandle) {
85//! let api = app.android_fs().private_storage();
86//!
87//! // Write data
88//! api.write(PrivateDir::Data, "config/data1.txt", "data").unwrap();
89//!
90//! // Read data
91//! let data = api.read_to_string(PrivateDir::Data, "config/data1.txt").unwrap();
92//! assert_eq!(data, "data");
93//! }
94//! ```
95//!
96//! # License
97//! MIT OR Apache-2.0
98
99mod models;
100mod impls;
101mod error;
102
103use std::io::{Read, Write};
104
105pub use models::*;
106pub use error::{Error, Result, PathError};
107pub use impls::{AndroidFsExt, init};
108pub use tauri_plugin_fs::FilePath;
109
110
111/// API
112pub trait AndroidFs {
113
114 /// Verify whether this plugin is available.
115 ///
116 /// On Android, this returns true.
117 /// On other platforms, this returns false.
118 fn is_available(&self) -> bool {
119 #[cfg(not(target_os = "android"))] {
120 false
121 }
122 #[cfg(target_os = "android")] {
123 true
124 }
125 }
126
127 /// Get the file name.
128 ///
129 /// `FilePath` can be obtained from functions such as `AndroidFs::show_open_file_dialog`, `AndroidFs::show_open_visual_media_dialog`, or `AndroidFs::show_save_file_dialog`.
130 ///
131 /// # Support
132 /// All Android version.
133 fn get_file_name(&self, path: &FilePath) -> crate::Result<String>;
134
135 /// Get the mime type.
136 /// If the type is unknown, this returns None.
137 ///
138 /// `FilePath` can be obtained from functions such as `AndroidFs::show_open_file_dialog`, `AndroidFs::show_open_visual_media_dialog`, or `AndroidFs::show_save_file_dialog`.
139 ///
140 /// # Support
141 /// All Android version.
142 fn get_mime_type(&self, path: &FilePath) -> crate::Result<Option<String>>;
143
144 /// Open a file in read-only mode.
145 ///
146 /// If you only need to read the entire file contents, consider using `AndroidFs::read` or `AndroidFs::read_to_string` instead.
147 ///
148 /// `FilePath` can be obtained from functions such as `AndroidFs::show_open_file_dialog` or `AndroidFs::show_open_visual_media_dialog`.
149 ///
150 /// # Support
151 /// All Android version.
152 fn open_file(&self, path: &FilePath) -> crate::Result<std::fs::File>;
153
154 /// Open a file in writable mode from ***writable*** `FilePath`.
155 ///
156 /// If you only need to write the contents, consider using `AndroidFs::write` instead.
157 ///
158 /// # Note
159 /// A **writable** `FilePath` can be obtained from `AndroidFs::show_save_file_dialog`,
160 /// but not from `AndroidFs::show_open_file_dialog` or `AndroidFs::show_open_visual_media_dialog`.
161 ///
162 /// # Support
163 /// All Android version.
164 fn open_file_writable(&self, path: &FilePath) -> crate::Result<std::fs::File>;
165
166 /// Reads the entire contents of a file into a bytes vector.
167 ///
168 /// If you need to operate on a readable file, use `AndroidFs::open_file` instead.
169 ///
170 /// `FilePath` can be obtained from functions such as `AndroidFs::show_open_file_dialog` or `AndroidFs::show_open_visual_media_dialog`.
171 ///
172 /// # Support
173 /// All Android version.
174 fn read(&self, path: &FilePath) -> crate::Result<Vec<u8>> {
175 let mut file = self.open_file(path)?;
176 let mut buf = file.metadata().ok()
177 .map(|m| m.len() as usize)
178 .map(Vec::with_capacity)
179 .unwrap_or_else(Vec::new);
180
181 file.read_to_end(&mut buf)?;
182 Ok(buf)
183 }
184
185 /// Reads the entire contents of a file into a string.
186 ///
187 /// If you need to operate on a readable file, use `AndroidFs::open_file` instead.
188 ///
189 /// `FilePath` can be obtained from functions such as `AndroidFs::show_open_file_dialog` or `AndroidFs::show_open_visual_media_dialog`.
190 ///
191 /// # Support
192 /// All Android version.
193 fn read_to_string(&self, path: &FilePath) -> crate::Result<String> {
194 let mut file = self.open_file(path)?;
195 let mut buf = file.metadata().ok()
196 .map(|m| m.len() as usize)
197 .map(String::with_capacity)
198 .unwrap_or_else(String::new);
199
200 file.read_to_string(&mut buf)?;
201 Ok(buf)
202 }
203
204 /// Writes a slice as the entire contents of a file in a **writable** `FilePath`
205 ///
206 /// If you need to operate on a writable file, use `AndroidFs::open_file_writable` instead.
207 ///
208 /// # Note
209 /// A **writable** `FilePath` can be obtained from `AndroidFs::show_save_file_dialog`,
210 /// but not from `AndroidFs::show_open_file_dialog` or `AndroidFs::show_visual_media_dialog`.
211 ///
212 /// # Support
213 /// All Android version.
214 fn write(&self, path: &FilePath, contetns: impl AsRef<[u8]>) -> crate::Result<()> {
215 let mut file = self.open_file_writable(path)?;
216 file.write_all(contetns.as_ref())?;
217 Ok(())
218 }
219
220 /// Open a dialog for file selection.
221 /// This returns a **readonly** `FilePath` vec. If no file is selected or canceled by user, it is an empty vec.
222 ///
223 /// For images and videos, consider using `AndroidFs::show_open_visiual_media_dialog` instead.
224 ///
225 /// # Note
226 /// `mime_types` represents the types of files that should be selected.
227 /// However, there is no guarantee that the returned file will match the specified types.
228 /// If this is empty, all file types will be available for selection.
229 /// This is equivalent to `["*/*"]`, and it will invoke the standard file picker in most cases.
230 ///
231 /// # Support
232 /// All Android version.
233 fn show_open_file_dialog(
234 &self,
235 mime_types: &[&str],
236 multiple: bool
237 ) -> crate::Result<Vec<FilePath>>;
238
239 /// Opens a dialog for media file selection, such as images and videos.
240 /// This returns a **readonly** `FilePath` vec. If no file is selected or canceled by user, it is an empty vec.
241 ///
242 /// This is more user-friendly than `AndroidFs::show_open_file_dialog`.
243 ///
244 /// # Note
245 /// The file obtained from this function cannot retrieve the correct file name using `AndroidFs::get_file_name`.
246 /// Instead, it will be assigned a sequential number, such as 1000091523.png.
247 /// <https://issuetracker.google.com/issues/268079113>
248 ///
249 /// # Support
250 /// This is available on devices that meet the following criteria:
251 /// - Run Android 11 (API level 30) or higher
252 /// - Receive changes to Modular System Components through Google System Updates
253 ///
254 /// Availability on a given device can be verified by calling `is_visual_media_dialog_available`.
255 /// If not supported, this functions the same as `AndroidFs::show_open_file_dialog`.
256 fn show_open_visual_media_dialog(
257 &self,
258 target: VisualMediaTarget,
259 multiple: bool
260 ) -> crate::Result<Vec<FilePath>>;
261
262 /// Open a dialog for file saving, and write contents to the selected file, then return that path.
263 /// This returns a **writable** `FilePath` . If canceled by the user, return None, and do not write it.
264 ///
265 /// When storing media files such as images, videos, and audio, consider using `PublicStorage::write_image` or a similar method.
266 /// When a file does not need to be accessed by other applications and users, consider using `PrivateStorage::write`.
267 /// These are easier because the destination does not need to be selected in a dialog.
268 ///
269 /// If you want to operate directly on writable files, use `AndroidFs::show_save_file_dialog` then `AndroidFs::open_file_writable` insted.
270 ///
271 /// # Note
272 /// `mime_type` specify the type of the target file to be saved.
273 /// It should be provided whenever possible. If not specified, `application/octet-stream` is used, as generic, unknown, or undefined file types.
274 ///
275 /// # Support
276 /// All Android version.
277 fn show_save_file_dialog_with_contents(
278 &self,
279 default_file_name: impl AsRef<str>,
280 mime_type: Option<&str>,
281 contents: impl AsRef<[u8]>,
282 ) -> crate::Result<Option<FilePath>> {
283
284 if let Some(path) = self.show_save_file_dialog(default_file_name, mime_type)? {
285 self.write(&path, contents)?;
286 return Ok(Some(path))
287 }
288
289 Ok(None)
290 }
291
292 /// Open a dialog for file saving, and return the selected path.
293 /// This returns a **writable** `FilePath` . If canceled by the user, return None.
294 ///
295 /// When storing media files such as images, videos, and audio, consider using `PublicStorage::write_image` or a similar method.
296 /// When a file does not need to be accessed by other applications and users, consider using `PrivateStorage::write`.
297 /// These are easier because the destination does not need to be selected in a dialog.
298 ///
299 /// If you only need to write contents, use `AndroidFs::show_save_file_dialog_with_contents` instead.
300 ///
301 /// # Note
302 /// `mime_type` specify the type of the target file to be saved.
303 /// It should be provided whenever possible. If not specified, `application/octet-stream` is used, as generic, unknown, or undefined file types.
304 ///
305 /// # Support
306 /// All Android version.
307 fn show_save_file_dialog(
308 &self,
309 default_file_name: impl AsRef<str>,
310 mime_type: Option<&str>,
311 ) -> crate::Result<Option<FilePath>>;
312
313 /// Verify whether `AndroidFs::show_open_visual_media_dialog` is available on a given device.
314 ///
315 /// # Support
316 /// All Android version.
317 fn is_visual_media_dialog_available(&self) -> crate::Result<bool>;
318
319 /// File storage API intended to be shared with other apps.
320 fn public_storage(&self) -> &impl PublicStorage;
321
322 /// File storage API intended to be shared with other apps.
323 #[deprecated(note = "This is typo. Use `public_storage` instead.")]
324 #[warn(deprecated)]
325 fn pubic_storage(&self) -> &impl PublicStorage;
326
327 /// File storage API intended for the app’s use only.
328 fn private_storage(&self) -> &impl PrivateStorage;
329}
330
331/// File storage API intended to be shared with other apps.
332pub trait PublicStorage {
333
334 /// Save the contents to public storage.
335 /// This is used when saving a file for access by other applications and user.
336 ///
337 /// When storing media files such as images, videos, and audio, consider using `PublicStorage::write_image` or a similar method.
338 /// For saving a general-purpose file, it is often better to use `AndroidFs::open_save_file_dialog`.
339 ///
340 /// If the same file name already exists, a sequential number is added to the name and saved.
341 ///
342 /// If you want to operate directly on writable files, use `PublicStorage::write_with_contents_writer` insted.
343 ///
344 /// # Note
345 /// Do not save files directly in the base directory.
346 /// Please specify a subdirectory in the `relative_path_with_sub_dir`, such as `appName/file.txt` or `appName/2025-2-11/file.txt`.
347 /// Do not use `file.txt`.
348 ///
349 /// # Support
350 /// All Android version.
351 fn write(
352 &self,
353 base_dir: PublicGeneralPurposeDir,
354 relative_path_with_sub_dir: impl AsRef<str>,
355 mime_type: Option<&str>,
356 contents: impl AsRef<[u8]>,
357 ) -> crate::Result<FilePath> {
358
359 self.write_with_contents_writer(
360 base_dir,
361 relative_path_with_sub_dir,
362 mime_type,
363 |file| file.write_all(contents.as_ref())
364 )
365 }
366
367 /// Save the contents as an image file to public storage.
368 /// This is used when saving a file for access by other applications and user.
369 ///
370 /// If the same file name already exists, a sequential number is added to the name and saved.
371 ///
372 /// If you want to operate directly on writable files, use `PublicStorage::write_image_with_contents_writer` insted.
373 ///
374 /// # Note
375 /// Do not set a non-image type to `mime_type`, as it may result in an error.
376 /// Even if the type is an image, if the Android system does not recognize it as such, an error will occur.
377 ///
378 /// Do not save files directly in the base directory.
379 /// Please specify a subdirectory in the `relative_path_with_sub_dir`, such as `appName/file.png` or `appName/2025-2-11/file.png`.
380 /// Do not use `file.png`.
381 ///
382 /// # Support
383 /// All Android version.
384 fn write_image(
385 &self,
386 base_dir: PublicImageDir,
387 relative_path_with_sub_dir: impl AsRef<str>,
388 mime_type: Option<&str>,
389 contents: impl AsRef<[u8]>,
390 ) -> crate::Result<FilePath> {
391
392 self.write_image_with_contents_writer(
393 base_dir,
394 relative_path_with_sub_dir,
395 mime_type,
396 |file| file.write_all(contents.as_ref())
397 )
398 }
399
400 /// Save the contents as an video file to public storage.
401 /// This is used when saving a file for access by other applications and user.
402 ///
403 /// If the same file name already exists, a sequential number is added to the name and saved.
404 ///
405 /// If you want to operate directly on writable files, use `PublicStorage::write_video_with_contents_writer` insted.
406 ///
407 /// # Note
408 /// Do not set a non-video type to `mime_type`, as it may result in an error.
409 /// Even if the type is an video, if the Android system does not recognize it as such, an error will occur.
410 ///
411 /// Do not save files directly in the base directory.
412 /// Please specify a subdirectory in the `relative_path_with_sub_dir, such as `appName/file.mp4` or `appName/2025-2-11/file.mp4`.
413 /// Do not use `file.mp4`.
414 ///
415 /// # Support
416 /// All Android version.
417 fn write_video(
418 &self,
419 base_dir: PublicVideoDir,
420 relative_path_with_sub_dir: impl AsRef<str>,
421 mime_type: Option<&str>,
422 contents: impl AsRef<[u8]>,
423 ) -> crate::Result<FilePath> {
424
425 self.write_video_with_contents_writer(
426 base_dir,
427 relative_path_with_sub_dir,
428 mime_type,
429 |file| file.write_all(contents.as_ref())
430 )
431 }
432
433 /// Save the contents as an audio file to public storage.
434 /// This is used when saving a file for access by other applications and user.
435 ///
436 /// If the same file name already exists, a sequential number is added to the name and saved.
437 ///
438 /// If you want to operate directly on writable files, use `PublicStorage::write_audio_with_contents_writer` insted.
439 ///
440 /// # Note
441 /// Do not set a non-audio type to `mime_type`, as it may result in an error.
442 /// Even if the type is an audio, if the Android system does not recognize it as such, an error will occur.
443 ///
444 /// Do not save files directly in the base directory.
445 /// Please specify a subdirectory in the `relative_path_with_sub_dir`, such as `appName/file.mp3` or `appName/2025-2-11/file.mp3`.
446 /// Do not use `file.mp3`.
447 ///
448 /// # Support
449 /// `PublicAudioDir::Audiobooks` is not available on Android 9 (API level 28) and lower.
450 /// Availability on a given device can be verified by calling `PublicStorage::is_audiobooks_dir_available`.
451 ///
452 /// `PublicAudioDir::Recordings` is not available on Android 11 (API level 30) and lower.
453 /// Availability on a given device can be verified by calling `PublicStorage::is_recordings_dir_available`.
454 ///
455 /// Others are available in all Android versions.
456 fn write_audio(
457 &self,
458 base_dir: PublicAudioDir,
459 relative_path_with_sub_dir: impl AsRef<str>,
460 mime_type: Option<&str>,
461 contents: impl AsRef<[u8]>,
462 ) -> crate::Result<FilePath> {
463
464 self.write_audio_with_contents_writer(
465 base_dir,
466 relative_path_with_sub_dir,
467 mime_type,
468 |file| file.write_all(contents.as_ref())
469 )
470 }
471
472 /// See ``PublicStorage::write`` for description.
473 ///
474 /// The following is equivalent to `PublicStorage::write`.
475 /// ```ignore
476 /// self.write_with_contents_writer(
477 /// base_dir,
478 /// relative_path_with_sub_dir,
479 /// mime_type,
480 /// |file| file.write_all(contents)
481 /// )
482 /// ```
483 fn write_with_contents_writer(
484 &self,
485 base_dir: PublicGeneralPurposeDir,
486 relative_path_with_sub_dir: impl AsRef<str>,
487 mime_type: Option<&str>,
488 contents_writer: impl FnOnce(&mut std::fs::File) -> std::io::Result<()>
489 ) -> crate::Result<FilePath>;
490
491 /// See ``PublicStorage::write_image`` for description.
492 ///
493 /// The following is equivalent to `PublicStorage::write_image`.
494 /// ```ignore
495 /// self.write_image_with_contents_writer(
496 /// base_dir,
497 /// relative_path_with_sub_dir,
498 /// mime_type,
499 /// |file| file.write_all(contents)
500 /// )
501 /// ```
502 fn write_image_with_contents_writer(
503 &self,
504 base_dir: PublicImageDir,
505 relative_path_with_sub_dir: impl AsRef<str>,
506 mime_type: Option<&str>,
507 contents_writer: impl FnOnce(&mut std::fs::File) -> std::io::Result<()>
508 ) -> crate::Result<FilePath>;
509
510 /// See ``PublicStorage::write_video`` for description.
511 ///
512 /// The following is equivalent to `PublicStorage::write_video`.
513 /// ```ignore
514 /// self.write_video_with_contents_writer(
515 /// base_dir,
516 /// relative_path_with_sub_dir,
517 /// mime_type,
518 /// |file| file.write_all(contents)
519 /// )
520 /// ```
521 fn write_video_with_contents_writer(
522 &self,
523 base_dir: PublicVideoDir,
524 relative_path_with_sub_dir: impl AsRef<str>,
525 mime_type: Option<&str>,
526 contents_writer: impl FnOnce(&mut std::fs::File) -> std::io::Result<()>
527 ) -> crate::Result<FilePath>;
528
529 /// See ``PublicStorage::write_audio`` for description.
530 ///
531 /// The following is equivalent to `PublicStorage::write_audio`.
532 /// ```ignore
533 /// self.write_audio_with_contents_writer(
534 /// base_dir,
535 /// relative_path_with_sub_dir,
536 /// mime_type,
537 /// |file| file.write_all(contents)
538 /// )
539 /// ```
540 fn write_audio_with_contents_writer(
541 &self,
542 base_dir: PublicAudioDir,
543 relative_path_with_sub_dir: impl AsRef<str>,
544 mime_type: Option<&str>,
545 contents_writer: impl FnOnce(&mut std::fs::File) -> std::io::Result<()>
546 ) -> crate::Result<FilePath>;
547
548 /// Verify whether `PublicAudioDir::Audiobooks` is available on a given device.
549 ///
550 /// # Support
551 /// All Android version.
552 fn is_audiobooks_dir_available(&self) -> crate::Result<bool>;
553
554 /// Verify whether `PublicAudioDir::Recordings` is available on a given device.
555 ///
556 /// # Support
557 /// All Android version.
558 fn is_recordings_dir_available(&self) -> crate::Result<bool>;
559}
560
561/// File storage API intended for the app’s use only.
562pub trait PrivateStorage {
563
564 /// Get the absolute path of the specified directory.
565 /// Apps require no extra permissions to read or write to the returned path, since this path lives in their private storage.
566 ///
567 /// These files will be deleted when the app is uninstalled, and may also be deleted by the user.
568 /// When using `PrivateDir::Cache`, the system will automatically delete files in this directory as disk space is needed elsewhere on the device.
569 ///
570 /// The returned path may change over time if the calling app is moved to an adopted storage device, so only relative paths should be persisted.
571 ///
572 /// # Examples
573 /// ```no_run
574 /// use tauri_plugin_android_fs::{AndroidFs, AndroidFsExt, PrivateDir, PrivateStorage};
575 ///
576 /// fn example(app: tauri::AppHandle) {
577 /// let api = app.android_fs().private_storage();
578 ///
579 /// let dir_path = api.resolve_path(PrivateDir::Data).unwrap();
580 /// let file_path = dir_path.join("2025-2-12/data.txt");
581 ///
582 /// // Write file
583 /// std::fs::create_dir_all(file_path.parent().unwrap()).unwrap();
584 /// std::fs::write(&file_path, "aaaa").unwrap();
585 ///
586 /// // Read file
587 /// let _ = std::fs::read_to_string(&file_path).unwrap();
588 ///
589 /// // Remove file
590 /// std::fs::remove_file(&file_path).unwrap();
591 ///
592 /// // Remove all files in the dir.
593 /// std::fs::remove_dir_all(&dir_path).unwrap();
594 /// }
595 /// ```
596 ///
597 /// # Support
598 /// All Android version.
599 fn resolve_path(&self, dir: PrivateDir) -> crate::Result<std::path::PathBuf>;
600
601 /// Get the absolute path of the specified relative path and base directory.
602 /// Apps require no extra permissions to read or write to the returned path, since this path lives in their private storage.
603 ///
604 /// See `PrivateStorage::resolve_path` for details.
605 ///
606 /// # Support
607 /// All Android version.
608 fn resolve_path_with(
609 &self,
610 base_dir: PrivateDir,
611 relative_path: impl AsRef<str>
612 ) -> crate::Result<std::path::PathBuf> {
613
614 let relative_path = relative_path.as_ref().trim_start_matches('/');
615 let path = self.resolve_path(base_dir)?.join(relative_path);
616 Ok(path)
617 }
618
619 /// Writes a slice as the entire contents of a file.
620 ///
621 /// This function will create a file if it does not exist, and will entirely replace its contents if it does.
622 /// Recursively create parent directories if they are missing.
623 ///
624 /// This internally uses `PrivateStorage::resolve_path` , `std::fs::create_dir_all` , and `std::fs::write`.
625 /// See `PrivateStorage::resolve_path` for details.
626 ///
627 /// # Support
628 /// All Android version.
629 fn write(
630 &self,
631 base_dir: PrivateDir,
632 relative_path: impl AsRef<str>,
633 contents: impl AsRef<[u8]>
634 ) -> crate::Result<()> {
635
636 let path = self.resolve_path_with(base_dir, relative_path)?;
637
638 if let Some(parent_dir) = path.parent() {
639 std::fs::create_dir_all(parent_dir)?;
640 }
641
642 std::fs::write(path, contents)?;
643
644 Ok(())
645 }
646
647 /// Open a file in read-only mode.
648 ///
649 /// If you only need to read the entire file contents, consider using `PrivateStorage::read` or `PrivateStorage::read_to_string` instead.
650 ///
651 /// This internally uses `PrivateStorage::resolve_path` and `std::fs::File::open`.
652 /// See `PrivateStorage::resolve_path` for details.
653 ///
654 /// # Support
655 /// All Android version.
656 fn open_file(
657 &self,
658 base_dir: PrivateDir,
659 relative_path: impl AsRef<str>,
660 ) -> crate::Result<std::fs::File> {
661
662 let path = self.resolve_path_with(base_dir, relative_path)?;
663 Ok(std::fs::File::open(path)?)
664 }
665
666 /// Reads the entire contents of a file into a bytes vector.
667 ///
668 /// If you need `std::fs::File`, use ``PrivateStorage::open_file`` insted.
669 ///
670 /// This internally uses `PrivateStorage::resolve_path` and `std::fs::read`.
671 /// See `PrivateStorage::resolve_path` for details.
672 ///
673 /// # Support
674 /// All Android version.
675 fn read(
676 &self,
677 base_dir: PrivateDir,
678 relative_path: impl AsRef<str>,
679 ) -> crate::Result<Vec<u8>> {
680
681 let path = self.resolve_path_with(base_dir, relative_path)?;
682 Ok(std::fs::read(path)?)
683 }
684
685 /// Reads the entire contents of a file into a string.
686 ///
687 /// If you need `std::fs::File`, use ``PrivateStorage::open_file`` insted.
688 ///
689 /// This internally uses `PrivateStorage::resolve_path` and `std::fs::read_to_string`.
690 /// See `PrivateStorage::resolve_path` for details.
691 ///
692 /// # Support
693 /// All Android version.
694 fn read_to_string(
695 &self,
696 base_dir: PrivateDir,
697 relative_path: impl AsRef<str>,
698 ) -> crate::Result<String> {
699
700 let path = self.resolve_path_with(base_dir, relative_path)?;
701 Ok(std::fs::read_to_string(path)?)
702 }
703
704 /// Returns an iterator over the entries within a directory.
705 ///
706 /// This internally uses `PrivateStorage::resolve_path` and `std::fs::read_dir`.
707 /// See `PrivateStorage::resolve_path` for details.
708 ///
709 /// # Support
710 /// All Android version.
711 fn read_dir(
712 &self,
713 base_dir: PrivateDir,
714 relative_path: Option<&str>,
715 ) -> crate::Result<std::fs::ReadDir> {
716
717 let path = match relative_path {
718 Some(relative_path) => self.resolve_path_with(base_dir, relative_path)?,
719 None => self.resolve_path(base_dir)?,
720 };
721
722 Ok(std::fs::read_dir(path)?)
723 }
724
725 /// Removes a file from the filesystem.
726 ///
727 /// This internally uses `PrivateStorage::resolve_path` and `std::fs::remove_file`.
728 /// See `PrivateStorage::resolve_path` for details.
729 ///
730 /// # Support
731 /// All Android version.
732 fn remove_file(
733 &self,
734 base_dir: PrivateDir,
735 relative_path: impl AsRef<str>,
736 ) -> crate::Result<()> {
737
738 let path = self.resolve_path_with(base_dir, relative_path)?;
739 Ok(std::fs::remove_file(path)?)
740 }
741
742 /// Removes an empty directory.
743 /// 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.
744 ///
745 /// This internally uses `PrivateStorage::resolve_path` and `std::fs::remove_dir`.
746 /// See `PrivateStorage::resolve_path` for details.
747 ///
748 /// # Support
749 /// All Android version.
750 fn remove_dir(
751 &self,
752 base_dir: PrivateDir,
753 relative_path: Option<&str>,
754 ) -> crate::Result<()> {
755
756 let path = match relative_path {
757 Some(relative_path) => self.resolve_path_with(base_dir, relative_path)?,
758 None => self.resolve_path(base_dir)?,
759 };
760
761 std::fs::remove_dir(path)?;
762 Ok(())
763 }
764
765 /// Removes a directory at this path, after removing all its contents. Use carefully!
766 ///
767 /// This internally uses `PrivateStorage::resolve_path` and `std::fs::remove_dir_all`.
768 /// See `PrivateStorage::resolve_path` for details.
769 ///
770 /// # Support
771 /// All Android version.
772 fn remove_dir_all(
773 &self,
774 base_dir: PrivateDir,
775 relative_path: Option<&str>,
776 ) -> crate::Result<()> {
777
778 let path = match relative_path {
779 Some(relative_path) => self.resolve_path_with(base_dir, relative_path)?,
780 None => self.resolve_path(base_dir)?,
781 };
782
783 std::fs::remove_dir_all(path)?;
784 Ok(())
785 }
786
787 /// Returns Ok(true) if the path points at an existing entity.
788 ///
789 /// This internally uses `PrivateStorage::resolve_path` and `std::fs::exists`.
790 /// See `PrivateStorage::resolve_path` for details.
791 ///
792 /// # Support
793 /// All Android version.
794 fn exists(
795 &self,
796 base_dir: PrivateDir,
797 relative_path: impl AsRef<str>
798 ) -> crate::Result<bool> {
799
800 let path = self.resolve_path_with(base_dir, relative_path)?;
801 Ok(std::fs::exists(path)?)
802 }
803
804 /// Queries the file system to get information about a file, directory.
805 ///
806 /// This internally uses `PrivateStorage::resolve_path` and `std::fs::metadata`.
807 /// See `PrivateStorage::resolve_path` for details.
808 ///
809 /// # Support
810 /// All Android version.
811 fn metadata(
812 &self,
813 base_dir: PrivateDir,
814 relative_path: Option<&str>,
815 ) -> crate::Result<std::fs::Metadata> {
816
817 let path = match relative_path {
818 Some(relative_path) => self.resolve_path_with(base_dir, relative_path)?,
819 None => self.resolve_path(base_dir)?,
820 };
821
822 Ok(std::fs::metadata(path)?)
823 }
824}