wip
[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.setDataAndType(Uri.parse(encodedStoragePath), "image/*");
250 sendIntent.putExtra("jpg", "image/*");
251 // sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + encodedStoragePath));
252 // sendIntent.putExtra("jpg", "image/*");
253
254 mFileActivity.startActivity(Intent.createChooser(sendIntent,
255 mFileActivity.getString(R.string.set_picture_as)));
256 } else {
257 // Intent sendIntent = new Intent(android.content.Intent.ACTION_SEND);
258 // // set MimeType
259 // sendIntent.setType(file.getMimetype());
260 //// sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("content://" + DiskLruImageCacheFileProvider.AUTHORITY + "/#" + file.getRemoteId() + "#" + file.getFileName()));
261 // sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("content://" + DiskLruImageCacheFileProvider.AUTHORITY + file.getRemotePath()));
262 // sendIntent.putExtra(Intent.ACTION_SEND, true); // Send Action
263 //
264 // // Show dialog, without the own app
265 // String[] packagesToExclude = new String[] { mFileActivity.getPackageName() };
266 // DialogFragment chooserDialog = ShareLinkToDialog.newInstance(sendIntent, packagesToExclude, file);
267 // chooserDialog.show(mFileActivity.getSupportFragmentManager(), FTAG_CHOOSER_DIALOG);
268 }
269 } else {
270 Log_OC.wtf(TAG, "Trying to send a NULL OCFile");
271 }
272 }
273
274 /**
275 * Request the synchronization of a file or folder with the OC server, including its contents.
276 *
277 * @param file The file or folder to synchronize
278 */
279 public void syncFile(OCFile file) {
280 if (!file.isFolder()){
281 Intent intent = new Intent(mFileActivity, OperationsService.class);
282 intent.setAction(OperationsService.ACTION_SYNC_FILE);
283 intent.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
284 intent.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
285 intent.putExtra(OperationsService.EXTRA_SYNC_FILE_CONTENTS, true);
286 mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(intent);
287 mFileActivity.showLoadingDialog();
288
289 } else {
290 Intent intent = new Intent(mFileActivity, OperationsService.class);
291 intent.setAction(OperationsService.ACTION_SYNC_FOLDER);
292 intent.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
293 intent.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
294 mFileActivity.startService(intent);
295
296 }
297 }
298
299 public void toggleFavorite(OCFile file, boolean isFavorite) {
300 file.setFavorite(isFavorite);
301 mFileActivity.getStorageManager().saveFile(file);
302
303 /// register the OCFile instance in the observer service to monitor local updates
304 Intent observedFileIntent = FileObserverService.makeObservedFileIntent(
305 mFileActivity,
306 file,
307 mFileActivity.getAccount(),
308 isFavorite);
309 mFileActivity.startService(observedFileIntent);
310
311 /// immediate content synchronization
312 if (file.isFavorite()) {
313 syncFile(file);
314 }
315 }
316
317 public void renameFile(OCFile file, String newFilename) {
318 // RenameFile
319 Intent service = new Intent(mFileActivity, OperationsService.class);
320 service.setAction(OperationsService.ACTION_RENAME);
321 service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
322 service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
323 service.putExtra(OperationsService.EXTRA_NEWNAME, newFilename);
324 mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
325
326 mFileActivity.showLoadingDialog();
327 }
328
329
330 public void removeFile(OCFile file, boolean onlyLocalCopy) {
331 // RemoveFile
332 Intent service = new Intent(mFileActivity, OperationsService.class);
333 service.setAction(OperationsService.ACTION_REMOVE);
334 service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
335 service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
336 service.putExtra(OperationsService.EXTRA_REMOVE_ONLY_LOCAL, onlyLocalCopy);
337 mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
338
339 mFileActivity.showLoadingDialog();
340 }
341
342
343 public void createFolder(String remotePath, boolean createFullPath) {
344 // Create Folder
345 Intent service = new Intent(mFileActivity, OperationsService.class);
346 service.setAction(OperationsService.ACTION_CREATE_FOLDER);
347 service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
348 service.putExtra(OperationsService.EXTRA_REMOTE_PATH, remotePath);
349 service.putExtra(OperationsService.EXTRA_CREATE_FULL_PATH, createFullPath);
350 mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
351
352 mFileActivity.showLoadingDialog();
353 }
354
355 /**
356 * Cancel the transference in downloads (files/folders) and file uploads
357 * @param file OCFile
358 */
359 public void cancelTransference(OCFile file) {
360 Account account = mFileActivity.getAccount();
361 if (file.isFolder()) {
362 OperationsService.OperationsServiceBinder opsBinder = mFileActivity.getOperationsServiceBinder();
363 if (opsBinder != null) {
364 opsBinder.cancel(account, file);
365 }
366 }
367
368 // for both files and folders
369 FileDownloaderBinder downloaderBinder = mFileActivity.getFileDownloaderBinder();
370 if (downloaderBinder != null && downloaderBinder.isDownloading(account, file)) {
371 downloaderBinder.cancel(account, file);
372 }
373 FileUploaderBinder uploaderBinder = mFileActivity.getFileUploaderBinder();
374 if (uploaderBinder != null && uploaderBinder.isUploading(account, file)) {
375 uploaderBinder.cancel(account, file);
376 }
377 }
378
379 /**
380 * Start move file operation
381 *
382 * @param newfile File where it is going to be moved
383 * @param currentFile File with the previous info
384 */
385 public void moveFile(OCFile newfile, OCFile currentFile) {
386 // Move files
387 Intent service = new Intent(mFileActivity, OperationsService.class);
388 service.setAction(OperationsService.ACTION_MOVE_FILE);
389 service.putExtra(OperationsService.EXTRA_NEW_PARENT_PATH, newfile.getRemotePath());
390 service.putExtra(OperationsService.EXTRA_REMOTE_PATH, currentFile.getRemotePath());
391 service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
392 mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
393
394 mFileActivity.showLoadingDialog();
395 }
396
397 /**
398 * Start copy file operation
399 *
400 * @param newfile File where it is going to be moved
401 * @param currentFile File with the previous info
402 */
403 public void copyFile(OCFile newfile, OCFile currentFile) {
404 // Copy files
405 Intent service = new Intent(mFileActivity, OperationsService.class);
406 service.setAction(OperationsService.ACTION_COPY_FILE);
407 service.putExtra(OperationsService.EXTRA_NEW_PARENT_PATH, newfile.getRemotePath());
408 service.putExtra(OperationsService.EXTRA_REMOTE_PATH, currentFile.getRemotePath());
409 service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
410 mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
411
412 mFileActivity.showLoadingDialog();
413 }
414
415 public long getOpIdWaitingFor() {
416 return mWaitingForOpId;
417 }
418
419
420 public void setOpIdWaitingFor(long waitingForOpId) {
421 mWaitingForOpId = waitingForOpId;
422 }
423
424 /**
425 * @return 'True' if the server doesn't need to check forbidden characters
426 */
427 public boolean isVersionWithForbiddenCharacters() {
428 if (mFileActivity.getAccount() != null) {
429 OwnCloudVersion serverVersion = AccountUtils.getServerVersion(mFileActivity.getAccount());
430 return (serverVersion != null && serverVersion.isVersionWithForbiddenCharacters());
431 }
432 return false;
433 }
434 }