Share public link in ShareFileFragment
[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.shares.ShareType;
43 import com.owncloud.android.lib.resources.status.OwnCloudVersion;
44 import com.owncloud.android.services.OperationsService;
45 import com.owncloud.android.services.observer.FileObserverService;
46 import com.owncloud.android.ui.activity.FileActivity;
47 import com.owncloud.android.ui.activity.ShareActivity;
48 import com.owncloud.android.ui.dialog.ShareLinkToDialog;
49
50 import org.apache.http.protocol.HTTP;
51
52 import java.util.List;
53
54 /**
55 *
56 */
57 public class FileOperationsHelper {
58
59 private static final String TAG = FileOperationsHelper.class.getName();
60
61 private static final String FTAG_CHOOSER_DIALOG = "CHOOSER_DIALOG";
62
63 protected FileActivity mFileActivity = null;
64
65 /// Identifier of operation in progress which result shouldn't be lost
66 private long mWaitingForOpId = Long.MAX_VALUE;
67
68 public FileOperationsHelper(FileActivity fileActivity) {
69 mFileActivity = fileActivity;
70 }
71
72
73 public void openFile(OCFile file) {
74 if (file != null) {
75 String storagePath = file.getStoragePath();
76 String encodedStoragePath = WebdavUtils.encodePath(storagePath);
77
78 Intent intentForSavedMimeType = new Intent(Intent.ACTION_VIEW);
79 intentForSavedMimeType.setDataAndType(Uri.parse("file://"+ encodedStoragePath),
80 file.getMimetype());
81 intentForSavedMimeType.setFlags(
82 Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
83 );
84
85 Intent intentForGuessedMimeType = null;
86 if (storagePath.lastIndexOf('.') >= 0) {
87 String guessedMimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(
88 storagePath.substring(storagePath.lastIndexOf('.') + 1)
89 );
90 if (guessedMimeType != null && !guessedMimeType.equals(file.getMimetype())) {
91 intentForGuessedMimeType = new Intent(Intent.ACTION_VIEW);
92 intentForGuessedMimeType.
93 setDataAndType(Uri.parse("file://"+ encodedStoragePath),
94 guessedMimeType);
95 intentForGuessedMimeType.setFlags(
96 Intent.FLAG_GRANT_READ_URI_PERMISSION |
97 Intent.FLAG_GRANT_WRITE_URI_PERMISSION
98 );
99 }
100 }
101
102 Intent openFileWithIntent;
103 if (intentForGuessedMimeType != null) {
104 openFileWithIntent = intentForGuessedMimeType;
105 } else {
106 openFileWithIntent = intentForSavedMimeType;
107 }
108
109 List<ResolveInfo> launchables = mFileActivity.getPackageManager().
110 queryIntentActivities(openFileWithIntent, PackageManager.GET_INTENT_FILTERS);
111
112 if(launchables != null && launchables.size() > 0) {
113 try {
114 mFileActivity.startActivity(
115 Intent.createChooser(
116 openFileWithIntent, mFileActivity.getString(R.string.actionbar_open_with)
117 )
118 );
119 } catch (ActivityNotFoundException anfe) {
120 showNoAppForFileTypeToast(mFileActivity.getApplicationContext());
121 }
122 } else {
123 showNoAppForFileTypeToast(mFileActivity.getApplicationContext());
124 }
125
126 } else {
127 Log_OC.wtf(TAG, "Trying to open a NULL OCFile");
128 }
129 }
130
131 /**
132 * Displays a toast stating that no application could be found to open the file.
133 *
134 * @param context the context to be able to show a toast.
135 */
136 private void showNoAppForFileTypeToast(Context context) {
137 Toast.makeText(context,
138 R.string.file_list_no_app_for_file_type, Toast.LENGTH_SHORT)
139 .show();
140 }
141
142
143 /**
144 /**
145 * Helper method to share a file via a public link. Starts a request to do it in {@link OperationsService}
146 *
147 * @param file The file to share.
148 */
149 public void shareFileViaLink(OCFile file) {
150 if (isSharedSupported()) {
151 if (file != null) {
152 mFileActivity.showLoadingDialog(
153 mFileActivity.getApplicationContext().
154 getString(R.string.wait_a_moment)
155 );
156 Intent service = new Intent(mFileActivity, OperationsService.class);
157 service.setAction(OperationsService.ACTION_CREATE_SHARE_VIA_LINK);
158 service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
159 service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
160 mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
161
162 } else {
163 Log_OC.wtf(TAG, "Trying to share a NULL OCFile");
164 // TODO user-level error?
165 }
166
167 } else {
168 // Show a Message
169 Toast t = Toast.makeText(
170 mFileActivity, mFileActivity.getString(R.string.share_link_no_support_share_api),
171 Toast.LENGTH_LONG
172 );
173 t.show();
174 }
175 }
176
177
178 public void shareFileWithLinkOLD(OCFile file) {
179
180 if (isSharedSupported()) {
181 if (file != null) {
182 String link = "https://fake.url";
183 Intent intent = createShareWithLinkIntent(link);
184 String[] packagesToExclude = new String[]{mFileActivity.getPackageName()};
185 DialogFragment chooserDialog = ShareLinkToDialog.newInstance(intent,
186 packagesToExclude, file);
187 chooserDialog.show(mFileActivity.getSupportFragmentManager(), FTAG_CHOOSER_DIALOG);
188
189 } else {
190 Log_OC.wtf(TAG, "Trying to share a NULL OCFile");
191 }
192
193 } else {
194 // Show a Message
195 Toast t = Toast.makeText(
196 mFileActivity, mFileActivity.getString(R.string.share_link_no_support_share_api),
197 Toast.LENGTH_LONG
198 );
199 t.show();
200 }
201 }
202
203
204 public void shareFileWithLinkToApp(OCFile file, String password, Intent sendIntent) {
205
206 if (file != null) {
207 mFileActivity.showLoadingDialog(mFileActivity.getApplicationContext().
208 getString(R.string.wait_a_moment));
209
210 Intent service = new Intent(mFileActivity, OperationsService.class);
211 service.setAction(OperationsService.ACTION_CREATE_SHARE_VIA_LINK);
212 service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
213 service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
214 service.putExtra(OperationsService.EXTRA_PASSWORD_SHARE, password);
215 service.putExtra(OperationsService.EXTRA_SEND_INTENT, sendIntent);
216 mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
217
218 } else {
219 Log_OC.wtf(TAG, "Trying to open a NULL OCFile");
220 }
221 }
222
223
224 private Intent createShareWithLinkIntent(String link) {
225 Intent intentToShareLink = new Intent(Intent.ACTION_SEND);
226 intentToShareLink.putExtra(Intent.EXTRA_TEXT, link);
227 intentToShareLink.setType(HTTP.PLAIN_TEXT_TYPE);
228 return intentToShareLink;
229 }
230
231
232 /**
233 * Helper method to share a file with a known sharee. Starts a request to do it in {@link OperationsService}
234 *
235 * @param file The file to share.
236 * @param shareeName Name (user name or group name) of the target sharee.
237 * @param shareType The share type determines the sharee type.
238 */
239 public void shareFileWithSharee(OCFile file, String shareeName, ShareType shareType) {
240 if (file != null) {
241 // TODO check capability?
242 mFileActivity.showLoadingDialog(mFileActivity.getApplicationContext().
243 getString(R.string.wait_a_moment));
244
245 Intent service = new Intent(mFileActivity, OperationsService.class);
246 service.setAction(OperationsService.ACTION_CREATE_SHARE_WITH_SHAREE);
247 service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
248 service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
249 service.putExtra(OperationsService.EXTRA_SHARE_WITH, shareeName);
250 service.putExtra(OperationsService.EXTRA_SHARE_TYPE, shareType);
251 mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
252
253 } else {
254 Log_OC.wtf(TAG, "Trying to share a NULL OCFile");
255 }
256 }
257
258
259 /**
260 * @return 'True' if the server supports the Share API
261 */
262 public boolean isSharedSupported() {
263 if (mFileActivity.getAccount() != null) {
264 OwnCloudVersion serverVersion = AccountUtils.getServerVersion(mFileActivity.getAccount());
265 return (serverVersion != null && serverVersion.isSharedSupported());
266 }
267 return false;
268 }
269
270
271 public void unshareFileWithLink(OCFile file) {
272
273 // Unshare the file: Create the intent
274 Intent unshareService = new Intent(mFileActivity, OperationsService.class);
275 unshareService.setAction(OperationsService.ACTION_UNSHARE);
276 unshareService.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
277 unshareService.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
278 unshareService.putExtra(OperationsService.EXTRA_SHARE_TYPE, ShareType.PUBLIC_LINK);
279 unshareService.putExtra(OperationsService.EXTRA_SHARE_WITH, "");
280
281 unshareFile(unshareService);
282 }
283
284 public void unshareFileWithUserOrGroup(OCFile file, ShareType shareType, String userOrGroup){
285
286 // Unshare the file: Create the intent
287 Intent unshareService = new Intent(mFileActivity, OperationsService.class);
288 unshareService.setAction(OperationsService.ACTION_UNSHARE);
289 unshareService.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
290 unshareService.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
291 unshareService.putExtra(OperationsService.EXTRA_SHARE_TYPE, shareType);
292 unshareService.putExtra(OperationsService.EXTRA_SHARE_WITH, userOrGroup);
293
294 unshareFile(unshareService);
295 }
296
297
298 private void unshareFile(Intent unshareService){
299 if (isSharedSupported()) {
300 // Unshare the file
301 mWaitingForOpId = mFileActivity.getOperationsServiceBinder().
302 queueNewOperation(unshareService);
303
304 mFileActivity.showLoadingDialog(mFileActivity.getApplicationContext().
305 getString(R.string.wait_a_moment));
306
307 } else {
308 // Show a Message
309 Toast t = Toast.makeText(mFileActivity,
310 mFileActivity.getString(R.string.share_link_no_support_share_api),
311 Toast.LENGTH_LONG);
312 t.show();
313
314 }
315 }
316
317 /**
318 * Show an instance of {@link ShareType} for sharing or unsharing the {@OCFile} received as parameter.
319 *
320 * @param file File to share or unshare.
321 */
322 public void showShareFile(OCFile file){
323 Intent intent = new Intent(mFileActivity, ShareActivity.class);
324 intent.putExtra(mFileActivity.EXTRA_FILE, file);
325 intent.putExtra(mFileActivity.EXTRA_ACCOUNT, mFileActivity.getAccount());
326 mFileActivity.startActivity(intent);
327
328 }
329
330
331 /**
332 * @return 'True' if the server supports the Search Users API
333 */
334 public boolean isSearchUsersSupportedSupported() {
335 if (mFileActivity.getAccount() != null) {
336 OwnCloudVersion serverVersion = AccountUtils.getServerVersion(mFileActivity.getAccount());
337 return (serverVersion != null && serverVersion.isSearchUsersSupported());
338 }
339 return false;
340 }
341
342 public void sendDownloadedFile(OCFile file) {
343 if (file != null) {
344 String storagePath = file.getStoragePath();
345 String encodedStoragePath = WebdavUtils.encodePath(storagePath);
346 Intent sendIntent = new Intent(android.content.Intent.ACTION_SEND);
347 // set MimeType
348 sendIntent.setType(file.getMimetype());
349 sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + encodedStoragePath));
350 sendIntent.putExtra(Intent.ACTION_SEND, true); // Send Action
351
352 // Show dialog, without the own app
353 String[] packagesToExclude = new String[]{mFileActivity.getPackageName()};
354 DialogFragment chooserDialog = ShareLinkToDialog.newInstance(sendIntent,
355 packagesToExclude, file);
356 chooserDialog.show(mFileActivity.getSupportFragmentManager(), FTAG_CHOOSER_DIALOG);
357
358 } else {
359 Log_OC.wtf(TAG, "Trying to send a NULL OCFile");
360 }
361 }
362
363 /**
364 * Request the synchronization of a file or folder with the OC server, including its contents.
365 *
366 * @param file The file or folder to synchronize
367 */
368 public void syncFile(OCFile file) {
369 if (!file.isFolder()){
370 Intent intent = new Intent(mFileActivity, OperationsService.class);
371 intent.setAction(OperationsService.ACTION_SYNC_FILE);
372 intent.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
373 intent.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
374 intent.putExtra(OperationsService.EXTRA_SYNC_FILE_CONTENTS, true);
375 mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(intent);
376 mFileActivity.showLoadingDialog(mFileActivity.getApplicationContext().
377 getString(R.string.wait_a_moment));
378
379 } else {
380 Intent intent = new Intent(mFileActivity, OperationsService.class);
381 intent.setAction(OperationsService.ACTION_SYNC_FOLDER);
382 intent.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
383 intent.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
384 mFileActivity.startService(intent);
385
386 }
387 }
388
389 public void toggleFavorite(OCFile file, boolean isFavorite) {
390 file.setFavorite(isFavorite);
391 mFileActivity.getStorageManager().saveFile(file);
392
393 /// register the OCFile instance in the observer service to monitor local updates
394 Intent observedFileIntent = FileObserverService.makeObservedFileIntent(
395 mFileActivity,
396 file,
397 mFileActivity.getAccount(),
398 isFavorite);
399 mFileActivity.startService(observedFileIntent);
400
401 /// immediate content synchronization
402 if (file.isFavorite()) {
403 syncFile(file);
404 }
405 }
406
407 public void renameFile(OCFile file, String newFilename) {
408 // RenameFile
409 Intent service = new Intent(mFileActivity, OperationsService.class);
410 service.setAction(OperationsService.ACTION_RENAME);
411 service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
412 service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
413 service.putExtra(OperationsService.EXTRA_NEWNAME, newFilename);
414 mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
415
416 mFileActivity.showLoadingDialog(mFileActivity.getApplicationContext().
417 getString(R.string.wait_a_moment));
418 }
419
420
421 public void removeFile(OCFile file, boolean onlyLocalCopy) {
422 // RemoveFile
423 Intent service = new Intent(mFileActivity, OperationsService.class);
424 service.setAction(OperationsService.ACTION_REMOVE);
425 service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
426 service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
427 service.putExtra(OperationsService.EXTRA_REMOVE_ONLY_LOCAL, onlyLocalCopy);
428 mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
429
430 mFileActivity.showLoadingDialog(mFileActivity.getApplicationContext().
431 getString(R.string.wait_a_moment));
432 }
433
434
435 public void createFolder(String remotePath, boolean createFullPath) {
436 // Create Folder
437 Intent service = new Intent(mFileActivity, OperationsService.class);
438 service.setAction(OperationsService.ACTION_CREATE_FOLDER);
439 service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
440 service.putExtra(OperationsService.EXTRA_REMOTE_PATH, remotePath);
441 service.putExtra(OperationsService.EXTRA_CREATE_FULL_PATH, createFullPath);
442 mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
443
444 mFileActivity.showLoadingDialog(mFileActivity.getApplicationContext().
445 getString(R.string.wait_a_moment));
446 }
447
448 /**
449 * Cancel the transference in downloads (files/folders) and file uploads
450 * @param file OCFile
451 */
452 public void cancelTransference(OCFile file) {
453 Account account = mFileActivity.getAccount();
454 if (file.isFolder()) {
455 OperationsService.OperationsServiceBinder opsBinder =
456 mFileActivity.getOperationsServiceBinder();
457 if (opsBinder != null) {
458 opsBinder.cancel(account, file);
459 }
460 }
461
462 // for both files and folders
463 FileDownloaderBinder downloaderBinder = mFileActivity.getFileDownloaderBinder();
464 if (downloaderBinder != null && downloaderBinder.isDownloading(account, file)) {
465 downloaderBinder.cancel(account, file);
466 }
467 FileUploaderBinder uploaderBinder = mFileActivity.getFileUploaderBinder();
468 if (uploaderBinder != null && uploaderBinder.isUploading(account, file)) {
469 uploaderBinder.cancel(account, file);
470 }
471 }
472
473 /**
474 * Start move file operation
475 *
476 * @param newfile File where it is going to be moved
477 * @param currentFile File with the previous info
478 */
479 public void moveFile(OCFile newfile, OCFile currentFile) {
480 // Move files
481 Intent service = new Intent(mFileActivity, OperationsService.class);
482 service.setAction(OperationsService.ACTION_MOVE_FILE);
483 service.putExtra(OperationsService.EXTRA_NEW_PARENT_PATH, newfile.getRemotePath());
484 service.putExtra(OperationsService.EXTRA_REMOTE_PATH, currentFile.getRemotePath());
485 service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
486 mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
487
488 mFileActivity.showLoadingDialog(mFileActivity.getApplicationContext().
489 getString(R.string.wait_a_moment));
490 }
491
492 /**
493 * Start copy file operation
494 *
495 * @param newfile File where it is going to be moved
496 * @param currentFile File with the previous info
497 */
498 public void copyFile(OCFile newfile, OCFile currentFile) {
499 // Copy files
500 Intent service = new Intent(mFileActivity, OperationsService.class);
501 service.setAction(OperationsService.ACTION_COPY_FILE);
502 service.putExtra(OperationsService.EXTRA_NEW_PARENT_PATH, newfile.getRemotePath());
503 service.putExtra(OperationsService.EXTRA_REMOTE_PATH, currentFile.getRemotePath());
504 service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
505 mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
506
507 mFileActivity.showLoadingDialog(mFileActivity.getApplicationContext().
508 getString(R.string.wait_a_moment));
509 }
510
511 public long getOpIdWaitingFor() {
512 return mWaitingForOpId;
513 }
514
515
516 public void setOpIdWaitingFor(long waitingForOpId) {
517 mWaitingForOpId = waitingForOpId;
518 }
519
520 /**
521 * @return 'True' if the server doesn't need to check forbidden characters
522 */
523 public boolean isVersionWithForbiddenCharacters() {
524 if (mFileActivity.getAccount() != null) {
525 OwnCloudVersion serverVersion =
526 AccountUtils.getServerVersion(mFileActivity.getAccount());
527 return (serverVersion != null && serverVersion.isVersionWithForbiddenCharacters());
528 }
529 return false;
530 }
531
532 }