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