UriUploader.java 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. /**
  2. * ownCloud Android client application
  3. *
  4. * Copyright (C) 2016 ownCloud Inc.
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2,
  8. * as published by the Free Software Foundation.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. *
  18. */
  19. package com.owncloud.android.ui.helpers;
  20. import android.accounts.Account;
  21. import android.content.ContentResolver;
  22. import android.net.Uri;
  23. import android.os.Parcelable;
  24. import android.support.v4.app.FragmentManager;
  25. import com.owncloud.android.R;
  26. import com.owncloud.android.files.services.FileUploader;
  27. import com.owncloud.android.lib.common.utils.Log_OC;
  28. import com.owncloud.android.operations.UploadFileOperation;
  29. import com.owncloud.android.ui.activity.FileActivity;
  30. import com.owncloud.android.ui.asynctasks.CopyAndUploadContentUrisTask;
  31. import com.owncloud.android.ui.fragment.TaskRetainerFragment;
  32. import com.owncloud.android.utils.DisplayUtils;
  33. import com.owncloud.android.utils.UriUtils;
  34. import java.util.ArrayList;
  35. import java.util.List;
  36. /**
  37. * This class examines URIs pointing to files to upload and then requests {@link FileUploader} to upload them.
  38. *
  39. * URIs with scheme file:// do not require any previous processing, their path is sent to {@link FileUploader}
  40. * to find the source file.
  41. *
  42. * URIs with scheme content:// are handling assuming that file is in private storage owned by a different app,
  43. * and that persistency permission is not granted. Due to this, contents of the file are temporary copied by
  44. * the OC app, and then passed {@link FileUploader}.
  45. */
  46. public class UriUploader {
  47. private final String TAG = UriUploader.class.getSimpleName();
  48. private FileActivity mActivity;
  49. private ArrayList<Parcelable> mUrisToUpload;
  50. private CopyAndUploadContentUrisTask.OnCopyTmpFilesTaskListener mCopyTmpTaskListener;
  51. private int mBehaviour;
  52. private String mUploadPath;
  53. private Account mAccount;
  54. private boolean mShowWaitingDialog;
  55. private UriUploaderResultCode mCode = UriUploaderResultCode.OK;
  56. public enum UriUploaderResultCode {
  57. OK,
  58. ERROR_UNKNOWN,
  59. ERROR_NO_FILE_TO_UPLOAD,
  60. ERROR_READ_PERMISSION_NOT_GRANTED
  61. }
  62. public UriUploader(
  63. FileActivity activity,
  64. ArrayList<Parcelable> uris,
  65. String uploadPath,
  66. Account account,
  67. int behaviour,
  68. boolean showWaitingDialog,
  69. CopyAndUploadContentUrisTask.OnCopyTmpFilesTaskListener copyTmpTaskListener
  70. ) {
  71. mActivity = activity;
  72. mUrisToUpload = uris;
  73. mUploadPath = uploadPath;
  74. mAccount = account;
  75. mBehaviour = behaviour;
  76. mShowWaitingDialog = showWaitingDialog;
  77. mCopyTmpTaskListener = copyTmpTaskListener;
  78. }
  79. public UriUploaderResultCode uploadUris() {
  80. try {
  81. List<Uri> contentUris = new ArrayList<>();
  82. List<String> contentRemotePaths = new ArrayList<>();
  83. int schemeFileCounter = 0;
  84. for (Parcelable sourceStream : mUrisToUpload) {
  85. Uri sourceUri = (Uri) sourceStream;
  86. if (sourceUri != null) {
  87. String displayName = UriUtils.getDisplayNameForUri(sourceUri, mActivity);
  88. if (displayName == null) {
  89. displayName = generateDiplayName();
  90. }
  91. String remotePath = mUploadPath + displayName;
  92. if (ContentResolver.SCHEME_CONTENT.equals(sourceUri.getScheme())) {
  93. contentUris.add(sourceUri);
  94. contentRemotePaths.add(remotePath);
  95. } else if (ContentResolver.SCHEME_FILE.equals(sourceUri.getScheme())) {
  96. /// file: uris should point to a local file, should be safe let FileUploader handle them
  97. requestUpload(sourceUri.getPath(), remotePath);
  98. schemeFileCounter++;
  99. }
  100. }
  101. }
  102. if (!contentUris.isEmpty()) {
  103. /// content: uris will be copied to temporary files before calling {@link FileUploader}
  104. copyThenUpload(contentUris.toArray(new Uri[contentUris.size()]),
  105. contentRemotePaths.toArray(new String[contentRemotePaths.size()]));
  106. } else if (schemeFileCounter == 0) {
  107. mCode = UriUploaderResultCode.ERROR_NO_FILE_TO_UPLOAD;
  108. }
  109. } catch (SecurityException e) {
  110. mCode = UriUploaderResultCode.ERROR_READ_PERMISSION_NOT_GRANTED;
  111. Log_OC.e(TAG, "Permissions fail", e);
  112. } catch (Exception e) {
  113. mCode = UriUploaderResultCode.ERROR_UNKNOWN;
  114. Log_OC.e(TAG, "Unexpected error", e);
  115. }
  116. return mCode;
  117. }
  118. private String generateDiplayName() {
  119. return mActivity.getString(R.string.common_unknown) +
  120. "-" + DisplayUtils.unixTimeToHumanReadable(System.currentTimeMillis());
  121. }
  122. /**
  123. * Requests the upload of a file in the local file system to {@link FileUploader} service.
  124. *
  125. * The original file will be left in its original location, and will not be duplicated.
  126. * As a side effect, the user will see the file as not uploaded when accesses to the OC app.
  127. * This is considered as acceptable, since when a file is shared from another app to OC,
  128. * the usual workflow will go back to the original app.
  129. *
  130. * @param localPath Absolute path in the local file system to the file to upload.
  131. * @param remotePath Absolute path in the current OC account to set to the uploaded file.
  132. */
  133. private void requestUpload(String localPath, String remotePath) {
  134. FileUploader.UploadRequester requester = new FileUploader.UploadRequester();
  135. requester.uploadNewFile(
  136. mActivity,
  137. mAccount,
  138. localPath,
  139. remotePath,
  140. mBehaviour,
  141. null, // MIME type will be detected from file name
  142. false, // do not create parent folder if not existent
  143. UploadFileOperation.CREATED_BY_USER
  144. );
  145. }
  146. /**
  147. *
  148. * @param sourceUris Array of content:// URIs to the files to upload
  149. * @param remotePaths Array of absolute paths to set to the uploaded files
  150. */
  151. private void copyThenUpload(Uri[] sourceUris, String[] remotePaths) {
  152. if (mShowWaitingDialog) {
  153. mActivity.showLoadingDialog(mActivity.getResources().
  154. getString(R.string.wait_for_tmp_copy_from_private_storage));
  155. }
  156. CopyAndUploadContentUrisTask copyTask = new CopyAndUploadContentUrisTask
  157. (mCopyTmpTaskListener, mActivity);
  158. FragmentManager fm = mActivity.getSupportFragmentManager();
  159. // Init Fragment without UI to retain AsyncTask across configuration changes
  160. TaskRetainerFragment taskRetainerFragment =
  161. (TaskRetainerFragment) fm.findFragmentByTag(TaskRetainerFragment.FTAG_TASK_RETAINER_FRAGMENT);
  162. if (taskRetainerFragment == null) {
  163. taskRetainerFragment = new TaskRetainerFragment();
  164. fm.beginTransaction()
  165. .add(taskRetainerFragment, TaskRetainerFragment.FTAG_TASK_RETAINER_FRAGMENT).commit();
  166. } // else, Fragment was created before
  167. taskRetainerFragment.setTask(copyTask);
  168. copyTask.execute(
  169. CopyAndUploadContentUrisTask.makeParamsToExecute(
  170. mAccount,
  171. sourceUris,
  172. remotePaths,
  173. mActivity.getContentResolver()
  174. )
  175. );
  176. }
  177. }