Skip to main content

tauri_plugin_android_fs/api/models/
dir.rs

1use serde::{Deserialize, Serialize};
2use std::str::FromStr;
3use crate::*;
4
5
6/// Directory for the app’s use only.
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/// Directory for the app’s use.  
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    /// This may be accessible by other apps.
68    /// 
69    /// e.g. 
70    /// - `/storage/emulated/{user-id}/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    /// This may be accessible by other apps.
81    /// 
82    /// e.g. 
83    /// - `/storage/emulated/{user-id}/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 [`PublicStorage`](crate::api::api_async::PublicStorage).
96    ///
97    /// e.g. 
98    /// - `/storage/emulated/{user-id}/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/// Directory in which to place files that are available to other applications and users. 
107#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Deserialize, Serialize)]
108#[non_exhaustive]
109pub enum PublicDir {
110    
111    #[serde(untagged)]
112    Image(PublicImageDir),
113
114    #[serde(untagged)]
115    Video(PublicVideoDir),
116
117    #[serde(untagged)]
118    Audio(PublicAudioDir),
119
120    #[serde(untagged)]
121    GeneralPurpose(PublicGeneralPurposeDir),
122}
123
124/// Directory in which to place images that are available to other applications and users.  
125#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Deserialize, Serialize)]
126#[non_exhaustive]
127pub enum PublicImageDir {
128
129    Pictures,
130
131    DCIM,
132}
133
134/// Directory in which to place videos that are available to other applications and users.  
135#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Deserialize, Serialize)]
136#[non_exhaustive]
137pub enum PublicVideoDir {
138
139	Movies,
140
141	DCIM,
142}
143
144/// Directory in which to place audios that are available to other applications and users.  
145#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Deserialize, Serialize)]
146#[non_exhaustive]
147pub enum PublicAudioDir {
148
149    Music,
150
151    Alarms,
152
153    /// This is not available on Android 9 (API level 28) and lower.  
154    Audiobooks,
155
156    Notifications,
157
158    Podcasts,
159
160    Ringtones,
161
162    /// This is not available on Android 11 (API level 30) and lower.  
163    Recordings,
164}
165
166/// Directory in which to place files that are available to other applications and users.  
167#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Deserialize, Serialize)]
168#[non_exhaustive]
169pub enum PublicGeneralPurposeDir {
170
171    Documents,
172
173    /// This is not the plural "Downloads", but the singular "Download".
174    /// <https://developer.android.com/reference/android/os/Environment#DIRECTORY_DOWNLOADS>
175    Download,
176}
177
178impl std::fmt::Display for PublicImageDir {
179    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
180        match self {
181            PublicImageDir::Pictures => write!(f, "Pictures"),
182            PublicImageDir::DCIM => write!(f, "DCIM"),
183        }
184    }
185}
186
187impl std::fmt::Display for PublicVideoDir {
188    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
189        match self {
190            PublicVideoDir::Movies => write!(f, "Movies"),
191            PublicVideoDir::DCIM => write!(f, "DCIM"),
192        }
193    }
194}
195
196impl std::fmt::Display for PublicAudioDir {
197    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
198        match self {
199            PublicAudioDir::Music => write!(f, "Music"),
200            PublicAudioDir::Alarms => write!(f, "Alarms"),
201            PublicAudioDir::Audiobooks => write!(f, "Audiobooks"),
202            PublicAudioDir::Notifications => write!(f, "Notifications"),
203            PublicAudioDir::Podcasts => write!(f, "Podcasts"),
204            PublicAudioDir::Ringtones => write!(f, "Ringtones"),
205            PublicAudioDir::Recordings => write!(f, "Recordings"),
206        }
207    }
208}
209
210impl std::fmt::Display for PublicGeneralPurposeDir {
211    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
212        match self {
213            PublicGeneralPurposeDir::Documents => write!(f, "Documents"),
214            PublicGeneralPurposeDir::Download => write!(f, "Download"),
215        }
216    }
217}
218
219impl std::fmt::Display for PublicDir {
220    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
221        match self {
222            PublicDir::Image(p) => p.fmt(f),
223            PublicDir::Video(p) => p.fmt(f),
224            PublicDir::Audio(p) => p.fmt(f),
225            PublicDir::GeneralPurpose(p) => p.fmt(f),
226        }
227    }
228}
229
230macro_rules! impl_into_pubdir {
231    ($target: ident, $wrapper: ident) => {
232        impl From<$target> for PublicDir {
233            fn from(value: $target) -> Self {
234                Self::$wrapper(value)
235            }
236        }
237    };
238}
239impl_into_pubdir!(PublicImageDir, Image);
240impl_into_pubdir!(PublicVideoDir, Video);
241impl_into_pubdir!(PublicAudioDir, Audio);
242impl_into_pubdir!(PublicGeneralPurposeDir, GeneralPurpose);
243
244impl FromStr for PublicImageDir {
245    type Err = Error;
246
247    fn from_str(s: &str) -> Result<Self> {
248        if s.eq_ignore_ascii_case("pictures") {
249            Ok(PublicImageDir::Pictures)
250        } 
251        else if s.eq_ignore_ascii_case("dcim") {
252            Ok(PublicImageDir::DCIM)
253        } 
254        else {
255            Err(Error::with(format!("invalid PublicImageDir: {s}")))
256        }
257    }
258}
259
260impl FromStr for PublicVideoDir {
261    type Err = Error;
262
263    fn from_str(s: &str) -> Result<Self> {
264        if s.eq_ignore_ascii_case("movies") {
265            Ok(PublicVideoDir::Movies)
266        }
267        else if s.eq_ignore_ascii_case("dcim") {
268            Ok(PublicVideoDir::DCIM)
269        }
270        else {
271            Err(Error::with(format!("invalid PublicVideoDir: {s}")))
272        }
273    }
274}
275
276impl FromStr for PublicAudioDir {
277    type Err = Error;
278
279    fn from_str(s: &str) -> Result<Self> {
280        if s.eq_ignore_ascii_case("music") {
281            Ok(PublicAudioDir::Music)
282        } 
283        else if s.eq_ignore_ascii_case("alarms") {
284            Ok(PublicAudioDir::Alarms)
285        }
286        else if s.eq_ignore_ascii_case("audiobooks") {
287            Ok(PublicAudioDir::Audiobooks)
288        }
289        else if s.eq_ignore_ascii_case("notifications") {
290            Ok(PublicAudioDir::Notifications)
291        } 
292        else if s.eq_ignore_ascii_case("podcasts") {
293            Ok(PublicAudioDir::Podcasts)
294        } 
295        else if s.eq_ignore_ascii_case("ringtones") {
296            Ok(PublicAudioDir::Ringtones)
297        } 
298        else if s.eq_ignore_ascii_case("recordings") {
299            Ok(PublicAudioDir::Recordings)
300        } 
301        else {
302            Err(Error::with(format!("invalid PublicAudioDir: {s}")))
303        }
304    }
305}
306
307impl FromStr for PublicGeneralPurposeDir {
308    type Err = Error;
309
310    fn from_str(s: &str) -> Result<Self> {
311        if s.eq_ignore_ascii_case("documents") {
312            Ok(PublicGeneralPurposeDir::Documents)
313        }
314        else if s.eq_ignore_ascii_case("download") {
315            Ok(PublicGeneralPurposeDir::Download)
316        } 
317        else if s.eq_ignore_ascii_case("downloads") {
318            Ok(PublicGeneralPurposeDir::Download)
319        } 
320        else {
321            Err(Error::with(format!("invalid PublicGeneralPurposeDir: {s}")))
322        }
323    }
324}
325
326impl FromStr for PublicDir {
327    type Err = Error;
328
329    fn from_str(s: &str) -> Result<Self> {
330        if let Ok(v) = PublicImageDir::from_str(s) {
331            Ok(PublicDir::Image(v))
332        }
333        else if let Ok(v) = PublicVideoDir::from_str(s) {
334            Ok(PublicDir::Video(v))
335        }
336        else if let Ok(v) = PublicAudioDir::from_str(s) {
337            Ok(PublicDir::Audio(v))
338        }
339        else if let Ok(v) = PublicGeneralPurposeDir::from_str(s) {
340            Ok(PublicDir::GeneralPurpose(v))
341        }
342        else {
343            Err(Error::with(format!("invalid PublicDir: {s}")))
344        }
345    }
346}