tauri_plugin_android_fs/api/file_sender.rs
1use crate::*;
2
3
4/// API of sharing files with other apps.
5///
6/// # Examples
7/// ```
8/// fn example(app: &tauri::AppHandle) {
9/// use tauri_plugin_android_fs::AndroidFsExt as _;
10///
11/// let api = app.android_fs();
12/// let file_sender = api.file_sender();
13/// }
14/// ```
15pub struct FileSender<'a, R: tauri::Runtime>(
16 #[allow(unused)]
17 pub(crate) &'a AndroidFs<R>
18);
19
20impl<'a, R: tauri::Runtime> FileSender<'a, R> {
21
22 /// Show app chooser for sharing files with other apps.
23 /// This function returns immediately after requesting to open the app chooser,
24 /// without waiting for the app’s response.
25 ///
26 /// This sends the files as a single unit.
27 /// The available apps depend on the MIME types associated with the files.
28 /// This does not result in an error even if no available apps are found.
29 /// An empty app chooser is displayed.
30 ///
31 /// # Args
32 /// - ***uris*** :
33 /// Target file URIs to share.
34 /// This all needs to be **readable**.
35 /// Files in [`PrivateStorage`] **cannot** be used.
36 ///
37 /// # Support
38 /// All Android version.
39 ///
40 /// # References
41 /// <https://developer.android.com/reference/android/content/Intent#ACTION_SEND_MULTIPLE>
42 /// <https://developer.android.com/reference/android/content/Intent#ACTION_SEND>
43 pub fn share_files<'b>(
44 &self,
45 uris: impl IntoIterator<Item = &'b FileUri>,
46 ) -> crate::Result<()> {
47
48 // もし use_app_chooser と exclude_self_from_app_chooser を関数の引数として公開するなら、
49 // Show app chooser for sharing files with other apps.
50 //. This function returns immediately after requesting to open the app chooser,
51 // を以下に変更した方が説明文としてわかりやすいかもしれない。
52 // Share files with other app that user selected.
53 // This function returns immediately after requesting to share the files,
54
55 on_android!({
56 impl_se!(struct Req<'a> { uris: Vec<&'a FileUri>, common_mime_type: Option<&'a str>, use_app_chooser: bool, exclude_self_from_app_chooser: bool });
57 impl_de!(struct Res;);
58
59 // Decides whether the app chooser dialog is always shown.
60 // The recommended value is true, which ensures the dialog is always displayed.
61 // If set to false, the behavior depends on the user’s previous choice:
62 // if the user has previously selected an app as "ALWAYS" in Android,
63 // that app will be opened directly.
64 // Otherwise, the app list will appear, offering both the "JUST ONCE" and "ALWAYS" options.
65 //
66 // NOTE:
67 // これがfalseの場合も、対応できるアプリがない場合にエラーが発生することはない。
68 // ただ何も起こらないのでユーザー的にはあまり良くない。
69 // trueの場合は空のapp chooserと「対応できるアプリがありません」のようなテキストが表示される。
70 let use_app_chooser = true;
71
72 // Decides whether to exclude this app from the app chooser.
73 // This is effective only if this app is configured to receive [`INTENT.ACTION_SEND_MULTIPLE`](https://developer.android.com/reference/android/content/Intent#ACTION_SEND_MULTIPLE) or [`INTENT.ACTION_SEND`](https://developer.android.com/reference/android/content/Intent#ACTION_SEND).
74 // If set to true, ***use_app_chooser*** must also be true and on Android 7 or later;
75 // otherwise, this setting will be ignored.
76 let exclude_self_from_app_chooser = true;
77
78 // Noneの場合、共有するファイルに設定されているMIME typeを用いる
79 let common_mime_type = None;
80
81 let uris = uris.into_iter().collect::<Vec<_>>();
82
83 self.0.api
84 .run_mobile_plugin::<Res>("shareFiles", Req { uris, common_mime_type, use_app_chooser, exclude_self_from_app_chooser })
85 .map(|_| ())
86 .map_err(Into::into)
87 })
88 }
89
90 /// Show app chooser for sharing file with other apps.
91 /// This function returns immediately after requesting to open the app chooser,
92 /// without waiting for the app’s response.
93 ///
94 /// The available apps depend on the MIME type associated with the file.
95 /// This does not result in an error even if no available apps are found.
96 /// An empty app chooser is displayed.
97 ///
98 /// # Args
99 /// - ***uri*** :
100 /// Target file URI to share.
101 /// Must be **readable**.
102 /// Files in [`PrivateStorage`] **cannot** be used.
103 ///
104 /// # Support
105 /// All Android version.
106 ///
107 /// # References
108 /// <https://developer.android.com/reference/android/content/Intent#ACTION_SEND>
109 pub fn share_file(
110 &self,
111 uri: &FileUri,
112 ) -> crate::Result<()> {
113
114 self.share_files([uri])
115 }
116
117 /// Show app chooser for opening file with other apps.
118 /// This function returns immediately after requesting to open the app chooser,
119 /// without waiting for the app’s response.
120 ///
121 /// The available apps depend on the MIME type associated with the file.
122 /// This does not result in an error even if no available apps are found.
123 /// An empty app chooser is displayed.
124 ///
125 /// # Args
126 /// - ***uri*** :
127 /// Target file URI to view.
128 /// Must be **readable**.
129 /// Files in [`PrivateStorage`] **cannot** be used.
130 ///
131 /// # Support
132 /// All Android version.
133 ///
134 /// # References
135 /// <https://developer.android.com/reference/android/content/Intent#ACTION_VIEW>
136 pub fn open_file(
137 &self,
138 uri: &FileUri,
139 ) -> crate::Result<()> {
140
141 on_android!({
142 impl_se!(struct Req<'a> { uri: &'a FileUri, mime_type: Option<&'a str>, use_app_chooser: bool, exclude_self_from_app_chooser: bool });
143 impl_de!(struct Res;);
144
145 let use_app_chooser = true;
146 let exclude_self_from_app_chooser = true;
147 let mime_type = None;
148
149 self.0.api
150 .run_mobile_plugin::<Res>("viewFile", Req { uri, mime_type, use_app_chooser, exclude_self_from_app_chooser })
151 .map(|_| ())
152 .map_err(Into::into)
153 })
154 }
155
156 /// Show app chooser for editing file with other apps.
157 /// This function returns immediately after requesting to open the app chooser,
158 /// without waiting for the app’s response.
159 ///
160 /// The available apps depend on the MIME type associated with the file.
161 /// This does not result in an error even if no available apps are found.
162 /// An empty app chooser is displayed.
163 ///
164 /// # Note
165 /// I think that this may be the least commonly used request for sending file to app.
166 /// Even if you want to open an image or video editing app,
167 /// [`FileSender::open_file`] allows you to choose from a wider range of apps in many cases.
168 ///
169 /// # Args
170 /// - ***uri*** :
171 /// Target file URI to view.
172 /// Must be **read-writeable**.
173 /// Files in [`PrivateStorage`] **cannot** be used.
174 ///
175 /// # Support
176 /// All Android version.
177 ///
178 /// # References
179 /// <https://developer.android.com/reference/android/content/Intent#ACTION_EDIT>
180 pub fn edit_file(
181 &self,
182 uri: &FileUri,
183 ) -> crate::Result<()> {
184
185 on_android!({
186 impl_se!(struct Req<'a> { uri: &'a FileUri, mime_type: Option<&'a str>, use_app_chooser: bool, exclude_self_from_app_chooser: bool });
187 impl_de!(struct Res;);
188
189 let use_app_chooser = true;
190 let exclude_self_from_app_chooser = true;
191 let mime_type = None;
192
193 self.0.api
194 .run_mobile_plugin::<Res>("editFile", Req { uri, mime_type, use_app_chooser, exclude_self_from_app_chooser })
195 .map(|_| ())
196 .map_err(Into::into)
197 })
198 }
199
200 /// Determines whether the specified files can be used with [`FileSender::share_files`].
201 /// If no app is available to handle the files, this returns false.
202 ///
203 /// # Args
204 /// - ***uris*** :
205 /// Target file URIs to share.
206 /// This all needs to be **readable**.
207 ///
208 /// # Support
209 /// All Android version.
210 #[deprecated = "Since Android 11, This does not function correctly due to android security."]
211 pub fn can_share_files<'b>(
212 &self,
213 uris: impl IntoIterator<Item = &'b FileUri>,
214 ) -> crate::Result<bool> {
215
216 on_android!({
217 impl_se!(struct Req<'a> { uris: Vec<&'a FileUri>, common_mime_type: Option<&'a str> });
218 impl_de!(struct Res { value: bool });
219
220 let common_mime_type = None;
221 let uris = uris.into_iter().collect::<Vec<_>>();
222
223 self.0.api
224 .run_mobile_plugin::<Res>("canShareFiles", Req { uris, common_mime_type })
225 .map(|v| v.value)
226 .map_err(Into::into)
227 })
228 }
229
230 /// Determines whether the specified file can be used with [`FileSender::share_file`].
231 /// If no app is available to handle the file, this returns false.
232 ///
233 /// # Args
234 /// - ***uri*** :
235 /// Target file URI.
236 /// Must be **readable**.
237 ///
238 /// # Support
239 /// All Android version.
240 #[deprecated = "Since Android 11, This does not function correctly due to android security."]
241 pub fn can_share_file(&self, uri: &FileUri) -> crate::Result<bool> {
242 #[allow(deprecated)]
243 self.can_share_files([uri])
244 }
245
246 /// Determines whether the specified file can be used with [`FileSender::open_file`].
247 /// If no app is available to handle the file, this returns false.
248 ///
249 /// # Args
250 /// - ***uri*** :
251 /// Target file URI.
252 /// Must be **readable**.
253 ///
254 /// # Support
255 /// All Android version.
256 #[deprecated = "Since Android 11, This does not function correctly due to android security."]
257 pub fn can_open_file(&self, uri: &FileUri) -> crate::Result<bool> {
258 on_android!({
259 impl_se!(struct Req<'a> { uri: &'a FileUri, mime_type: Option<&'a str> });
260 impl_de!(struct Res { value: bool });
261
262 let mime_type = None;
263
264 self.0.api
265 .run_mobile_plugin::<Res>("canViewFile", Req { uri, mime_type })
266 .map(|v| v.value)
267 .map_err(Into::into)
268 })
269 }
270
271 /// Determines whether the specified file can be used with [`FileSender::edit_file`].
272 /// If no app is available to handle the file, this returns false.
273 ///
274 /// # Args
275 /// - ***uri*** :
276 /// Target file URI.
277 /// Must be **read-writeable**.
278 ///
279 /// # Support
280 /// All Android version.
281 #[deprecated = "Since Android 11, This does not function correctly due to android security."]
282 pub fn can_edit_file(&self, uri: &FileUri) -> crate::Result<bool> {
283 on_android!({
284 impl_se!(struct Req<'a> { uri: &'a FileUri, mime_type: Option<&'a str> });
285 impl_de!(struct Res { value: bool });
286
287 let mime_type = None;
288
289 self.0.api
290 .run_mobile_plugin::<Res>("canEditFile", Req { uri, mime_type })
291 .map(|v| v.value)
292 .map_err(Into::into)
293 })
294 }
295}