tauri_plugin_android_fs/api/
public_storage.rs

1use sync_async::sync_async;
2use crate::*;
3use super::*;
4
5
6/// API of file storage that is available to other applications and users.  
7/// 
8/// # Examples
9/// ```no_run
10/// fn example(app: &tauri::AppHandle) {
11///     use tauri_plugin_android_fs::AndroidFsExt as _;
12/// 
13///     let api = app.android_fs();
14///     let public_storage = api.public_storage();
15/// }
16/// ```
17#[sync_async]
18pub struct PublicStorage<'a, R: tauri::Runtime> {
19    #[cfg(target_os = "android")]
20    pub(crate) handle: &'a tauri::plugin::PluginHandle<R>,
21
22    #[cfg(not(target_os = "android"))]
23    #[allow(unused)]
24    pub(crate) handle: &'a std::marker::PhantomData<fn() -> R>,
25}
26
27#[cfg(target_os = "android")]
28#[sync_async(
29    use(if_sync) impls::SyncImpls as Impls;
30    use(if_async) impls::AsyncImpls as Impls;
31)]
32impl<'a, R: tauri::Runtime> PublicStorage<'a, R> {
33    
34    #[always_sync]
35    fn impls(&self) -> Impls<'_, R> {
36        Impls { handle: &self.handle }
37    }
38}
39
40#[sync_async(
41    use(if_async) api_async::{AndroidFs, FileOpener, FilePicker, AppStorage, PrivateStorage, WritableStream};
42    use(if_sync) api_sync::{AndroidFs, FileOpener, FilePicker, AppStorage, PrivateStorage, WritableStream};
43)]
44impl<'a, R: tauri::Runtime> PublicStorage<'a, R> {
45
46    /// Requests file access permission from the user if needed.
47    ///
48    /// When this function returns `true`,
49    /// the app is allowed to create files in `PublicStorage` and read/write the files it creates. 
50    /// Access to files created by other apps is not guaranteed.
51    /// Additionally, after the app is uninstalled and reinstalled, 
52    /// previously created files may become inaccessible.
53    ///
54    /// # Version behavior
55    /// ### Android 11 or higher
56    /// Requests no permission.   
57    /// This function always returns `true`.
58    /// 
59    /// ### Android 10
60    /// Selects either the behavior for Android 11 or higher or for Android 9 or lower, as needed.
61    ///
62    /// ### Android 9 or lower
63    /// Requests [`WRITE_EXTERNAL_STORAGE`](https://developer.android.com/reference/android/Manifest.permission#WRITE_EXTERNAL_STORAGE) and [`READ_EXTERNAL_STORAGE`](https://developer.android.com/reference/android/Manifest.permission#READ_EXTERNAL_STORAGE) permissions.   
64    /// To request the permissions, you must declare it in `AndroidManifest.xml`.
65    /// By enabling the `legacy_storage_permission` feature,
66    /// the permissions will be declared automatically only for Android 9 or lower.
67    ///
68    /// # Support
69    /// All Android versions
70    #[maybe_async]
71    pub fn request_permission(&self) -> Result<bool> {
72        #[cfg(not(target_os = "android"))] {
73            Err(Error::NOT_ANDROID)
74        }
75        #[cfg(target_os = "android")] {
76            self.impls().request_storage_permission_for_public_storage().await
77        }
78    }
79
80    /// Indicates whether the app has file access permission.
81    ///
82    /// When this function returns `true`,
83    /// the app is allowed to create files in `PublicStorage` and read/write the files it creates. 
84    /// Access to files created by other apps is not guaranteed.
85    /// Additionally, after the app is uninstalled and reinstalled, 
86    /// previously created files may become inaccessible.
87    ///
88    /// # Version behavior
89    /// ### Android 11 or higher
90    /// Always returns `true`.
91    ///
92    /// ### Android 10
93    /// Selects either the behavior for Android 11 or higher or for Android 9 or lower, as needed.
94    ///
95    /// ### Android 9 or lower
96    /// Returns `true` if the app has been granted [`WRITE_EXTERNAL_STORAGE`](https://developer.android.com/reference/android/Manifest.permission#WRITE_EXTERNAL_STORAGE) and [`READ_EXTERNAL_STORAGE`](https://developer.android.com/reference/android/Manifest.permission#READ_EXTERNAL_STORAGE) permissions.    
97    /// See [`PublicStorage::request_permission`] for requesting the permissions.
98    ///
99    /// # Support
100    /// All Android versions.
101    #[maybe_async]
102    pub fn has_permission(&self) -> Result<bool> {
103        #[cfg(not(target_os = "android"))] {
104            Err(Error::NOT_ANDROID)
105        }
106        #[cfg(target_os = "android")] {
107            self.impls().has_storage_permission_for_public_storage().await
108        }
109    }
110
111    /// Gets a list of currently available storage volumes (internal storage, SD card, USB drive, etc.).
112    /// Be aware of TOCTOU.
113    /// 
114    /// Since read-only SD cards and similar cases may be included, 
115    /// please use [`StorageVolume { is_readonly, .. }`](StorageVolume) for filtering as needed.
116    /// 
117    /// This typically includes [`primary storage volume`](PublicStorage::get_primary_volume),
118    /// but it may occasionally be absent if the primary volume is inaccessible 
119    /// (e.g., mounted on a computer, removed, or another issue).
120    ///
121    /// Primary storage volume is always listed first, if included. 
122    /// But the order of the others is not guaranteed.  
123    /// 
124    /// # Version behavior
125    /// For Android 9 (API level 28) or lower, 
126    /// this does not include any storage volumes other than the primary one. 
127    /// 
128    /// # Note
129    /// The volume represents the logical view of a storage volume for an individual user:
130    /// each user may have a different view for the same physical volume.
131    /// In other words, it provides a separate area for each user in a multi-user environment.
132    /// 
133    /// # Support
134    /// All Android version.  
135    #[maybe_async]
136    pub fn get_volumes(&self) -> Result<Vec<StorageVolume>> {
137        #[cfg(not(target_os = "android"))] {
138            Err(Error::NOT_ANDROID)
139        }
140        #[cfg(target_os = "android")] {
141            self.impls().get_available_storage_volumes_for_public_storage().await
142        }
143    }
144
145    /// Gets a primary storage volume.  
146    /// This is the most common and recommended storage volume for placing files that can be accessed by other apps or user.
147    /// In many cases, it is device's built-in storage.  
148    /// 
149    /// A device always has one (and one only) primary storage volume.  
150    /// 
151    /// Primary volume may not currently be accessible 
152    /// if it has been mounted by the user on their computer, 
153    /// has been removed from the device, or some other problem has happened. 
154    /// If so, this returns `None`.
155    /// 
156    /// # Note
157    /// The volume represents the logical view of a storage volume for an individual user:
158    /// each user may have a different view for the same physical volume.
159    /// In other words, it provides a separate area for each user in a multi-user environment.
160    /// 
161    /// # Support
162    /// All Android version.
163    #[maybe_async]
164    pub fn get_primary_volume(&self) -> Result<Option<StorageVolume>> {
165        #[cfg(not(target_os = "android"))] {
166            Err(Error::NOT_ANDROID)
167        }
168        #[cfg(target_os = "android")] {
169            self.impls().get_primary_storage_volume_if_available_for_public_storage().await
170        }
171    }
172
173    /// Creates a new empty file in the specified public directory of the storage volume.  
174    /// This returns a **persistent read-write** URI.
175    ///
176    /// The app can read/write it until the app is uninstalled. 
177    /// And it is **not** removed when the app itself is uninstalled.  
178    /// 
179    /// # Note
180    /// ### Android 10 or higher. 
181    /// Files are automatically registered in the appropriate MediaStore as needed. 
182    /// Scanning is triggered when the file descriptor is closed
183    /// or as part of the [`pending`](PublicStorage::set_pending) lifecycle.
184    /// 
185    /// ### Android 9 or lower
186    /// [`WRITE_EXTERNAL_STORAGE`](https://developer.android.com/reference/android/Manifest.permission#WRITE_EXTERNAL_STORAGE) and [`READ_EXTERNAL_STORAGE`](https://developer.android.com/reference/android/Manifest.permission#READ_EXTERNAL_STORAGE) permissions are required.    
187    /// This needs two steps: 
188    /// 
189    /// 1. Declare :  
190    ///     By enabling the `legacy_storage_permission` feature,  
191    ///     you can declare the permissions only for Android 9 or lower automatically at build time.  
192    ///
193    /// 2. Runtime request :  
194    ///     By calling [`PublicStorage::request_permission`],
195    ///     you can request the permissions from the user at runtime.  
196    ///
197    /// After writing content to the file, call [`PublicStorage::scan`].  
198    /// Until then, the file may not appear in the gallery or other apps.
199    /// 
200    /// # Args
201    /// - ***volume_id*** :  
202    /// The ID of the storage volume, such as internal storage or an SD card.  
203    /// Usually, you don't need to specify this unless there is a special reason.  
204    /// If `None` is provided, [`the primary storage volume`](PublicStorage::get_primary_volume) will be used.
205    ///
206    /// - ***base_dir*** :  
207    /// The base directory for the file.  
208    /// When using [`PublicImageDir`], only image MIME types should be used for ***mime_type***; using other types may cause errors.  
209    /// Similarly, [`PublicVideoDir`] and [`PublicAudioDir`] should only be used with their respective media types.  
210    /// Only [`PublicGeneralPurposeDir`] supports all MIME types.
211    ///
212    /// - ***relative_path*** :  
213    /// The file path relative to the base directory.  
214    /// To keep files organized, it is recommended to place your app's name directory at the top level.  
215    /// Any missing parent directories will be created automatically.  
216    /// If a file with the same name already exists, a sequential number is appended to ensure uniqueness.  
217    /// If the file has no extension, one may be inferred from ***mime_type*** and appended to the file name.  
218    /// Strings may also be sanitized as needed, so they may not be used exactly as provided.
219    /// Note that append-exntesion and sanitize-path operation may vary depending on the device model and Android version.  
220    ///
221    /// - ***mime_type*** :  
222    /// The MIME type of the file to be created.  
223    /// If `None`, the MIME type will be inferred from the extension of ***relative_path***.  
224    /// If that also fails, `application/octet-stream` will be used.
225    /// 
226    /// # Support
227    /// All Android version.
228    ///
229    /// Note :  
230    /// - [`PublicAudioDir::Audiobooks`] is not available on Android 9 (API level 28) and lower.
231    /// Availability on a given device can be verified by calling [`PublicStorage::is_audiobooks_dir_available`].  
232    /// - [`PublicAudioDir::Recordings`] is not available on Android 11 (API level 30) and lower.
233    /// Availability on a given device can be verified by calling [`PublicStorage::is_recordings_dir_available`].  
234    /// - Others dirs are available in all Android versions.
235    #[maybe_async]
236    pub fn create_new_file(
237        &self,
238        volume_id: Option<&StorageVolumeId>,
239        base_dir: impl Into<PublicDir>,
240        relative_path: impl AsRef<std::path::Path>, 
241        mime_type: Option<&str>
242    ) -> Result<FileUri> {
243
244        #[cfg(not(target_os = "android"))] {
245            Err(Error::NOT_ANDROID)
246        }
247        #[cfg(target_os = "android")] {
248            self.impls().create_new_file_in_public_storage(
249                volume_id, 
250                base_dir, 
251                relative_path, 
252                mime_type, 
253                false
254            ).await
255        }
256    }
257
258    /// Creates a new empty file in the specified public directory of the storage volume.  
259    /// This returns a **persistent read-write** URI.
260    ///
261    /// The app can read/write it until the app is uninstalled. 
262    /// And it is **not** removed when the app itself is uninstalled.  
263    /// 
264    /// # Note
265    /// ### Android 10 or higher
266    /// Files are automatically registered in the appropriate MediaStore as needed. 
267    /// Scanning is triggered when the file descriptor is closed
268    /// or as part of the [`pending`](PublicStorage::set_pending) lifecycle.
269    /// 
270    /// Diffrences from [`PublicStorage::create_new_file`] are that
271    /// files are marked as pending and will not be visible to other apps until 
272    /// [`PublicStorage::set_pending(..., false)`](PublicStorage::set_pending) is called. 
273    ///
274    /// ### Android 9 or lower
275    /// This behavior is equal to [`PublicStorage::create_new_file`]. 
276    /// So `pending` is ignored.  
277    /// 
278    /// [`WRITE_EXTERNAL_STORAGE`](https://developer.android.com/reference/android/Manifest.permission#WRITE_EXTERNAL_STORAGE) and [`READ_EXTERNAL_STORAGE`](https://developer.android.com/reference/android/Manifest.permission#READ_EXTERNAL_STORAGE) permissions are required.    
279    /// This needs two steps: 
280    /// 
281    /// 1. Declare :  
282    ///     By enabling the `legacy_storage_permission` feature,  
283    ///     you can declare the permissions only for Android 9 or lower automatically at build time.  
284    ///
285    /// 2. Runtime request :  
286    ///     By calling [`PublicStorage::request_permission`],
287    ///     you can request the permissions from the user at runtime.  
288    ///
289    /// After writing content to the file, call [`PublicStorage::scan`].  
290    /// Until then, the file may not appear in the gallery or other apps.
291    /// 
292    /// # Args
293    /// - ***volume_id*** :  
294    /// The ID of the storage volume, such as internal storage or an SD card.  
295    /// Usually, you don't need to specify this unless there is a special reason.  
296    /// If `None` is provided, [`the primary storage volume`](PublicStorage::get_primary_volume) will be used.
297    ///
298    /// - ***base_dir*** :  
299    /// The base directory for the file.  
300    /// When using [`PublicImageDir`], only image MIME types should be used for ***mime_type***; using other types may cause errors.  
301    /// Similarly, [`PublicVideoDir`] and [`PublicAudioDir`] should only be used with their respective media types.  
302    /// Only [`PublicGeneralPurposeDir`] supports all MIME types.
303    ///
304    /// - ***relative_path*** :  
305    /// The file path relative to the base directory.  
306    /// To keep files organized, it is recommended to place your app's name directory at the top level.  
307    /// Any missing parent directories will be created automatically.  
308    /// If a file with the same name already exists, a sequential number is appended to ensure uniqueness.  
309    /// If the file has no extension, one may be inferred from ***mime_type*** and appended to the file name.  
310    /// Strings may also be sanitized as needed, so they may not be used exactly as provided.
311    /// Note that append-exntesion and sanitize-path operation may vary depending on the device model and Android version.  
312    ///
313    /// - ***mime_type*** :  
314    /// The MIME type of the file to be created.  
315    /// If `None`, the MIME type will be inferred from the extension of ***relative_path***.  
316    /// If that also fails, `application/octet-stream` will be used.
317    /// 
318    /// # Support
319    /// All Android version.
320    ///
321    /// Note :  
322    /// - [`PublicAudioDir::Audiobooks`] is not available on Android 9 (API level 28) and lower.
323    /// Availability on a given device can be verified by calling [`PublicStorage::is_audiobooks_dir_available`].  
324    /// - [`PublicAudioDir::Recordings`] is not available on Android 11 (API level 30) and lower.
325    /// Availability on a given device can be verified by calling [`PublicStorage::is_recordings_dir_available`].  
326    /// - Others dirs are available in all Android versions.
327    #[maybe_async]
328    pub fn create_new_file_with_pending(
329        &self,
330        volume_id: Option<&StorageVolumeId>,
331        base_dir: impl Into<PublicDir>,
332        relative_path: impl AsRef<std::path::Path>, 
333        mime_type: Option<&str>
334    ) -> Result<FileUri> {
335
336        #[cfg(not(target_os = "android"))] {
337            Err(Error::NOT_ANDROID)
338        }
339        #[cfg(target_os = "android")] {
340            self.impls().create_new_file_in_public_storage(
341                volume_id, 
342                base_dir, 
343                relative_path, 
344                mime_type, 
345                true
346            ).await
347        }
348    }
349
350    /// Recursively create a directory and all of its parent components if they are missing.  
351    /// If it already exists, do nothing.
352    /// 
353    /// [`PublicStorage::create_new_file`] and [`PublicStorage::create_new_file_with_pending`]
354    /// do this automatically, so there is no need to use it together.
355    /// 
356    /// # Note
357    /// On Android 9 or lower,
358    /// [`WRITE_EXTERNAL_STORAGE`](https://developer.android.com/reference/android/Manifest.permission#WRITE_EXTERNAL_STORAGE) and [`READ_EXTERNAL_STORAGE`](https://developer.android.com/reference/android/Manifest.permission#READ_EXTERNAL_STORAGE) permissions are required.    
359    /// This needs two steps: 
360    /// 
361    /// 1. Declare :  
362    ///     By enabling the `legacy_storage_permission` feature,  
363    ///     you can declare the permissions only for Android 9 or lower automatically at build time.  
364    ///
365    /// 2. Runtime request :  
366    ///     By calling [`PublicStorage::request_permission`],
367    ///     you can request the permissions from the user at runtime.  
368    ///
369    /// # Args  
370    /// - ***volume_id*** :  
371    /// ID of the storage volume, such as internal storage, SD card, etc.  
372    /// If `None` is provided, [`the primary storage volume`](PublicStorage::get_primary_volume) will be used.  
373    /// 
374    /// - ***base_dir*** :  
375    /// The base directory.  
376    ///  
377    /// - ***relative_path*** :  
378    /// The directory path relative to the base directory.    
379    /// Strings may also be sanitized as needed, so they may not be used exactly as provided.
380    /// Note that sanitize-path operation may vary depending on the device model and Android version.  
381    ///
382    /// # Support
383    /// All Android Version.
384    ///
385    /// Note :  
386    /// - [`PublicAudioDir::Audiobooks`] is not available on Android 9 (API level 28) and lower.
387    /// Availability on a given device can be verified by calling [`PublicStorage::is_audiobooks_dir_available`].  
388    /// - [`PublicAudioDir::Recordings`] is not available on Android 11 (API level 30) and lower.
389    /// Availability on a given device can be verified by calling [`PublicStorage::is_recordings_dir_available`].  
390    /// - Others dirs are available in all Android versions.
391    #[maybe_async]
392    pub fn create_dir_all(
393        &self,
394        volume_id: Option<&StorageVolumeId>,
395        base_dir: impl Into<PublicDir>,
396        relative_path: impl AsRef<std::path::Path>, 
397    ) -> Result<()> {
398
399        #[cfg(not(target_os = "android"))] {
400            Err(Error::NOT_ANDROID)
401        }
402        #[cfg(target_os = "android")] {
403            self.impls().create_dir_all_in_public_storage(volume_id, base_dir, relative_path).await
404        }
405    }
406
407    /// Writes contents to the new file in the specified public directory of the storage volume.  
408    /// This returns a **persistent read-write** URI.
409    ///
410    /// The app can read/write it until the app is uninstalled. 
411    /// And it is **not** removed when the app itself is uninstalled.  
412    /// 
413    /// # Note
414    /// On Android 9 or lower,
415    /// [`WRITE_EXTERNAL_STORAGE`](https://developer.android.com/reference/android/Manifest.permission#WRITE_EXTERNAL_STORAGE) and [`READ_EXTERNAL_STORAGE`](https://developer.android.com/reference/android/Manifest.permission#READ_EXTERNAL_STORAGE) permissions are required.    
416    /// This needs two steps: 
417    /// 
418    /// 1. Declare :  
419    ///     By enabling the `legacy_storage_permission` feature,  
420    ///     you can declare the permissions only for Android 9 or lower automatically at build time.  
421    ///
422    /// 2. Runtime request :  
423    ///     By calling [`PublicStorage::request_permission`],
424    ///     you can request the permissions from the user at runtime.  
425    ///
426    /// # Args
427    /// - ***volume_id*** :  
428    /// The ID of the storage volume, such as internal storage or an SD card.  
429    /// Usually, you don't need to specify this unless there is a special reason.  
430    /// If `None` is provided, [`the primary storage volume`](PublicStorage::get_primary_volume) will be used.
431    ///
432    /// - ***base_dir*** :  
433    /// The base directory for the file.  
434    /// When using [`PublicImageDir`], only image MIME types should be used for ***mime_type***; using other types may cause errors.  
435    /// Similarly, [`PublicVideoDir`] and [`PublicAudioDir`] should only be used with their respective media types.  
436    /// Only [`PublicGeneralPurposeDir`] supports all MIME types.
437    ///
438    /// - ***relative_path*** :  
439    /// The file path relative to the base directory.  
440    /// To keep files organized, it is recommended to place your app's name directory at the top level.  
441    /// Any missing parent directories will be created automatically.  
442    /// If a file with the same name already exists, a sequential number is appended to ensure uniqueness.  
443    /// If the file has no extension, one may be inferred from ***mime_type*** and appended to the file name.  
444    /// Strings may also be sanitized as needed, so they may not be used exactly as provided.
445    /// Note that append-exntesion and sanitize-path operation may vary depending on the device model and Android version.  
446    ///
447    /// - ***mime_type*** :  
448    /// The MIME type of the file to be created.  
449    /// If `None`, the MIME type will be inferred from the extension of ***relative_path***.  
450    /// If that also fails, `application/octet-stream` will be used.
451    /// 
452    /// - ***contents*** :  
453    /// Contents.
454    /// 
455    /// # Support
456    /// All Android version.
457    ///
458    /// Note :  
459    /// - [`PublicAudioDir::Audiobooks`] is not available on Android 9 (API level 28) and lower.
460    /// Availability on a given device can be verified by calling [`PublicStorage::is_audiobooks_dir_available`].  
461    /// - [`PublicAudioDir::Recordings`] is not available on Android 11 (API level 30) and lower.
462    /// Availability on a given device can be verified by calling [`PublicStorage::is_recordings_dir_available`].  
463    /// - Others dirs are available in all Android versions.
464    #[maybe_async]
465    pub fn write_new(
466        &self,
467        volume_id: Option<&StorageVolumeId>,
468        base_dir: impl Into<PublicDir>,
469        relative_path: impl AsRef<std::path::Path>,
470        mime_type: Option<&str>,
471        contents: impl AsRef<[u8]>
472    ) -> Result<FileUri> {
473
474        #[cfg(not(target_os = "android"))] {
475            Err(Error::NOT_ANDROID)
476        }
477        #[cfg(target_os = "android")] {
478            self.impls().write_new_file_in_public_storage(volume_id, base_dir, relative_path, mime_type, contents).await
479        }
480    }
481
482    /// Scans the specified file in MediaStore.   
483    /// By doing this, the file will be visible with corrent metadata in the Gallery and etc.
484    ///
485    /// You don’t need to call this after [`PublicStorage::write_new`].   
486    /// 
487    /// # Version behavior
488    /// ### Android 10 or higher
489    /// This function does nothing, 
490    /// because files are automatically registered in the appropriate MediaStore as needed. 
491    /// Scanning is triggered when the file descriptor is closed
492    /// or as part of the [`pending`](PublicStorage::set_pending) lifecycle.  
493    /// 
494    /// If you really need to perform this operation in this version, 
495    /// please use [`PublicStorage::_scan`].
496    ///
497    /// ### Android 9 or lower
498    /// Requests the specified file to be scanned by MediaStore.  
499    /// This function returns when the scan request has been initiated.   
500    /// 
501    /// # Args
502    /// - ***uri*** :  
503    /// The target file URI.
504    /// This must be a URI obtained from one of the following:  
505    ///     - [`PublicStorage::write_new`]
506    ///     - [`PublicStorage::create_new_file`]
507    ///     - [`PublicStorage::create_new_file_with_pending`]
508    ///     - [`PublicStorage::scan_by_path`]
509    ///
510    /// # Support
511    /// All Android versions.
512    #[maybe_async]
513    pub fn scan(
514        &self, 
515        uri: &FileUri,
516    ) -> Result<()> {
517
518        #[cfg(not(target_os = "android"))] {
519            Err(Error::NOT_ANDROID)
520        }
521        #[cfg(target_os = "android")] {
522            self.impls().scan_file_in_public_storage(uri, false).await
523        }
524    }
525
526    /// For details, see [`PublicStorage::scan`].
527    /// 
528    /// The difference is that this method scans the file even on Android 10 or higher.
529    /// 
530    /// On Android 10 or higher, files are automatically registered in the appropriate MediaStore as needed. 
531    /// Scanning is triggered when the file descriptor is closed
532    /// or as part of the [`pending`](PublicStorage::set_pending) lifecycle.  
533    /// Therefore, please consider carefully whether this is truly necessary. 
534    #[maybe_async]
535    pub fn _scan(
536        &self, 
537        uri: &FileUri,
538    ) -> Result<()> {
539
540        #[cfg(not(target_os = "android"))] {
541            Err(Error::NOT_ANDROID)
542        }
543        #[cfg(target_os = "android")] {
544            self.impls().scan_file_in_public_storage(uri, true).await
545        }
546    }
547
548    /// For details, see [`PublicStorage::_scan`].
549    /// 
550    /// The difference is that this function waits until the scan is complete and then returns either success or an error.
551    #[maybe_async]
552    pub fn _scan_for_result(
553        &self, 
554        uri: &FileUri,
555    ) -> Result<()> {
556
557        #[cfg(not(target_os = "android"))] {
558            Err(Error::NOT_ANDROID)
559        }
560        #[cfg(target_os = "android")] {
561            self.impls().scan_file_in_public_storage_for_result(uri, true).await
562        }
563    }
564
565    /// Scans the specified file in MediaStore and returns it's URI if success.   
566    /// By doing this, the file will be visible in the Gallery and etc.
567    ///
568    /// # Note
569    /// Unlike [`PublicStorage::scan`], 
570    /// this function waits until the scan is complete and then returns either success or an error.
571    /// 
572    /// # Args
573    /// - ***uri*** :  
574    /// Absolute path of the target file.
575    /// This must be a path obtained from one of the following:  
576    ///     - [`PublicStorage::_resolve_path`] and it's descendants path.
577    ///     - [`PublicStorage::_get_path`]
578    /// 
579    /// - ***mime_type*** :  
580    /// The MIME type of the file.  
581    /// If `None`, the MIME type will be inferred from the extension of the path.  
582    /// If that also fails, `application/octet-stream` will be used.
583    /// 
584    /// # Support
585    /// All Android version.
586    #[maybe_async]
587    pub fn scan_by_path(
588        &self, 
589        path: impl AsRef<std::path::Path>,
590        mime_type: Option<&str>
591    ) -> Result<FileUri> {
592
593        #[cfg(not(target_os = "android"))] {
594            Err(Error::NOT_ANDROID)
595        }
596        #[cfg(target_os = "android")] {
597            self.impls().scan_file_by_path_in_public_storage(path, mime_type).await
598        }
599    }
600
601    /// Specifies whether the specified file on PublicStorage is marked as pending.   
602    /// When set to `true`, the app has exclusive access to the file, and it becomes invisible to other apps.
603    /// 
604    /// If it remains `true` for more than seven days, 
605    /// the system will automatically delete the file.
606    /// 
607    /// # Version behavior
608    /// This is available for Android 10 or higher.  
609    /// On Android 9 or lower, this does nothing. 
610    /// 
611    /// # Args
612    /// - ***uri*** :  
613    /// Target file URI.
614    /// This must be a URI obtained from one of the following:  
615    ///     - [`PublicStorage::write_new`]
616    ///     - [`PublicStorage::create_new_file`]
617    ///     - [`PublicStorage::create_new_file_with_pending`]
618    ///     - [`PublicStorage::scan_by_path`]
619    /// 
620    /// # Support
621    /// All Android version.
622    /// 
623    /// # References
624    /// - <https://developer.android.com/reference/android/provider/MediaStore.MediaColumns#IS_PENDING>
625    /// - <https://developer.android.com/training/data-storage/shared/media?hl=en#toggle-pending-status>
626    #[maybe_async]
627    pub fn set_pending(&self, uri: &FileUri, is_pending: bool) -> Result<()> {
628        #[cfg(not(target_os = "android"))] {
629            Err(Error::NOT_ANDROID)
630        }
631        #[cfg(target_os = "android")] {
632            self.impls().set_file_pending_in_public_storage(uri, is_pending).await
633        }
634    }
635
636    /// Gets the absolute path of the specified file.
637    /// 
638    /// # Note
639    /// For description and notes on path permissions and handling, 
640    /// see [`PublicStorage::_resolve_path`].
641    /// It involves important constraints and required settings. 
642    /// Therefore, **operate files via paths only when it is truly necessary**.
643    /// 
644    /// # Args
645    /// - ***uri*** :   
646    /// Target file URI.
647    /// This must be a URI obtained from one of the following:  
648    ///     - [`PublicStorage::write_new`]
649    ///     - [`PublicStorage::create_new_file`]
650    ///     - [`PublicStorage::create_new_file_with_pending`]
651    ///     - [`PublicStorage::scan_by_path`]
652    /// 
653    /// # Support
654    /// All Android version.
655    #[maybe_async]
656    pub fn _get_path(
657        &self,
658        uri: &FileUri,
659    ) -> Result<std::path::PathBuf> {
660
661        #[cfg(not(target_os = "android"))] {
662            Err(Error::NOT_ANDROID)
663        }
664        #[cfg(target_os = "android")] {
665            self.impls().get_file_path_in_public_storage(uri).await
666        }
667    }
668
669    /// Retrieves the absolute path for a specified public directory within the given storage volume.   
670    /// This function does **not** create any directories; it only constructs the path.
671    /// 
672    /// The app is allowed to create files in the directory and read/write the files it creates. 
673    /// Access to files created by other apps is not guaranteed.
674    /// Additionally, after the app is uninstalled and reinstalled, 
675    /// previously created files may become inaccessible.
676    /// 
677    /// The directory is **not** removed when the app itself is uninstalled.  
678    /// 
679    /// It is strongly recommended to call [`PublicStorage::scan_by_path`] 
680    /// after writing to the file to request registration in MediaStore.  
681    /// 
682    /// # Note
683    /// As shown below, this involves important constraints and required settings.
684    /// Therefore, **operate files via paths only when it is truly necessary**.
685    /// 
686    /// Do not use operations such as rename or remove that rely on paths 
687    /// (including URIs obtained via [`FileUri::from_path`] with this paths), 
688    /// as they may break consistency with the MediaStore on old version.
689    /// Instead, use the URI obtained through [`PublicStorage::scan_by_path`] together with methods 
690    /// such as [`AndroidFs::rename`] or [`AndroidFs::remove_file`].
691    /// 
692    /// ### Android 11 or higher
693    /// No permission is required.   
694    /// When using [`PublicImageDir`], use only image type for file name extension, 
695    /// using other type extension or none may cause errors.
696    /// Similarly, use only the corresponding extesions for [`PublicVideoDir`] and [`PublicAudioDir`].
697    /// Only [`PublicGeneralPurposeDir`] supports all extensions and no extension. 
698    /// 
699    /// ### Android 10 or lower
700    /// [`WRITE_EXTERNAL_STORAGE`](https://developer.android.com/reference/android/Manifest.permission#WRITE_EXTERNAL_STORAGE) and [`READ_EXTERNAL_STORAGE`](https://developer.android.com/reference/android/Manifest.permission#READ_EXTERNAL_STORAGE) permissions are required.    
701    /// This needs two steps: 
702    /// 
703    /// 1. Declare :  
704    ///     By enabling the `legacy_storage_permission_include_android_10` feature,  
705    ///     you can declare the permissions only for Android 10 or lower automatically at build time.  
706    /// 
707    /// 2. Runtime request :  
708    ///     By calling [`PublicStorage::request_permission`],
709    ///     you can request the permissions from the user at runtime.  
710    ///
711    /// ### Android 10
712    /// Files within PublicStorage cannot be accessed via file paths, 
713    /// so it is necessary to declare that the app need access `PublicStorage` using the method of Android 9 or lower.   
714    /// 
715    /// For it, please [set `android:requestLegacyExternalStorage="true"`](https://developer.android.com/training/data-storage/use-cases#opt-out-in-production-app).
716    /// 
717    /// `src-tauri/gen/android/app/src/main/AndroidManifest.xml`
718    /// ```xml
719    /// <manifest ... >
720    ///     <application 
721  	///         android:requestLegacyExternalStorage="true" 
722  	///         ...
723    ///     >
724    ///         ...
725    ///     </application>
726    /// </manifest>
727    /// ```
728    /// And it is not possible to access `PublicStorage`
729	/// on volumes other than the primary storage via paths, just like on Android 9 or lower.   
730	/// But filtering using [`PublicStorage::get_volumes`]
731	/// or [`StorageVolume::is_available_for_public_storage`] may not work correctly, 
732	/// as these are intended for access via URIs.
733    /// 
734    /// # Args
735    /// - ***volume_id*** :  
736    /// ID of the storage volume, such as internal storage, SD card, etc.  
737    /// If `None` is provided, [`the primary storage volume`](PublicStorage::get_primary_volume) will be used.  
738    /// 
739    /// - ***base_dir*** :  
740    /// The base directory.  
741    /// One of [`PublicImageDir`], [`PublicVideoDir`], [`PublicAudioDir`], [`PublicGeneralPurposeDir`].  
742    ///  
743    /// # Support
744    /// All Android version.
745    /// 
746    /// Note :  
747    /// - [`PublicAudioDir::Audiobooks`] is not available on Android 9 (API level 28) and lower.
748    /// Availability on a given device can be verified by calling [`PublicStorage::is_audiobooks_dir_available`].  
749    /// - [`PublicAudioDir::Recordings`] is not available on Android 11 (API level 30) and lower.
750    /// Availability on a given device can be verified by calling [`PublicStorage::is_recordings_dir_available`].  
751    /// - Others dirs are available in all Android versions.
752    #[maybe_async]
753    pub fn _resolve_path(
754        &self,
755        volume_id: Option<&StorageVolumeId>,
756        base_dir: impl Into<PublicDir>,
757    ) -> Result<std::path::PathBuf> {
758
759        #[cfg(not(target_os = "android"))] {
760            Err(Error::NOT_ANDROID)
761        }
762        #[cfg(target_os = "android")] {
763            self.impls().resolve_dir_path_in_public_storage(volume_id, base_dir).await
764        }
765    }
766
767    /// Builds the specified directory URI.  
768    /// 
769    /// This should only be used as `initial_location` in the file picker, such as [`FilePicker::pick_files`]. 
770    /// It must not be used for any other purpose.  
771    /// 
772    /// This is useful when selecting save location, 
773    /// but when selecting existing entries, `initial_location` is often better with None.
774    /// 
775    /// # Args  
776    /// - ***volume_id*** :  
777    /// ID of the storage volume, such as internal storage, SD card, etc.  
778    /// If `None` is provided, [`the primary storage volume`](PublicStorage::get_primary_volume) will be used.  
779    /// 
780    /// - ***base_dir*** :  
781    /// The base directory.  
782    ///  
783    /// - ***relative_path*** :  
784    /// The directory path relative to the base directory.  
785    /// 
786    /// - ***create_dir_all*** :  
787    /// Creates directories if missing.  
788    /// See [`PublicStorage::create_dir_all`].
789    /// If error occurs, it will be ignored.
790    ///  
791    /// # Support
792    /// All Android version.
793    ///
794    /// Note :  
795    /// - [`PublicAudioDir::Audiobooks`] is not available on Android 9 (API level 28) and lower.
796    /// Availability on a given device can be verified by calling [`PublicStorage::is_audiobooks_dir_available`].  
797    /// - [`PublicAudioDir::Recordings`] is not available on Android 11 (API level 30) and lower.
798    /// Availability on a given device can be verified by calling [`PublicStorage::is_recordings_dir_available`].  
799    /// - Others dirs are available in all Android versions.
800    #[maybe_async]
801    pub fn resolve_initial_location(
802        &self,
803        volume_id: Option<&StorageVolumeId>,
804        base_dir: impl Into<PublicDir>,
805        relative_path: impl AsRef<std::path::Path>,
806        create_dir_all: bool
807    ) -> Result<FileUri> {
808
809        #[cfg(not(target_os = "android"))] {
810            Err(Error::NOT_ANDROID)
811        }
812        #[cfg(target_os = "android")] {
813            self.impls().resolve_initial_location_in_public_storage(volume_id, base_dir, relative_path, create_dir_all).await
814        }
815    }
816
817    /// Verify whether [`PublicAudioDir::Audiobooks`] is available on a given device.   
818    /// 
819    /// If on Android 10 (API level 29) or higher, this returns true.  
820    /// If on Android 9 (API level 28) and lower, this returns false.  
821    /// 
822    /// # Support
823    /// All Android version.
824    #[always_sync]
825    pub fn is_audiobooks_dir_available(&self) -> Result<bool> {
826        #[cfg(not(target_os = "android"))] {
827            Err(Error::NOT_ANDROID)
828        }
829        #[cfg(target_os = "android")] {
830            Ok(self.impls().consts()?.env_dir_audiobooks.is_some())
831        }
832    }
833
834    /// Verify whether [`PublicAudioDir::Recordings`] is available on a given device.   
835    /// 
836    /// If on Android 12 (API level 31) or higher, this returns true.  
837    /// If on Android 11 (API level 30) and lower, this returns false.  
838    /// 
839    /// # Support
840    /// All Android version.
841    #[always_sync]
842    pub fn is_recordings_dir_available(&self) -> Result<bool> {
843        #[cfg(not(target_os = "android"))] {
844            Err(Error::NOT_ANDROID)
845        }
846        #[cfg(target_os = "android")] {
847            Ok(self.impls().consts()?.env_dir_recordings.is_some())
848        }
849    }
850    
851
852    #[deprecated = "Use PublicStorage::scan instead"]
853    #[maybe_async]
854    pub fn scan_file(
855        &self, 
856        uri: &FileUri,
857    ) -> Result<()> {
858
859        self.scan(uri).await
860    }
861
862    #[deprecated = "Use `AndroidFs::resolve_root_initial_location` instead"]
863    #[maybe_async]
864    pub fn resolve_initial_location_top(
865        &self,
866        volume_id: Option<&StorageVolumeId>
867    ) -> Result<FileUri> {
868
869        #[cfg(not(target_os = "android"))] {
870            Err(Error::NOT_ANDROID)
871        }
872        #[cfg(target_os = "android")] {
873            self.impls().resolve_root_initial_location(volume_id).await
874        }
875    }
876
877    #[deprecated = "Use `PublicStorage::_resolve_path` instead"]
878    #[maybe_async]
879    pub fn resolve_path(
880        &self,
881        volume_id: Option<&StorageVolumeId>,
882        base_dir: impl Into<PublicDir>,
883    ) -> Result<std::path::PathBuf> {
884
885        self._resolve_path(volume_id, base_dir).await
886    }
887
888    #[deprecated = "Use `PublicStorage::_get_path` instead"]
889    #[maybe_async]
890    pub fn get_path(
891        &self,
892        uri: &FileUri,
893    ) -> Result<std::path::PathBuf> {
894
895        self._get_path(uri).await
896    }
897}