FileOperationsHelper.java 15 KB

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