Skip to main content

tauri_plugin_android_fs/models/
dir.rs

1use serde::{Deserialize, Serialize};
2use std::str::FromStr;
3use crate::*;
4
5
6/// The application specific directory.  
7#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Deserialize, Serialize)]
8#[non_exhaustive]
9pub enum PrivateDir {
10
11    /// The application specific persistent-data directory.  
12    /// 
13    /// Files stored in this directory are included in [Android Auto Backup](https://developer.android.com/identity/data/autobackup).  
14    /// 
15    /// The system prevents other apps and user from accessing these locations. 
16    /// In cases where the device is rooted or the user has special permissions, the user may be able to access this.   
17    ///  
18    /// This will be deleted when the app is uninstalled and may also be deleted at the user’s request.  
19    /// 
20    /// e.g. `/data/user/0/{app-package-name}/files`
21    /// 
22    /// <https://developer.android.com/reference/android/content/Context#getFilesDir()>
23    Data,
24
25    /// The application specific cache directory.  
26    /// 
27    /// Files stored in this directory are **not** included in [Android Auto Backup](https://developer.android.com/identity/data/autobackup).  
28    /// 
29    /// The system prevents other apps and user from accessing these locations. 
30    /// In cases where the device is rooted or the user has special permissions, the user may be able to access this.   
31    /// 
32    /// This will be deleted when the app is uninstalled and may also be deleted at the user’s request. 
33    ///
34    /// In addition, the system will automatically delete files in this directory as disk space is needed elsewhere on the device. 
35    /// But you should not rely on this. The cache should be explicitly cleared by yourself.
36    /// 
37    /// e.g. `/data/user/0/{app-package-name}/cache`
38    /// 
39    /// <https://developer.android.com/reference/android/content/Context#getCacheDir()>
40    Cache,
41
42    /// The application specific persistent-data directory.  
43    /// 
44    /// This is similar to [`PrivateDir::Data`].
45    /// But files stored in this directory are **not** included in [Android Auto Backup](https://developer.android.com/identity/data/autobackup).  
46    /// 
47    /// The system prevents other apps and user from accessing these locations. 
48    /// In cases where the device is rooted or the user has special permissions, the user may be able to access this.   
49    ///  
50    /// This will be deleted when the app is uninstalled and may also be deleted at the user’s request.  
51    /// 
52    /// e.g. `/data/user/0/{app-package-name}/no_backup`
53    /// 
54    /// <https://developer.android.com/reference/android/content/Context#getNoBackupFilesDir()>
55    NoBackupData,
56}
57
58/// The directory for the app.  
59#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Deserialize, Serialize)]
60#[non_exhaustive]
61pub enum AppDir {
62
63    /// The directory for persistent-data files.  
64    /// 
65    /// This will be deleted when the app is uninstalled and may also be deleted at the user’s request.  
66    ///
67    /// Please note that, unlike [`PrivateDir::Data`], it may be accessible by other apps.
68    /// 
69    /// e.g. 
70    /// - `/storage/emulated/0/Android/data/{app-package-name}/files`
71    /// - `/storage/{sd-card-id}/Android/data/{app-package-name}/files`
72    ///
73    /// <https://developer.android.com/reference/android/content/Context#getExternalFilesDirs(java.lang.String)>
74    Data,
75    
76    /// The directory for cache files.  
77    /// 
78    /// This will be deleted when the app is uninstalled and may also be deleted at the user’s request. 
79    ///
80    /// Please note that, unlike [`PrivateDir::Cache`], it may be accessible by other apps.
81    /// 
82    /// e.g. 
83    /// - `/storage/emulated/0/Android/data/{app-package-name}/cache`
84    /// - `/storage/{sd-card-id}/Android/data/{app-package-name}/cache`
85    ///
86    /// <https://developer.android.com/reference/android/content/Context#getExternalCacheDirs()>
87    Cache,
88
89    /// The directory for shared media files to other apps or user.  
90    /// 
91    /// This will be deleted when the app is uninstalled and may also be deleted at the user’s request. 
92    ///
93    /// For Android 11 (API level 30) or higher, 
94    /// this has been marked as deprecated. 
95    /// It still works, but you should consider migrating to [`PublicDir`] of [`PublicStorage`](crate::api::api_async::PublicStorage).
96    ///
97    /// e.g. 
98    /// - `/storage/emulated/0/Android/media/{app-package-name}`
99    /// - `/storage/{sd-card-id}/Android/media/{app-package-name}`
100    /// 
101    /// <https://developer.android.com/reference/android/content/Context#getExternalMediaDirs()>
102    #[deprecated(note = "For Android 11 (API level 30) or higher, this is deprecated. Use `PublicDir` of `PublicStorage` instead.")]
103    PublicMedia
104}
105
106#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Deserialize, Serialize)]
107#[non_exhaustive]
108pub enum PublicDir {
109    
110    #[serde(untagged)]
111    Image(PublicImageDir),
112
113    #[serde(untagged)]
114    Video(PublicVideoDir),
115
116    #[serde(untagged)]
117    Audio(PublicAudioDir),
118
119    #[serde(untagged)]
120    GeneralPurpose(PublicGeneralPurposeDir),
121}
122
123/// Directory in which to place images that are available to other applications and users.  
124#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Deserialize, Serialize)]
125#[non_exhaustive]
126pub enum PublicImageDir {
127
128    Pictures,
129
130    DCIM,
131}
132
133/// Directory in which to place videos that are available to other applications and users.  
134#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Deserialize, Serialize)]
135#[non_exhaustive]
136pub enum PublicVideoDir {
137
138	Movies,
139
140	DCIM,
141}
142
143/// Directory in which to place audios that are available to other applications and users.  
144#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Deserialize, Serialize)]
145#[non_exhaustive]
146pub enum PublicAudioDir {
147
148    Music,
149
150    Alarms,
151
152    /// This is not available on Android 9 (API level 28) and lower.  
153    Audiobooks,
154
155    Notifications,
156
157    Podcasts,
158
159    Ringtones,
160
161    /// This is not available on Android 11 (API level 30) and lower.  
162    Recordings,
163}
164
165/// Directory in which to place files that are available to other applications and users.  
166#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Deserialize, Serialize)]
167#[non_exhaustive]
168pub enum PublicGeneralPurposeDir {
169
170    Documents,
171
172    /// This is not the plural "Downloads", but the singular "Download".
173    /// <https://developer.android.com/reference/android/os/Environment#DIRECTORY_DOWNLOADS>
174    Download,
175}
176
177impl std::fmt::Display for PublicImageDir {
178    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
179        match self {
180            PublicImageDir::Pictures => write!(f, "Pictures"),
181            PublicImageDir::DCIM => write!(f, "DCIM"),
182        }
183    }
184}
185
186impl std::fmt::Display for PublicVideoDir {
187    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
188        match self {
189            PublicVideoDir::Movies => write!(f, "Movies"),
190            PublicVideoDir::DCIM => write!(f, "DCIM"),
191        }
192    }
193}
194
195impl std::fmt::Display for PublicAudioDir {
196    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
197        match self {
198            PublicAudioDir::Music => write!(f, "Music"),
199            PublicAudioDir::Alarms => write!(f, "Alarms"),
200            PublicAudioDir::Audiobooks => write!(f, "Audiobooks"),
201            PublicAudioDir::Notifications => write!(f, "Notifications"),
202            PublicAudioDir::Podcasts => write!(f, "Podcasts"),
203            PublicAudioDir::Ringtones => write!(f, "Ringtones"),
204            PublicAudioDir::Recordings => write!(f, "Recordings"),
205        }
206    }
207}
208
209impl std::fmt::Display for PublicGeneralPurposeDir {
210    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
211        match self {
212            PublicGeneralPurposeDir::Documents => write!(f, "Documents"),
213            PublicGeneralPurposeDir::Download => write!(f, "Download"),
214        }
215    }
216}
217
218impl std::fmt::Display for PublicDir {
219    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
220        match self {
221            PublicDir::Image(p) => p.fmt(f),
222            PublicDir::Video(p) => p.fmt(f),
223            PublicDir::Audio(p) => p.fmt(f),
224            PublicDir::GeneralPurpose(p) => p.fmt(f),
225        }
226    }
227}
228
229macro_rules! impl_into_pubdir {
230    ($target: ident, $wrapper: ident) => {
231        impl From<$target> for PublicDir {
232            fn from(value: $target) -> Self {
233                Self::$wrapper(value)
234            }
235        }
236    };
237}
238impl_into_pubdir!(PublicImageDir, Image);
239impl_into_pubdir!(PublicVideoDir, Video);
240impl_into_pubdir!(PublicAudioDir, Audio);
241impl_into_pubdir!(PublicGeneralPurposeDir, GeneralPurpose);
242
243impl FromStr for PublicImageDir {
244    type Err = Error;
245
246    fn from_str(s: &str) -> Result<Self> {
247        if s.eq_ignore_ascii_case("pictures") {
248            Ok(PublicImageDir::Pictures)
249        } 
250        else if s.eq_ignore_ascii_case("dcim") {
251            Ok(PublicImageDir::DCIM)
252        } 
253        else {
254            Err(Error::with(format!("invalid PublicImageDir: {s}")))
255        }
256    }
257}
258
259impl FromStr for PublicVideoDir {
260    type Err = Error;
261
262    fn from_str(s: &str) -> Result<Self> {
263        if s.eq_ignore_ascii_case("movies") {
264            Ok(PublicVideoDir::Movies)
265        }
266        else if s.eq_ignore_ascii_case("dcim") {
267            Ok(PublicVideoDir::DCIM)
268        }
269        else {
270            Err(Error::with(format!("invalid PublicVideoDir: {s}")))
271        }
272    }
273}
274
275impl FromStr for PublicAudioDir {
276    type Err = Error;
277
278    fn from_str(s: &str) -> Result<Self> {
279        if s.eq_ignore_ascii_case("music") {
280            Ok(PublicAudioDir::Music)
281        } 
282        else if s.eq_ignore_ascii_case("alarms") {
283            Ok(PublicAudioDir::Alarms)
284        }
285        else if s.eq_ignore_ascii_case("audiobooks") {
286            Ok(PublicAudioDir::Audiobooks)
287        }
288        else if s.eq_ignore_ascii_case("notifications") {
289            Ok(PublicAudioDir::Notifications)
290        } 
291        else if s.eq_ignore_ascii_case("podcasts") {
292            Ok(PublicAudioDir::Podcasts)
293        } 
294        else if s.eq_ignore_ascii_case("ringtones") {
295            Ok(PublicAudioDir::Ringtones)
296        } 
297        else if s.eq_ignore_ascii_case("recordings") {
298            Ok(PublicAudioDir::Recordings)
299        } 
300        else {
301            Err(Error::with(format!("invalid PublicAudioDir: {s}")))
302        }
303    }
304}
305
306impl FromStr for PublicGeneralPurposeDir {
307    type Err = Error;
308
309    fn from_str(s: &str) -> Result<Self> {
310        if s.eq_ignore_ascii_case("documents") {
311            Ok(PublicGeneralPurposeDir::Documents)
312        }
313        else if s.eq_ignore_ascii_case("download") {
314            Ok(PublicGeneralPurposeDir::Download)
315        } 
316        else if s.eq_ignore_ascii_case("downloads") {
317            Ok(PublicGeneralPurposeDir::Download)
318        } 
319        else {
320            Err(Error::with(format!("invalid PublicGeneralPurposeDir: {s}")))
321        }
322    }
323}
324
325impl FromStr for PublicDir {
326    type Err = Error;
327
328    fn from_str(s: &str) -> Result<Self> {
329        if let Ok(v) = PublicImageDir::from_str(s) {
330            Ok(PublicDir::Image(v))
331        }
332        else if let Ok(v) = PublicVideoDir::from_str(s) {
333            Ok(PublicDir::Video(v))
334        }
335        else if let Ok(v) = PublicAudioDir::from_str(s) {
336            Ok(PublicDir::Audio(v))
337        }
338        else if let Ok(v) = PublicGeneralPurposeDir::from_str(s) {
339            Ok(PublicDir::GeneralPurpose(v))
340        }
341        else {
342            Err(Error::with(format!("invalid PublicDir: {s}")))
343        }
344    }
345}