FileOperationsHelper.java 19 KB

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