OCUpload.java 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  1. /**
  2. * ownCloud Android client application
  3. *
  4. * @author LukeOwncloud
  5. * @author masensio
  6. * @author David A. Velasco
  7. * Copyright (C) 2015 ownCloud Inc.
  8. *
  9. * This program is free software: you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License version 2,
  11. * as published by the Free Software Foundation.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. *
  21. */
  22. package com.owncloud.android.db;
  23. import android.accounts.Account;
  24. import android.content.Context;
  25. import android.os.Parcel;
  26. import android.os.Parcelable;
  27. import com.owncloud.android.R;
  28. import com.owncloud.android.authentication.AccountUtils;
  29. import com.owncloud.android.datamodel.OCFile;
  30. import com.owncloud.android.datamodel.UploadsStorageManager;
  31. import com.owncloud.android.datamodel.UploadsStorageManager.UploadStatus;
  32. import com.owncloud.android.files.services.FileUploader;
  33. import com.owncloud.android.lib.common.utils.Log_OC;
  34. import com.owncloud.android.utils.MimetypeIconUtil;
  35. import com.owncloud.android.utils.UploadUtils;
  36. import java.io.File;
  37. import java.util.Date;
  38. /**
  39. * Stores all information in order to start upload operations. PersistentUploadObject can
  40. * be stored persistently by {@link UploadsStorageManager}.
  41. *
  42. */
  43. public class OCUpload implements Parcelable {
  44. /** Generated - should be refreshed every time the class changes!! */
  45. // private static final long serialVersionUID = 2647551318657321611L;
  46. private static final String TAG = OCUpload.class.getSimpleName();
  47. private long mId;
  48. //private OCFile mFile;
  49. /**
  50. * Absolute path in the local file system to the file to be uploaded
  51. */
  52. private String mLocalPath;
  53. /**
  54. * Absolute path in the remote account to set to the uploaded file (not for its parent folder!)
  55. */
  56. private String mRemotePath;
  57. /**
  58. * Name of Owncloud account to upload file to.
  59. */
  60. private String mAccountName;
  61. /**
  62. * Local action for upload. (0 - COPY, 1 - MOVE, 2 - FORGET)
  63. */
  64. private int mLocalAction;
  65. /**
  66. * Overwrite destination file?
  67. */
  68. private boolean mForceOverwrite;
  69. /**
  70. * Create destination folder?
  71. */
  72. private boolean mIsCreateRemoteFolder;
  73. /**
  74. * Upload only via wifi?
  75. */
  76. private boolean mIsUseWifiOnly;
  77. /**
  78. * Upload only if phone being charged?
  79. */
  80. private boolean mIsWhileChargingOnly;
  81. /**
  82. * Status of upload (later, in_progress, ...).
  83. */
  84. private UploadStatus mUploadStatus;
  85. /**
  86. * Result from last upload operation. Can be null.
  87. */
  88. private UploadResult mLastResult;
  89. /**
  90. * Main constructor
  91. *
  92. * @param localPath Absolute path in the local file system to the file to be uploaded.
  93. * @param remotePath Absolute path in the remote account to set to the uploaded file.
  94. * @param accountName Name of an ownCloud account to update the file to.
  95. */
  96. public OCUpload(String localPath, String remotePath, String accountName) {
  97. if (localPath == null || !localPath.startsWith(File.separator)) {
  98. throw new IllegalArgumentException("Local path must be an absolute path in the local file system");
  99. }
  100. if (remotePath == null || !remotePath.startsWith(OCFile.PATH_SEPARATOR)) {
  101. throw new IllegalArgumentException("Remote path must be an absolute path in the local file system");
  102. }
  103. if (accountName == null || accountName.length() < 1) {
  104. throw new IllegalArgumentException("Invalid account name");
  105. }
  106. resetData();
  107. mLocalPath = localPath;
  108. mRemotePath = remotePath;
  109. mAccountName = accountName;
  110. }
  111. /**
  112. * Convenience constructor to reupload already existing {@link OCFile}s
  113. *
  114. * @param ocFile {@link OCFile} instance to update in the remote server.
  115. * @param account ownCloud {@link Account} where ocFile is contained.
  116. */
  117. public OCUpload(OCFile ocFile, Account account) {
  118. this(ocFile.getStoragePath(), ocFile.getRemotePath(), account.name);
  119. }
  120. /**
  121. * Reset all the fields to default values.
  122. */
  123. private void resetData() {
  124. mRemotePath = "";
  125. mLocalPath = "";
  126. mAccountName = "";
  127. mId = -1;
  128. mLocalAction = FileUploader.LOCAL_BEHAVIOUR_COPY;
  129. mForceOverwrite = false;
  130. mIsCreateRemoteFolder = false;
  131. mIsUseWifiOnly = true;
  132. mIsWhileChargingOnly = false;
  133. mUploadStatus = UploadStatus.UPLOAD_LATER;
  134. mLastResult = UploadResult.UNKNOWN;
  135. }
  136. // Getters & Setters
  137. public void setUploadId(long id) {
  138. mId = id;
  139. }
  140. public long getUploadId() {
  141. return mId;
  142. }
  143. /**
  144. * @return the uploadStatus
  145. */
  146. public UploadStatus getUploadStatus() {
  147. return mUploadStatus;
  148. }
  149. /**
  150. * Sets uploadStatus AND SETS lastResult = null;
  151. * @param uploadStatus the uploadStatus to set
  152. */
  153. public void setUploadStatus(UploadStatus uploadStatus) {
  154. this.mUploadStatus = uploadStatus;
  155. setLastResult(UploadResult.UNKNOWN);
  156. }
  157. /**
  158. * @return the lastResult
  159. */
  160. public UploadResult getLastResult() {
  161. return mLastResult;
  162. }
  163. /**
  164. * @param lastResult the lastResult to set
  165. */
  166. public void setLastResult(UploadResult lastResult) {
  167. this.mLastResult = lastResult;
  168. }
  169. /**
  170. * @return the localPath
  171. */
  172. public String getLocalPath() {
  173. return mLocalPath;
  174. }
  175. public void setLocalPath(String localPath) {
  176. mLocalPath = localPath;
  177. }
  178. /**
  179. * @return the remotePath
  180. */
  181. public String getRemotePath() {
  182. return mRemotePath;
  183. }
  184. /**
  185. * @return the mimeType
  186. */
  187. public String getMimeType() {
  188. return MimetypeIconUtil.getBestMimeTypeByFilename(mLocalPath);
  189. }
  190. /**
  191. * @return the localAction
  192. */
  193. public int getLocalAction() {
  194. return mLocalAction;
  195. }
  196. /**
  197. * @param localAction the localAction to set
  198. */
  199. public void setLocalAction(int localAction) {
  200. this.mLocalAction = localAction;
  201. }
  202. /**
  203. * @return the forceOverwrite
  204. */
  205. public boolean isForceOverwrite() {
  206. return mForceOverwrite;
  207. }
  208. /**
  209. * @param forceOverwrite the forceOverwrite to set
  210. */
  211. public void setForceOverwrite(boolean forceOverwrite) {
  212. this.mForceOverwrite = forceOverwrite;
  213. }
  214. /**
  215. * @return the isCreateRemoteFolder
  216. */
  217. public boolean isCreateRemoteFolder() {
  218. return mIsCreateRemoteFolder;
  219. }
  220. /**
  221. * @param isCreateRemoteFolder the isCreateRemoteFolder to set
  222. */
  223. public void setCreateRemoteFolder(boolean isCreateRemoteFolder) {
  224. this.mIsCreateRemoteFolder = isCreateRemoteFolder;
  225. }
  226. /**
  227. * @return the isUseWifiOnly
  228. */
  229. public boolean isUseWifiOnly() {
  230. return mIsUseWifiOnly;
  231. }
  232. /**
  233. * @param isUseWifiOnly the isUseWifiOnly to set
  234. */
  235. public void setUseWifiOnly(boolean isUseWifiOnly) {
  236. this.mIsUseWifiOnly = isUseWifiOnly;
  237. }
  238. /**
  239. * @return the accountName
  240. */
  241. public String getAccountName() {
  242. return mAccountName;
  243. }
  244. /**
  245. * Returns owncloud account as {@link Account} object.
  246. */
  247. public Account getAccount(Context context) {
  248. return AccountUtils.getOwnCloudAccountByName(context, getAccountName());
  249. }
  250. public void setWhileChargingOnly(boolean isWhileChargingOnly) {
  251. this.mIsWhileChargingOnly = isWhileChargingOnly;
  252. }
  253. public boolean isWhileChargingOnly() {
  254. return mIsWhileChargingOnly;
  255. }
  256. /**
  257. * For debugging purposes only.
  258. */
  259. public String toFormattedString() {
  260. try {
  261. String localPath = getLocalPath() != null ? getLocalPath() : "";
  262. return localPath + " status:" + getUploadStatus() + " result:" +
  263. (getLastResult() == null ? "null" : getLastResult().getValue());
  264. } catch (NullPointerException e){
  265. Log_OC.d(TAG, "Exception " + e.toString() );
  266. return (e.toString());
  267. }
  268. }
  269. /**
  270. * Removes all uploads restrictions. After calling this function upload is performed immediately if requested.
  271. */
  272. public void removeAllUploadRestrictions() {
  273. setUseWifiOnly(false);
  274. setWhileChargingOnly(false);
  275. //setUploadTimestamp(0);
  276. }
  277. /**
  278. * Returns true when user is able to cancel this upload. That is, when
  279. * upload is currently in progress or scheduled for upload.
  280. */
  281. public boolean userCanCancelUpload() {
  282. switch (this.getUploadStatus()) {
  283. case UPLOAD_IN_PROGRESS:
  284. case UPLOAD_LATER:
  285. return true;
  286. default:
  287. return false;
  288. }
  289. }
  290. /**
  291. * Returns true when user can choose to retry this upload. That is, when
  292. * user cancelled upload before or when upload has failed.
  293. */
  294. public boolean userCanRetryUpload() {
  295. switch (this.getUploadStatus()) {
  296. case UPLOAD_CANCELLED:
  297. case UPLOAD_FAILED_RETRY://automatically retried. no need for user option.
  298. case UPLOAD_FAILED_GIVE_UP: //TODO this case needs to be handled as described by
  299. // https://github.com/owncloud/android/issues/765#issuecomment-66490312
  300. case UPLOAD_LATER: //upload is already schedule but allow user to increase priority
  301. return true;
  302. default:
  303. return false;
  304. }
  305. }
  306. /****
  307. *
  308. */
  309. public static final Parcelable.Creator<OCUpload> CREATOR = new Parcelable.Creator<OCUpload>() {
  310. @Override
  311. public OCUpload createFromParcel(Parcel source) {
  312. return new OCUpload(source);
  313. }
  314. @Override
  315. public OCUpload[] newArray(int size) {
  316. return new OCUpload[size];
  317. }
  318. };
  319. /**
  320. * Reconstruct from parcel
  321. *
  322. * @param source The source parcel
  323. */
  324. protected OCUpload(Parcel source) {
  325. readFromParcel(source);
  326. }
  327. public void readFromParcel(Parcel source) {
  328. mId = source.readLong();
  329. mLocalPath = source.readString();
  330. mRemotePath = source.readString();
  331. mAccountName = source.readString();
  332. mLocalAction = source.readInt();
  333. mForceOverwrite = (source.readInt() == 1);
  334. mIsCreateRemoteFolder = (source.readInt() == 1);
  335. mIsUseWifiOnly = (source.readInt() == 1);
  336. mIsWhileChargingOnly = (source.readInt() == 1);
  337. try {
  338. mUploadStatus = UploadStatus.valueOf(source.readString());
  339. } catch (IllegalArgumentException x) {
  340. mUploadStatus = UploadStatus.UPLOAD_LATER;
  341. }
  342. try {
  343. mLastResult = UploadResult.valueOf(source.readString());
  344. } catch (IllegalArgumentException x) {
  345. mLastResult = UploadResult.UNKNOWN;
  346. }
  347. }
  348. @Override
  349. public int describeContents() {
  350. return this.hashCode();
  351. }
  352. @Override
  353. public void writeToParcel(Parcel dest, int flags) {
  354. dest.writeLong(mId);
  355. dest.writeString(mLocalPath);
  356. dest.writeString(mRemotePath);
  357. dest.writeString(mAccountName);
  358. dest.writeInt(mLocalAction);
  359. dest.writeInt(mForceOverwrite ? 1 : 0);
  360. dest.writeInt(mIsCreateRemoteFolder ? 1 : 0);
  361. dest.writeInt(mIsUseWifiOnly ? 1 : 0);
  362. dest.writeInt(mIsWhileChargingOnly ? 1 : 0);
  363. dest.writeString(mUploadStatus.name());
  364. dest.writeString(((mLastResult == null) ? "" : mLastResult.name()));
  365. }
  366. enum CanUploadFileNowStatus {NOW, LATER, FILE_GONE, ERROR};
  367. /**
  368. * Returns true when the file may be uploaded now. This methods checks all
  369. * restraints of the passed {@link OCUpload}, these include
  370. * isUseWifiOnly(), check if local file exists, check if file was already
  371. * uploaded...
  372. *
  373. * If return value is CanUploadFileNowStatus.NOW, uploadFile() may be
  374. * called.
  375. *
  376. * @return CanUploadFileNowStatus.NOW is upload may proceed, <br>
  377. * CanUploadFileNowStatus.LATER if upload should be performed at a
  378. * later time, <br>
  379. * CanUploadFileNowStatus.ERROR if a severe error happened, calling
  380. * entity should remove upload from queue.
  381. *
  382. */
  383. private CanUploadFileNowStatus canUploadFileNow(Context context) {
  384. if (getUploadStatus() == UploadStatus.UPLOAD_SUCCEEDED) {
  385. Log_OC.w(TAG, "Already succeeded uploadObject was again scheduled for upload. Fix that!");
  386. return CanUploadFileNowStatus.ERROR;
  387. }
  388. if (isUseWifiOnly()
  389. && !UploadUtils.isConnectedViaWiFi(context)) {
  390. Log_OC.d(TAG, "Do not start upload because it is wifi-only.");
  391. return CanUploadFileNowStatus.LATER;
  392. }
  393. if(isWhileChargingOnly() && !UploadUtils.isCharging(context)) {
  394. Log_OC.d(TAG, "Do not start upload because it is while charging only.");
  395. return CanUploadFileNowStatus.LATER;
  396. }
  397. if (!new File(getLocalPath()).exists()) {
  398. Log_OC.d(TAG, "Do not start upload because local file does not exist.");
  399. return CanUploadFileNowStatus.FILE_GONE;
  400. }
  401. return CanUploadFileNowStatus.NOW;
  402. }
  403. /**
  404. * Returns the reason as String why state of OCUpload is LATER. If
  405. * upload state != LATER return null.
  406. */
  407. public String getUploadLaterReason(Context context) {
  408. StringBuilder reason = new StringBuilder();
  409. Date now = new Date();
  410. if (isUseWifiOnly() && !UploadUtils.isConnectedViaWiFi(context)) {
  411. if (reason.length() > 0) {
  412. reason.append(context.getString(R.string.uploads_view_later_reason_add_wifi_reason));
  413. } else {
  414. reason.append(context.getString(R.string.uploads_view_later_reason_waiting_for_wifi));
  415. }
  416. }
  417. if (isWhileChargingOnly() && !UploadUtils.isCharging(context)) {
  418. if (reason.length() > 0) {
  419. reason.append(context.getString(R.string.uploads_view_later_reason_add_charging_reason));
  420. } else {
  421. reason.append(context.getString(R.string.uploads_view_later_reason_waiting_for_charging));
  422. }
  423. }
  424. reason.append(".");
  425. if (reason.length() > 1) {
  426. return reason.toString();
  427. }
  428. if (getUploadStatus() == UploadStatus.UPLOAD_LATER) {
  429. return context.getString(R.string.uploads_view_later_waiting_to_upload);
  430. }
  431. return null;
  432. }
  433. }