FileOperationsHelper.java 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  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. package com.owncloud.android.files;
  22. import android.accounts.Account;
  23. import android.content.ActivityNotFoundException;
  24. import android.content.Intent;
  25. import android.content.pm.PackageManager;
  26. import android.content.pm.ResolveInfo;
  27. import android.net.Uri;
  28. import android.support.v4.app.DialogFragment;
  29. import android.webkit.MimeTypeMap;
  30. import android.widget.Toast;
  31. import com.owncloud.android.R;
  32. import com.owncloud.android.authentication.AccountUtils;
  33. import com.owncloud.android.datamodel.OCFile;
  34. import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
  35. import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
  36. import com.owncloud.android.lib.common.network.WebdavUtils;
  37. import com.owncloud.android.lib.common.utils.Log_OC;
  38. import com.owncloud.android.lib.resources.status.OwnCloudVersion;
  39. import com.owncloud.android.services.OperationsService;
  40. import com.owncloud.android.services.observer.FileObserverService;
  41. import com.owncloud.android.ui.activity.FileActivity;
  42. import com.owncloud.android.ui.dialog.ShareLinkToDialog;
  43. import org.apache.http.protocol.HTTP;
  44. import java.util.List;
  45. /**
  46. *
  47. */
  48. public class FileOperationsHelper {
  49. private static final String TAG = FileOperationsHelper.class.getName();
  50. private static final String FTAG_CHOOSER_DIALOG = "CHOOSER_DIALOG";
  51. protected FileActivity mFileActivity = null;
  52. /// Identifier of operation in progress which result shouldn't be lost
  53. private long mWaitingForOpId = Long.MAX_VALUE;
  54. public FileOperationsHelper(FileActivity fileActivity) {
  55. mFileActivity = fileActivity;
  56. }
  57. public void openFile(OCFile file) {
  58. if (file != null) {
  59. String storagePath = file.getStoragePath();
  60. String encodedStoragePath = WebdavUtils.encodePath(storagePath);
  61. Intent intentForSavedMimeType = new Intent(Intent.ACTION_VIEW);
  62. intentForSavedMimeType.setDataAndType(Uri.parse("file://"+ encodedStoragePath), file.getMimetype());
  63. intentForSavedMimeType.setFlags(
  64. Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
  65. );
  66. Intent intentForGuessedMimeType = null;
  67. if (storagePath.lastIndexOf('.') >= 0) {
  68. String guessedMimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(
  69. storagePath.substring(storagePath.lastIndexOf('.') + 1)
  70. );
  71. if (guessedMimeType != null && !guessedMimeType.equals(file.getMimetype())) {
  72. intentForGuessedMimeType = new Intent(Intent.ACTION_VIEW);
  73. intentForGuessedMimeType.setDataAndType(Uri.parse("file://"+ encodedStoragePath), guessedMimeType);
  74. intentForGuessedMimeType.setFlags(
  75. Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
  76. );
  77. }
  78. }
  79. Intent chooserIntent;
  80. List<ResolveInfo> launchables;
  81. if (intentForGuessedMimeType != null) {
  82. chooserIntent = Intent.createChooser(intentForGuessedMimeType, mFileActivity.getString(R.string.actionbar_open_with));
  83. launchables = mFileActivity.getPackageManager().queryIntentActivities(intentForGuessedMimeType, PackageManager.GET_INTENT_FILTERS);
  84. } else {
  85. chooserIntent = Intent.createChooser(intentForSavedMimeType, mFileActivity.getString(R.string.actionbar_open_with));
  86. launchables = mFileActivity.getPackageManager().queryIntentActivities(intentForSavedMimeType, PackageManager.GET_INTENT_FILTERS);
  87. }
  88. if(launchables != null && launchables.size() > 0) {
  89. try {
  90. mFileActivity.startActivity(chooserIntent);
  91. } catch (ActivityNotFoundException anfe) {
  92. Toast.makeText(mFileActivity.getApplicationContext(),
  93. R.string.file_list_no_app_for_file_type, Toast.LENGTH_SHORT)
  94. .show();
  95. }
  96. } else {
  97. Toast.makeText(mFileActivity.getApplicationContext(),
  98. R.string.file_list_no_app_for_file_type, Toast.LENGTH_SHORT)
  99. .show();
  100. }
  101. } else {
  102. Log_OC.wtf(TAG, "Trying to open a NULL OCFile");
  103. }
  104. }
  105. public void shareFileWithLink(OCFile file) {
  106. if (isSharedSupported()) {
  107. if (file != null) {
  108. String link = "https://fake.url";
  109. Intent intent = createShareWithLinkIntent(link);
  110. String[] packagesToExclude = new String[]{mFileActivity.getPackageName()};
  111. DialogFragment chooserDialog = ShareLinkToDialog.newInstance(intent, packagesToExclude, file);
  112. chooserDialog.show(mFileActivity.getSupportFragmentManager(), FTAG_CHOOSER_DIALOG);
  113. } else {
  114. Log_OC.wtf(TAG, "Trying to share a NULL OCFile");
  115. }
  116. } else {
  117. // Show a Message
  118. Toast t = Toast.makeText(
  119. mFileActivity, mFileActivity.getString(R.string.share_link_no_support_share_api), Toast.LENGTH_LONG
  120. );
  121. t.show();
  122. }
  123. }
  124. public void shareFileWithLinkToApp(OCFile file, String password, Intent sendIntent) {
  125. if (file != null) {
  126. mFileActivity.showLoadingDialog();
  127. Intent service = new Intent(mFileActivity, OperationsService.class);
  128. service.setAction(OperationsService.ACTION_CREATE_SHARE);
  129. service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
  130. service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
  131. service.putExtra(OperationsService.EXTRA_PASSWORD_SHARE, password);
  132. service.putExtra(OperationsService.EXTRA_SEND_INTENT, sendIntent);
  133. mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
  134. } else {
  135. Log_OC.wtf(TAG, "Trying to open a NULL OCFile");
  136. }
  137. }
  138. private Intent createShareWithLinkIntent(String link) {
  139. Intent intentToShareLink = new Intent(Intent.ACTION_SEND);
  140. intentToShareLink.putExtra(Intent.EXTRA_TEXT, link);
  141. intentToShareLink.setType(HTTP.PLAIN_TEXT_TYPE);
  142. return intentToShareLink;
  143. }
  144. /**
  145. * @return 'True' if the server supports the Share API
  146. */
  147. public boolean isSharedSupported() {
  148. if (mFileActivity.getAccount() != null) {
  149. OwnCloudVersion serverVersion = AccountUtils.getServerVersion(mFileActivity.getAccount());
  150. return (serverVersion != null && serverVersion.isSharedSupported());
  151. }
  152. return false;
  153. }
  154. public void unshareFileWithLink(OCFile file) {
  155. if (isSharedSupported()) {
  156. // Unshare the file
  157. Intent service = new Intent(mFileActivity, OperationsService.class);
  158. service.setAction(OperationsService.ACTION_UNSHARE);
  159. service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
  160. service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
  161. mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
  162. mFileActivity.showLoadingDialog();
  163. } else {
  164. // Show a Message
  165. Toast t = Toast.makeText(mFileActivity, mFileActivity.getString(R.string.share_link_no_support_share_api), Toast.LENGTH_LONG);
  166. t.show();
  167. }
  168. }
  169. public void sendDownloadedFile(OCFile file) {
  170. if (file != null) {
  171. String storagePath = file.getStoragePath();
  172. String encodedStoragePath = WebdavUtils.encodePath(storagePath);
  173. Intent sendIntent = new Intent(android.content.Intent.ACTION_SEND);
  174. // set MimeType
  175. sendIntent.setType(file.getMimetype());
  176. sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + encodedStoragePath));
  177. sendIntent.putExtra(Intent.ACTION_SEND, true); // Send Action
  178. // Show dialog, without the own app
  179. String[] packagesToExclude = new String[]{mFileActivity.getPackageName()};
  180. DialogFragment chooserDialog = ShareLinkToDialog.newInstance(sendIntent, packagesToExclude, file);
  181. chooserDialog.show(mFileActivity.getSupportFragmentManager(), FTAG_CHOOSER_DIALOG);
  182. } else {
  183. Log_OC.wtf(TAG, "Trying to send a NULL OCFile");
  184. }
  185. }
  186. public void syncFile(OCFile file) {
  187. if (!file.isFolder()){
  188. Intent intent = new Intent(mFileActivity, OperationsService.class);
  189. intent.setAction(OperationsService.ACTION_SYNC_FILE);
  190. intent.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
  191. intent.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
  192. intent.putExtra(OperationsService.EXTRA_SYNC_FILE_CONTENTS, true);
  193. mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(intent);
  194. mFileActivity.showLoadingDialog();
  195. } else {
  196. Intent intent = new Intent(mFileActivity, OperationsService.class);
  197. intent.setAction(OperationsService.ACTION_SYNC_FOLDER);
  198. intent.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
  199. intent.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
  200. mFileActivity.startService(intent);
  201. }
  202. }
  203. public void toggleFavorite(OCFile file, boolean isFavorite) {
  204. file.setFavorite(isFavorite);
  205. mFileActivity.getStorageManager().saveFile(file);
  206. /// register the OCFile instance in the observer service to monitor local updates
  207. Intent observedFileIntent = FileObserverService.makeObservedFileIntent(
  208. mFileActivity,
  209. file,
  210. mFileActivity.getAccount(),
  211. isFavorite);
  212. mFileActivity.startService(observedFileIntent);
  213. /// immediate content synchronization
  214. if (file.isFavorite()) {
  215. syncFile(file);
  216. }
  217. }
  218. public void renameFile(OCFile file, String newFilename) {
  219. // RenameFile
  220. Intent service = new Intent(mFileActivity, OperationsService.class);
  221. service.setAction(OperationsService.ACTION_RENAME);
  222. service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
  223. service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
  224. service.putExtra(OperationsService.EXTRA_NEWNAME, newFilename);
  225. mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
  226. mFileActivity.showLoadingDialog();
  227. }
  228. public void removeFile(OCFile file, boolean onlyLocalCopy) {
  229. // RemoveFile
  230. Intent service = new Intent(mFileActivity, OperationsService.class);
  231. service.setAction(OperationsService.ACTION_REMOVE);
  232. service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
  233. service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
  234. service.putExtra(OperationsService.EXTRA_REMOVE_ONLY_LOCAL, onlyLocalCopy);
  235. mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
  236. mFileActivity.showLoadingDialog();
  237. }
  238. public void createFolder(String remotePath, boolean createFullPath) {
  239. // Create Folder
  240. Intent service = new Intent(mFileActivity, OperationsService.class);
  241. service.setAction(OperationsService.ACTION_CREATE_FOLDER);
  242. service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
  243. service.putExtra(OperationsService.EXTRA_REMOTE_PATH, remotePath);
  244. service.putExtra(OperationsService.EXTRA_CREATE_FULL_PATH, createFullPath);
  245. mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
  246. mFileActivity.showLoadingDialog();
  247. }
  248. /**
  249. * Cancel the transference in downloads (files/folders) and file uploads
  250. * @param file OCFile
  251. */
  252. public void cancelTransference(OCFile file) {
  253. Account account = mFileActivity.getAccount();
  254. if (file.isFolder()) {
  255. OperationsService.OperationsServiceBinder opsBinder = mFileActivity.getOperationsServiceBinder();
  256. if (opsBinder != null) {
  257. opsBinder.cancel(account, file);
  258. }
  259. }
  260. // for both files and folders
  261. FileDownloaderBinder downloaderBinder = mFileActivity.getFileDownloaderBinder();
  262. FileUploaderBinder uploaderBinder = mFileActivity.getFileUploaderBinder();
  263. if (downloaderBinder != null && downloaderBinder.isDownloading(account, file)) {
  264. downloaderBinder.cancel(account, file);
  265. // TODO - review why is this here, and solve in a better way
  266. // Remove etag for parent, if file is a favorite
  267. if (file.isFavorite()) {
  268. OCFile parent = mFileActivity.getStorageManager().getFileById(file.getParentId());
  269. parent.setEtag("");
  270. mFileActivity.getStorageManager().saveFile(parent);
  271. }
  272. } else if (uploaderBinder != null && uploaderBinder.isUploading(account, file)) {
  273. uploaderBinder.cancel(account, file);
  274. }
  275. }
  276. /**
  277. * Start move file operation
  278. *
  279. * @param newfile File where it is going to be moved
  280. * @param currentFile File with the previous info
  281. */
  282. public void moveFile(OCFile newfile, OCFile currentFile) {
  283. // Move files
  284. Intent service = new Intent(mFileActivity, OperationsService.class);
  285. service.setAction(OperationsService.ACTION_MOVE_FILE);
  286. service.putExtra(OperationsService.EXTRA_NEW_PARENT_PATH, newfile.getRemotePath());
  287. service.putExtra(OperationsService.EXTRA_REMOTE_PATH, currentFile.getRemotePath());
  288. service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
  289. mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
  290. mFileActivity.showLoadingDialog();
  291. }
  292. /**
  293. * Start copy file operation
  294. *
  295. * @param newfile File where it is going to be moved
  296. * @param currentFile File with the previous info
  297. */
  298. public void copyFile(OCFile newfile, OCFile currentFile) {
  299. // Copy files
  300. Intent service = new Intent(mFileActivity, OperationsService.class);
  301. service.setAction(OperationsService.ACTION_COPY_FILE);
  302. service.putExtra(OperationsService.EXTRA_NEW_PARENT_PATH, newfile.getRemotePath());
  303. service.putExtra(OperationsService.EXTRA_REMOTE_PATH, currentFile.getRemotePath());
  304. service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
  305. mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
  306. mFileActivity.showLoadingDialog();
  307. }
  308. public long getOpIdWaitingFor() {
  309. return mWaitingForOpId;
  310. }
  311. public void setOpIdWaitingFor(long waitingForOpId) {
  312. mWaitingForOpId = waitingForOpId;
  313. }
  314. /**
  315. * @return 'True' if the server doesn't need to check forbidden characters
  316. */
  317. public boolean isVersionWithForbiddenCharacters() {
  318. if (mFileActivity.getAccount() != null) {
  319. OwnCloudVersion serverVersion = AccountUtils.getServerVersion(mFileActivity.getAccount());
  320. return (serverVersion != null && serverVersion.isVersionWithForbiddenCharacters());
  321. }
  322. return false;
  323. }
  324. }