9241b6408ae62609d3c566af5a5c7b9b803640eb
[pub/Android/ownCloud.git] / src / com / owncloud / android / files / FileOperationsHelper.java
1 /**
2 * ownCloud Android client application
3 *
4 * @author masensio
5 * @author David A. Velasco
6 * Copyright (C) 2015 ownCloud Inc.
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2,
10 * as published by the Free Software Foundation.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 */
21
22 package com.owncloud.android.files;
23
24 import android.accounts.Account;
25 import android.content.ActivityNotFoundException;
26 import android.content.Context;
27 import android.content.Intent;
28 import android.content.pm.PackageManager;
29 import android.content.pm.ResolveInfo;
30 import android.net.Uri;
31 import android.support.v4.app.DialogFragment;
32 import android.webkit.MimeTypeMap;
33 import android.widget.Toast;
34
35 import com.owncloud.android.R;
36 import com.owncloud.android.authentication.AccountUtils;
37 import com.owncloud.android.datamodel.OCFile;
38 import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
39 import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
40 import com.owncloud.android.lib.common.network.WebdavUtils;
41 import com.owncloud.android.lib.common.utils.Log_OC;
42 import com.owncloud.android.lib.resources.status.OwnCloudVersion;
43 import com.owncloud.android.services.OperationsService;
44 import com.owncloud.android.services.observer.FileObserverService;
45 import com.owncloud.android.ui.activity.FileActivity;
46 import com.owncloud.android.ui.dialog.ShareLinkToDialog;
47
48 import org.apache.http.protocol.HTTP;
49
50 import java.util.List;
51
52 /**
53 *
54 */
55 public class FileOperationsHelper {
56
57 private static final String TAG = FileOperationsHelper.class.getName();
58
59 private static final String FTAG_CHOOSER_DIALOG = "CHOOSER_DIALOG";
60
61 protected FileActivity mFileActivity = null;
62
63 /// Identifier of operation in progress which result shouldn't be lost
64 private long mWaitingForOpId = Long.MAX_VALUE;
65
66 public FileOperationsHelper(FileActivity fileActivity) {
67 mFileActivity = fileActivity;
68 }
69
70
71 public void openFile(OCFile file) {
72 if (file != null) {
73 String storagePath = file.getStoragePath();
74 String encodedStoragePath = WebdavUtils.encodePath(storagePath);
75
76 Intent intentForSavedMimeType = new Intent(Intent.ACTION_VIEW);
77 intentForSavedMimeType.setDataAndType(Uri.parse("file://"+ encodedStoragePath), file.getMimetype());
78 intentForSavedMimeType.setFlags(
79 Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
80 );
81
82 Intent intentForGuessedMimeType = null;
83 if (storagePath.lastIndexOf('.') >= 0) {
84 String guessedMimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(
85 storagePath.substring(storagePath.lastIndexOf('.') + 1)
86 );
87 if (guessedMimeType != null && !guessedMimeType.equals(file.getMimetype())) {
88 intentForGuessedMimeType = new Intent(Intent.ACTION_VIEW);
89 intentForGuessedMimeType.setDataAndType(Uri.parse("file://"+ encodedStoragePath), guessedMimeType);
90 intentForGuessedMimeType.setFlags(
91 Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
92 );
93 }
94 }
95
96 Intent openFileWithIntent;
97 if (intentForGuessedMimeType != null) {
98 openFileWithIntent = intentForGuessedMimeType;
99 } else {
100 openFileWithIntent = intentForSavedMimeType;
101 }
102
103 List<ResolveInfo> launchables = mFileActivity.getPackageManager().
104 queryIntentActivities(openFileWithIntent, PackageManager.GET_INTENT_FILTERS);
105
106 if(launchables != null && launchables.size() > 0) {
107 try {
108 mFileActivity.startActivity(
109 Intent.createChooser(
110 openFileWithIntent, mFileActivity.getString(R.string.actionbar_open_with)
111 )
112 );
113 } catch (ActivityNotFoundException anfe) {
114 showNoAppForFileTypeToast(mFileActivity.getApplicationContext());
115 }
116 } else {
117 showNoAppForFileTypeToast(mFileActivity.getApplicationContext());
118 }
119
120 } else {
121 Log_OC.wtf(TAG, "Trying to open a NULL OCFile");
122 }
123 }
124
125 /**
126 * Displays a toast stating that no application could be found to open the file.
127 *
128 * @param context the context to be able to show a toast.
129 */
130 private void showNoAppForFileTypeToast(Context context) {
131 Toast.makeText(context,
132 R.string.file_list_no_app_for_file_type, Toast.LENGTH_SHORT)
133 .show();
134 }
135
136 public void shareFileWithLink(OCFile file) {
137
138 if (isSharedSupported()) {
139 if (file != null) {
140 String link = "https://fake.url";
141 Intent intent = createShareWithLinkIntent(link);
142 String[] packagesToExclude = new String[]{mFileActivity.getPackageName()};
143 DialogFragment chooserDialog = ShareLinkToDialog.newInstance(intent, packagesToExclude, file);
144 chooserDialog.show(mFileActivity.getSupportFragmentManager(), FTAG_CHOOSER_DIALOG);
145
146 } else {
147 Log_OC.wtf(TAG, "Trying to share a NULL OCFile");
148 }
149
150 } else {
151 // Show a Message
152 Toast t = Toast.makeText(
153 mFileActivity, mFileActivity.getString(R.string.share_link_no_support_share_api), Toast.LENGTH_LONG
154 );
155 t.show();
156 }
157 }
158
159
160 public void shareFileWithLinkToApp(OCFile file, String password, Intent sendIntent) {
161
162 if (file != null) {
163 mFileActivity.showLoadingDialog();
164
165 Intent service = new Intent(mFileActivity, OperationsService.class);
166 service.setAction(OperationsService.ACTION_CREATE_SHARE);
167 service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
168 service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
169 service.putExtra(OperationsService.EXTRA_PASSWORD_SHARE, password);
170 service.putExtra(OperationsService.EXTRA_SEND_INTENT, sendIntent);
171 mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
172
173 } else {
174 Log_OC.wtf(TAG, "Trying to open a NULL OCFile");
175 }
176 }
177
178
179 private Intent createShareWithLinkIntent(String link) {
180 Intent intentToShareLink = new Intent(Intent.ACTION_SEND);
181 intentToShareLink.putExtra(Intent.EXTRA_TEXT, link);
182 intentToShareLink.setType(HTTP.PLAIN_TEXT_TYPE);
183 return intentToShareLink;
184 }
185
186
187 /**
188 * @return 'True' if the server supports the Share API
189 */
190 public boolean isSharedSupported() {
191 if (mFileActivity.getAccount() != null) {
192 OwnCloudVersion serverVersion = AccountUtils.getServerVersion(mFileActivity.getAccount());
193 return (serverVersion != null && serverVersion.isSharedSupported());
194 }
195 return false;
196 }
197
198
199 public void unshareFileWithLink(OCFile file) {
200
201 if (isSharedSupported()) {
202 // Unshare the file
203 Intent service = new Intent(mFileActivity, OperationsService.class);
204 service.setAction(OperationsService.ACTION_UNSHARE);
205 service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
206 service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
207 mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
208
209 mFileActivity.showLoadingDialog();
210
211 } else {
212 // Show a Message
213 Toast t = Toast.makeText(mFileActivity, mFileActivity.getString(R.string.share_link_no_support_share_api), Toast.LENGTH_LONG);
214 t.show();
215
216 }
217 }
218
219 public void sendDownloadedFile(OCFile file) {
220 if (file != null) {
221 String storagePath = file.getStoragePath();
222 String encodedStoragePath = WebdavUtils.encodePath(storagePath);
223 Intent sendIntent = new Intent(android.content.Intent.ACTION_SEND);
224 // set MimeType
225 sendIntent.setType(file.getMimetype());
226 sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + encodedStoragePath));
227 sendIntent.putExtra(Intent.ACTION_SEND, true); // Send Action
228
229 // Show dialog, without the own app
230 String[] packagesToExclude = new String[]{mFileActivity.getPackageName()};
231 DialogFragment chooserDialog = ShareLinkToDialog.newInstance(sendIntent, packagesToExclude, file);
232 chooserDialog.show(mFileActivity.getSupportFragmentManager(), FTAG_CHOOSER_DIALOG);
233
234 } else {
235 Log_OC.wtf(TAG, "Trying to send a NULL OCFile");
236 }
237 }
238
239 public void setPictureAs(OCFile file) {
240 if (file != null) {
241 if (file.isDown()) {
242 String storagePath = file.getStoragePath();
243 String encodedStoragePath = WebdavUtils.encodePath(storagePath);
244 Intent sendIntent = new Intent(Intent.ACTION_ATTACH_DATA);
245 // set MimeType
246 sendIntent.setType(file.getMimetype());
247 // sendIntent.setData(Uri.parse(encodedStoragePath));
248 sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse(encodedStoragePath));
249 // sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + encodedStoragePath));
250 // sendIntent.putExtra("jpg", "image/*");
251
252 mFileActivity.startActivity(Intent.createChooser(sendIntent,
253 mFileActivity.getString(R.string.set_picture_as)));
254 } else {
255 // Intent sendIntent = new Intent(android.content.Intent.ACTION_SEND);
256 // // set MimeType
257 // sendIntent.setType(file.getMimetype());
258 //// sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("content://" + DiskLruImageCacheFileProvider.AUTHORITY + "/#" + file.getRemoteId() + "#" + file.getFileName()));
259 // sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("content://" + DiskLruImageCacheFileProvider.AUTHORITY + file.getRemotePath()));
260 // sendIntent.putExtra(Intent.ACTION_SEND, true); // Send Action
261 //
262 // // Show dialog, without the own app
263 // String[] packagesToExclude = new String[] { mFileActivity.getPackageName() };
264 // DialogFragment chooserDialog = ShareLinkToDialog.newInstance(sendIntent, packagesToExclude, file);
265 // chooserDialog.show(mFileActivity.getSupportFragmentManager(), FTAG_CHOOSER_DIALOG);
266 }
267 } else {
268 Log_OC.wtf(TAG, "Trying to send a NULL OCFile");
269 }
270 }
271
272 /**
273 * Request the synchronization of a file or folder with the OC server, including its contents.
274 *
275 * @param file The file or folder to synchronize
276 */
277 public void syncFile(OCFile file) {
278 if (!file.isFolder()){
279 Intent intent = new Intent(mFileActivity, OperationsService.class);
280 intent.setAction(OperationsService.ACTION_SYNC_FILE);
281 intent.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
282 intent.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
283 intent.putExtra(OperationsService.EXTRA_SYNC_FILE_CONTENTS, true);
284 mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(intent);
285 mFileActivity.showLoadingDialog();
286
287 } else {
288 Intent intent = new Intent(mFileActivity, OperationsService.class);
289 intent.setAction(OperationsService.ACTION_SYNC_FOLDER);
290 intent.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
291 intent.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
292 mFileActivity.startService(intent);
293
294 }
295 }
296
297 public void toggleFavorite(OCFile file, boolean isFavorite) {
298 file.setFavorite(isFavorite);
299 mFileActivity.getStorageManager().saveFile(file);
300
301 /// register the OCFile instance in the observer service to monitor local updates
302 Intent observedFileIntent = FileObserverService.makeObservedFileIntent(
303 mFileActivity,
304 file,
305 mFileActivity.getAccount(),
306 isFavorite);
307 mFileActivity.startService(observedFileIntent);
308
309 /// immediate content synchronization
310 if (file.isFavorite()) {
311 syncFile(file);
312 }
313 }
314
315 public void renameFile(OCFile file, String newFilename) {
316 // RenameFile
317 Intent service = new Intent(mFileActivity, OperationsService.class);
318 service.setAction(OperationsService.ACTION_RENAME);
319 service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
320 service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
321 service.putExtra(OperationsService.EXTRA_NEWNAME, newFilename);
322 mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
323
324 mFileActivity.showLoadingDialog();
325 }
326
327
328 public void removeFile(OCFile file, boolean onlyLocalCopy) {
329 // RemoveFile
330 Intent service = new Intent(mFileActivity, OperationsService.class);
331 service.setAction(OperationsService.ACTION_REMOVE);
332 service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
333 service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
334 service.putExtra(OperationsService.EXTRA_REMOVE_ONLY_LOCAL, onlyLocalCopy);
335 mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
336
337 mFileActivity.showLoadingDialog();
338 }
339
340
341 public void createFolder(String remotePath, boolean createFullPath) {
342 // Create Folder
343 Intent service = new Intent(mFileActivity, OperationsService.class);
344 service.setAction(OperationsService.ACTION_CREATE_FOLDER);
345 service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
346 service.putExtra(OperationsService.EXTRA_REMOTE_PATH, remotePath);
347 service.putExtra(OperationsService.EXTRA_CREATE_FULL_PATH, createFullPath);
348 mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
349
350 mFileActivity.showLoadingDialog();
351 }
352
353 /**
354 * Cancel the transference in downloads (files/folders) and file uploads
355 * @param file OCFile
356 */
357 public void cancelTransference(OCFile file) {
358 Account account = mFileActivity.getAccount();
359 if (file.isFolder()) {
360 OperationsService.OperationsServiceBinder opsBinder = mFileActivity.getOperationsServiceBinder();
361 if (opsBinder != null) {
362 opsBinder.cancel(account, file);
363 }
364 }
365
366 // for both files and folders
367 FileDownloaderBinder downloaderBinder = mFileActivity.getFileDownloaderBinder();
368 if (downloaderBinder != null && downloaderBinder.isDownloading(account, file)) {
369 downloaderBinder.cancel(account, file);
370 }
371 FileUploaderBinder uploaderBinder = mFileActivity.getFileUploaderBinder();
372 if (uploaderBinder != null && uploaderBinder.isUploading(account, file)) {
373 uploaderBinder.cancel(account, file);
374 }
375 }
376
377 /**
378 * Start move file operation
379 *
380 * @param newfile File where it is going to be moved
381 * @param currentFile File with the previous info
382 */
383 public void moveFile(OCFile newfile, OCFile currentFile) {
384 // Move files
385 Intent service = new Intent(mFileActivity, OperationsService.class);
386 service.setAction(OperationsService.ACTION_MOVE_FILE);
387 service.putExtra(OperationsService.EXTRA_NEW_PARENT_PATH, newfile.getRemotePath());
388 service.putExtra(OperationsService.EXTRA_REMOTE_PATH, currentFile.getRemotePath());
389 service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
390 mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
391
392 mFileActivity.showLoadingDialog();
393 }
394
395 /**
396 * Start copy file operation
397 *
398 * @param newfile File where it is going to be moved
399 * @param currentFile File with the previous info
400 */
401 public void copyFile(OCFile newfile, OCFile currentFile) {
402 // Copy files
403 Intent service = new Intent(mFileActivity, OperationsService.class);
404 service.setAction(OperationsService.ACTION_COPY_FILE);
405 service.putExtra(OperationsService.EXTRA_NEW_PARENT_PATH, newfile.getRemotePath());
406 service.putExtra(OperationsService.EXTRA_REMOTE_PATH, currentFile.getRemotePath());
407 service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
408 mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
409
410 mFileActivity.showLoadingDialog();
411 }
412
413 public long getOpIdWaitingFor() {
414 return mWaitingForOpId;
415 }
416
417
418 public void setOpIdWaitingFor(long waitingForOpId) {
419 mWaitingForOpId = waitingForOpId;
420 }
421
422 /**
423 * @return 'True' if the server doesn't need to check forbidden characters
424 */
425 public boolean isVersionWithForbiddenCharacters() {
426 if (mFileActivity.getAccount() != null) {
427 OwnCloudVersion serverVersion = AccountUtils.getServerVersion(mFileActivity.getAccount());
428 return (serverVersion != null && serverVersion.isVersionWithForbiddenCharacters());
429 }
430 return false;
431 }
432 }