|
@@ -1,2000 +0,0 @@
|
|
|
-/**
|
|
|
- * ownCloud Android client application
|
|
|
- *
|
|
|
- * @author LukeOwncloud
|
|
|
- * @author masensio
|
|
|
- * Copyright (C) 2015 ownCloud Inc.
|
|
|
- *
|
|
|
- * This program is free software: you can redistribute it and/or modify
|
|
|
- * it under the terms of the GNU General Public License version 2,
|
|
|
- * as published by the Free Software Foundation.
|
|
|
- *
|
|
|
- * This program is distributed in the hope that it will be useful,
|
|
|
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
- * GNU General Public License for more details.
|
|
|
- *
|
|
|
- * You should have received a copy of the GNU General Public License
|
|
|
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
- *
|
|
|
- */
|
|
|
-
|
|
|
-package com.owncloud.android.files.services;
|
|
|
-
|
|
|
-import android.accounts.Account;
|
|
|
-import android.accounts.AccountManager;
|
|
|
-import android.accounts.OnAccountsUpdateListener;
|
|
|
-import android.app.NotificationManager;
|
|
|
-import android.app.PendingIntent;
|
|
|
-import android.app.Service;
|
|
|
-import android.content.Context;
|
|
|
-import android.content.Intent;
|
|
|
-import android.os.Binder;
|
|
|
-import android.os.Handler;
|
|
|
-import android.os.HandlerThread;
|
|
|
-import android.os.IBinder;
|
|
|
-import android.os.Looper;
|
|
|
-import android.os.Message;
|
|
|
-import android.support.v4.app.NotificationCompat;
|
|
|
-import android.util.Pair;
|
|
|
-import android.webkit.MimeTypeMap;
|
|
|
-
|
|
|
-import com.owncloud.android.R;
|
|
|
-import com.owncloud.android.authentication.AccountUtils;
|
|
|
-import com.owncloud.android.authentication.AuthenticatorActivity;
|
|
|
-import com.owncloud.android.datamodel.FileDataStorageManager;
|
|
|
-import com.owncloud.android.datamodel.OCFile;
|
|
|
-import com.owncloud.android.datamodel.UploadsStorageManager;
|
|
|
-import com.owncloud.android.datamodel.UploadsStorageManager.UploadStatus;
|
|
|
-import com.owncloud.android.db.OCUpload;
|
|
|
-import com.owncloud.android.db.UploadResult;
|
|
|
-import com.owncloud.android.lib.common.OwnCloudAccount;
|
|
|
-import com.owncloud.android.lib.common.OwnCloudClient;
|
|
|
-import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
|
|
|
-import com.owncloud.android.lib.common.network.OnDatatransferProgressListener;
|
|
|
-import com.owncloud.android.lib.common.operations.RemoteOperation;
|
|
|
-import com.owncloud.android.lib.common.operations.RemoteOperationResult;
|
|
|
-import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
|
|
|
-import com.owncloud.android.lib.common.utils.Log_OC;
|
|
|
-import com.owncloud.android.lib.resources.files.ExistenceCheckRemoteOperation;
|
|
|
-import com.owncloud.android.lib.resources.files.FileUtils;
|
|
|
-import com.owncloud.android.lib.resources.files.ReadRemoteFileOperation;
|
|
|
-import com.owncloud.android.lib.resources.files.RemoteFile;
|
|
|
-import com.owncloud.android.lib.resources.status.OwnCloudVersion;
|
|
|
-import com.owncloud.android.notifications.NotificationBuilderWithProgressBar;
|
|
|
-import com.owncloud.android.notifications.NotificationDelayer;
|
|
|
-import com.owncloud.android.operations.CreateFolderOperation;
|
|
|
-import com.owncloud.android.operations.UploadFileOperation;
|
|
|
-import com.owncloud.android.operations.common.SyncOperation;
|
|
|
-import com.owncloud.android.ui.activity.FileActivity;
|
|
|
-import com.owncloud.android.ui.activity.UploadListActivity;
|
|
|
-import com.owncloud.android.utils.DisplayUtils;
|
|
|
-import com.owncloud.android.utils.ErrorMessageAdapter;
|
|
|
-import com.owncloud.android.utils.UploadUtils;
|
|
|
-import com.owncloud.android.utils.UriUtils;
|
|
|
-
|
|
|
-import java.io.File;
|
|
|
-import java.util.AbstractList;
|
|
|
-import java.util.Date;
|
|
|
-import java.util.HashMap;
|
|
|
-import java.util.Iterator;
|
|
|
-import java.util.Map;
|
|
|
-import java.util.Vector;
|
|
|
-import java.util.concurrent.atomic.AtomicBoolean;
|
|
|
-
|
|
|
-/**
|
|
|
- * Service for uploading files. Invoke using context.startService(...). Files to
|
|
|
- * be uploaded are stored persistently using {@link UploadsStorageManager}.
|
|
|
- *
|
|
|
- * On next invocation of {@link FileUploadService} uploaded files which
|
|
|
- * previously failed will be uploaded again until either upload succeeded or a
|
|
|
- * fatal error occured.
|
|
|
- *
|
|
|
- * Every file passed to this service is uploaded. No filtering is performed.
|
|
|
- * However, Intent keys (e.g., KEY_WIFI_ONLY) are obeyed.
|
|
|
- *
|
|
|
- */
|
|
|
-public class FileUploadService extends Service implements OnDatatransferProgressListener,
|
|
|
- OnAccountsUpdateListener {
|
|
|
-
|
|
|
- private static final String TAG = FileUploadService.class.getSimpleName();
|
|
|
-
|
|
|
- private static final String UPLOAD_START_MESSAGE = "UPLOAD_START";
|
|
|
- private static final String UPLOAD_FINISH_MESSAGE = "UPLOAD_FINISH";
|
|
|
- public static final String EXTRA_UPLOAD_RESULT = "RESULT";
|
|
|
- public static final String EXTRA_REMOTE_PATH = "REMOTE_PATH";
|
|
|
- public static final String EXTRA_OLD_REMOTE_PATH = "OLD_REMOTE_PATH";
|
|
|
- public static final String EXTRA_OLD_FILE_PATH = "OLD_FILE_PATH";
|
|
|
- public static final String EXTRA_LINKED_TO_PATH = "LINKED_TO";
|
|
|
- public static final String ACCOUNT_NAME = "ACCOUNT_NAME";
|
|
|
-
|
|
|
- public static final String KEY_FILE = "FILE";
|
|
|
- public static final String KEY_LOCAL_FILE = "LOCAL_FILE";
|
|
|
- public static final String KEY_REMOTE_FILE = "REMOTE_FILE";
|
|
|
- public static final String KEY_MIME_TYPE = "MIME_TYPE";
|
|
|
-
|
|
|
- /**
|
|
|
- * Call this Service with only this Intent key if all pending uploads are to be retried.
|
|
|
- */
|
|
|
- private static final String KEY_RETRY = "KEY_RETRY";
|
|
|
-// /**
|
|
|
-// * Call this Service with KEY_RETRY and KEY_RETRY_REMOTE_PATH to retry
|
|
|
-// * upload of file identified by KEY_RETRY_REMOTE_PATH.
|
|
|
-// */
|
|
|
-// private static final String KEY_RETRY_REMOTE_PATH = "KEY_RETRY_REMOTE_PATH";
|
|
|
- /**
|
|
|
- * Call this Service with KEY_RETRY and KEY_RETRY_UPLOAD to retry
|
|
|
- * upload of file identified by KEY_RETRY_UPLOAD.
|
|
|
- */
|
|
|
- private static final String KEY_RETRY_UPLOAD = "KEY_RETRY_UPLOAD";
|
|
|
- /**
|
|
|
- * {@link Account} to which file is to be uploaded.
|
|
|
- */
|
|
|
- public static final String KEY_ACCOUNT = "ACCOUNT";
|
|
|
- /**
|
|
|
- * Set whether single file or multiple files are to be uploaded. SINGLE_FILES = 0, MULTIPLE_FILEs = 1.
|
|
|
- */
|
|
|
- public static final String KEY_UPLOAD_TYPE = "UPLOAD_TYPE";
|
|
|
- /**
|
|
|
- * Set to true if remote file is to be overwritten. Default action is to upload with different name.
|
|
|
- */
|
|
|
- public static final String KEY_FORCE_OVERWRITE = "KEY_FORCE_OVERWRITE";
|
|
|
- /**
|
|
|
- * Set to true if remote folder is to be created if it does not exist.
|
|
|
- */
|
|
|
- public static final String KEY_CREATE_REMOTE_FOLDER = "CREATE_REMOTE_FOLDER";
|
|
|
- /**
|
|
|
- * Set to true if upload is to performed only when connected via wifi.
|
|
|
- */
|
|
|
- public static final String KEY_WIFI_ONLY = "WIFI_ONLY";
|
|
|
- /**
|
|
|
- * Set to true if upload is to performed only when phone is being charged.
|
|
|
- */
|
|
|
- public static final String KEY_WHILE_CHARGING_ONLY = "KEY_WHILE_CHARGING_ONLY";
|
|
|
-// /**
|
|
|
-// * Set to future UNIX timestamp. Upload will not be performed before this timestamp.
|
|
|
-// */
|
|
|
-// public static final String KEY_UPLOAD_TIMESTAMP= "KEY_UPLOAD_TIMESTAMP";
|
|
|
-
|
|
|
- public static final String KEY_LOCAL_BEHAVIOUR = "BEHAVIOUR";
|
|
|
-
|
|
|
- //public static final String KEY_INSTANT_UPLOAD = "INSTANT_UPLOAD";
|
|
|
-
|
|
|
- public static final int LOCAL_BEHAVIOUR_COPY = 0;
|
|
|
- public static final int LOCAL_BEHAVIOUR_MOVE = 1;
|
|
|
- public static final int LOCAL_BEHAVIOUR_FORGET = 2;
|
|
|
-
|
|
|
- public static final int UPLOAD_SINGLE_FILE = 0;
|
|
|
- public static final int UPLOAD_MULTIPLE_FILES = 1;
|
|
|
-
|
|
|
- /**
|
|
|
- * Describes local behavior for upload.
|
|
|
- */
|
|
|
-// public enum LocalBehaviour {
|
|
|
-// /**
|
|
|
-// * Creates a copy of file and stores it in tmp folder inside owncloud
|
|
|
-// * folder on sd-card. After upload it is moved to local owncloud
|
|
|
-// * storage. Original file stays untouched.
|
|
|
-// */
|
|
|
-// LOCAL_BEHAVIOUR_COPY(0),
|
|
|
-// /**
|
|
|
-// * Upload file from current storage. Afterwards original file is move to
|
|
|
-// * local owncloud storage.
|
|
|
-// */
|
|
|
-// LOCAL_BEHAVIOUR_MOVE(1),
|
|
|
-// /**
|
|
|
-// * Just uploads file and leaves it where it is. Original file stays
|
|
|
-// * untouched.
|
|
|
-// */
|
|
|
-// LOCAL_BEHAVIOUR_FORGET(2);
|
|
|
-// private final int value;
|
|
|
-//
|
|
|
-// LocalBehaviour(int value) {
|
|
|
-// this.value = value;
|
|
|
-// }
|
|
|
-//
|
|
|
-// public int getValue() {
|
|
|
-// return value;
|
|
|
-// }
|
|
|
-//
|
|
|
-// public static LocalBehaviour fromValue(int value){
|
|
|
-// switch (value)
|
|
|
-// {
|
|
|
-// case 0:
|
|
|
-// return LOCAL_BEHAVIOUR_COPY;
|
|
|
-// case 1:
|
|
|
-// return LOCAL_BEHAVIOUR_MOVE;
|
|
|
-// case 2:
|
|
|
-// return LOCAL_BEHAVIOUR_FORGET;
|
|
|
-// }
|
|
|
-// return null;
|
|
|
-// }
|
|
|
-// }
|
|
|
-
|
|
|
-// public enum UploadQuantity {
|
|
|
-// UPLOAD_SINGLE_FILE(0), UPLOAD_MULTIPLE_FILES(1);
|
|
|
-// private final int value;
|
|
|
-//
|
|
|
-// UploadQuantity(int value) {
|
|
|
-// this.value = value;
|
|
|
-// }
|
|
|
-//
|
|
|
-// public int getValue() {
|
|
|
-// return value;
|
|
|
-// }
|
|
|
-// };
|
|
|
-
|
|
|
- private Looper mServiceLooper;
|
|
|
- private ServiceHandler mServiceHandler;
|
|
|
- //private ExecutorService mUploadExecutor;
|
|
|
-
|
|
|
- private IBinder mBinder;
|
|
|
- private OwnCloudClient mUploadClient = null;
|
|
|
- private Account mCurrentAccount = null;
|
|
|
- private FileDataStorageManager mStorageManager;
|
|
|
- //since there can be only one instance of an Android service, there also just one db connection.
|
|
|
- private UploadsStorageManager mUploadsStorageManager = null;
|
|
|
-
|
|
|
- private final AtomicBoolean mCancellationRequested = new AtomicBoolean(false);
|
|
|
- //private final AtomicBoolean mCancellationPossible = new AtomicBoolean(false);
|
|
|
-
|
|
|
- /**
|
|
|
- * List of uploads that are currently pending. Maps from remotePath to where file
|
|
|
- * is being uploaded to {@link UploadFileOperation}.
|
|
|
- */
|
|
|
- //private ConcurrentMap<String, OCUpload> mPendingUploads = new ConcurrentHashMap<String, OCUpload>();
|
|
|
- // TODO: change kind of mPendingUploads: List to IndexedForest
|
|
|
- private IndexedForest<UploadFileOperation> mPendingUploads = new IndexedForest<UploadFileOperation>();
|
|
|
-
|
|
|
- /**
|
|
|
- * {@link UploadFileOperation} object of ongoing upload. Can be null. Note: There can only be one concurrent upload!
|
|
|
- */
|
|
|
- private UploadFileOperation mCurrentUpload = null;
|
|
|
-
|
|
|
- private NotificationManager mNotificationManager;
|
|
|
- private NotificationCompat.Builder mNotificationBuilder;
|
|
|
- private int mLastPercent;
|
|
|
-
|
|
|
- private static final String MIME_TYPE_PDF = "application/pdf";
|
|
|
- private static final String FILE_EXTENSION_PDF = ".pdf";
|
|
|
-
|
|
|
- public static String getUploadStartMessage() {
|
|
|
- return FileUploadService.class.getName() + UPLOAD_START_MESSAGE;
|
|
|
- }
|
|
|
-
|
|
|
- public static String getUploadFinishMessage() {
|
|
|
- return FileUploadService.class.getName() + UPLOAD_FINISH_MESSAGE;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Checks if an ownCloud server version should support chunked uploads.
|
|
|
- *
|
|
|
- * @param version OwnCloud version instance corresponding to an ownCloud
|
|
|
- * server.
|
|
|
- * @return 'True' if the ownCloud server with version supports chunked
|
|
|
- * uploads.
|
|
|
- * <p/>
|
|
|
- * TODO - move to OCClient
|
|
|
- */
|
|
|
- private static boolean chunkedUploadIsSupported(OwnCloudVersion version) {
|
|
|
- return (version != null && version.compareTo(OwnCloudVersion.owncloud_v4_5) >= 0);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Service initialization
|
|
|
- */
|
|
|
- // TODO: Clean method: comments on extra code
|
|
|
- @Override
|
|
|
- public void onCreate() {
|
|
|
- super.onCreate();
|
|
|
- Log_OC.d(TAG, "Creating service");
|
|
|
- //Log_OC.d(TAG, "mPendingUploads size:" + mPendingUploads.size() + " - onCreate");
|
|
|
- mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
|
|
- // HandlerThread thread = new HandlerThread("FileUploadService-Requester"); --> From FileUploadService
|
|
|
- HandlerThread thread = new HandlerThread("FileUploaderThread",
|
|
|
- android.os.Process.THREAD_PRIORITY_BACKGROUND);
|
|
|
- thread.start();
|
|
|
- mServiceLooper = thread.getLooper();
|
|
|
- //mServiceHandler = new ServiceHandler(mServiceLooper); // FileUploaderService
|
|
|
- mServiceHandler = new ServiceHandler(mServiceLooper, this); // FileUploader
|
|
|
- mBinder = new FileUploaderBinder();
|
|
|
-
|
|
|
- // From FileUploaderService
|
|
|
- mUploadsStorageManager = new UploadsStorageManager(getContentResolver());
|
|
|
-
|
|
|
- //when this service starts there is no upload in progress. if db says so, app probably crashed before.
|
|
|
- mUploadsStorageManager.setAllCurrentToUploadLater();
|
|
|
-
|
|
|
- // mUploadExecutor = Executors.newFixedThreadPool(1);
|
|
|
-
|
|
|
-// Log_OC.d(TAG, "FileUploadService.retry() called by onCreate()");
|
|
|
-// FileUploadService.retry(getApplicationContext());
|
|
|
-
|
|
|
- AccountManager am = AccountManager.get(getApplicationContext());
|
|
|
- am.addOnAccountsUpdatedListener(this, null, false);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Service clean up
|
|
|
- */
|
|
|
- @Override
|
|
|
- public void onDestroy() {
|
|
|
- Log_OC.v(TAG, "Destroying service");
|
|
|
- mBinder = null;
|
|
|
- mServiceHandler = null;
|
|
|
- mServiceLooper.quit();
|
|
|
- mServiceLooper = null;
|
|
|
- mNotificationManager = null;
|
|
|
-
|
|
|
- // From FileUploader
|
|
|
- //Log_OC.d(TAG, "mPendingUploads size:" + mPendingUploads.size() + " - onDestroy");
|
|
|
- Log_OC.d(TAG, "mPendingUploads size:" + mPendingUploads.toString() + " - onDestroy");
|
|
|
- //mServiceLooper.quit();
|
|
|
- //mUploadExecutor.shutdown();
|
|
|
-
|
|
|
- AccountManager am = AccountManager.get(getApplicationContext());
|
|
|
- am.removeOnAccountsUpdatedListener(this);
|
|
|
-
|
|
|
- super.onDestroy();
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- // Deprecated: TODO - Remove, not in FileUploader
|
|
|
-// @Override
|
|
|
-// public void onStart(Intent intent, int intentStartId) {
|
|
|
-// Message msg = mServiceHandler.obtainMessage();
|
|
|
-// msg.arg1 = intentStartId;
|
|
|
-// msg.obj = intent;
|
|
|
-// mServiceHandler.sendMessage(msg);
|
|
|
-// }
|
|
|
-
|
|
|
- /**
|
|
|
- * Entry point to add one or several files to the queue of uploads.
|
|
|
- * <p/>
|
|
|
- * New uploads are added calling to startService(), resulting in a call to
|
|
|
- * this method. This ensures the service will keep on working although the
|
|
|
- * caller activity goes away.
|
|
|
- */
|
|
|
- @Override
|
|
|
- public int onStartCommand(Intent intent, int flags, int startId) {
|
|
|
- Log_OC.d(TAG, "Starting command with id " + startId);
|
|
|
-
|
|
|
- boolean retry = intent.getBooleanExtra(KEY_RETRY, false);
|
|
|
- AbstractList<String> requestedUploads = new Vector<String>();
|
|
|
-
|
|
|
- if (!intent.hasExtra(KEY_ACCOUNT)) {
|
|
|
- Log_OC.e(TAG, "Not enough information provided in intent");
|
|
|
- return Service.START_NOT_STICKY;
|
|
|
-
|
|
|
- } else {
|
|
|
- Account account = intent.getParcelableExtra(KEY_ACCOUNT);
|
|
|
- if (!AccountUtils.exists(account, getApplicationContext())) {
|
|
|
- return Service.START_NOT_STICKY;
|
|
|
- }
|
|
|
- OwnCloudVersion ocv = AccountUtils.getServerVersion(account);
|
|
|
- boolean chunked = FileUploadService.chunkedUploadIsSupported(ocv);
|
|
|
-
|
|
|
- if (!retry) {
|
|
|
- if (!intent.hasExtra(KEY_UPLOAD_TYPE) || !(intent.hasExtra(KEY_LOCAL_FILE) ||
|
|
|
- intent.hasExtra(KEY_FILE))) {
|
|
|
- Log_OC.e(TAG, "Not enough information provided in intent");
|
|
|
- return Service.START_NOT_STICKY;
|
|
|
- }
|
|
|
- int uploadType = intent.getIntExtra(KEY_UPLOAD_TYPE, -1);
|
|
|
- if (uploadType == -1) {
|
|
|
- Log_OC.e(TAG, "Incorrect upload type provided");
|
|
|
- return Service.START_NOT_STICKY;
|
|
|
- }
|
|
|
-
|
|
|
- String[] localPaths = null, remotePaths = null, mimeTypes = null;
|
|
|
- OCFile[] files = null;
|
|
|
- if (uploadType == UPLOAD_SINGLE_FILE) {
|
|
|
-
|
|
|
- if (intent.hasExtra(KEY_FILE)) {
|
|
|
- files = new OCFile[]{intent.getParcelableExtra(KEY_FILE)};
|
|
|
-
|
|
|
- } else {
|
|
|
- localPaths = new String[]{intent.getStringExtra(KEY_LOCAL_FILE)};
|
|
|
- remotePaths = new String[]{intent.getStringExtra(KEY_REMOTE_FILE)};
|
|
|
- mimeTypes = new String[]{intent.getStringExtra(KEY_MIME_TYPE)};
|
|
|
- }
|
|
|
-
|
|
|
- } else { // mUploadType == UPLOAD_MULTIPLE_FILES
|
|
|
-
|
|
|
- if (intent.hasExtra(KEY_FILE)) {
|
|
|
- files = (OCFile[]) intent.getParcelableArrayExtra(KEY_FILE); // TODO
|
|
|
- // will
|
|
|
- // this
|
|
|
- // casting
|
|
|
- // work
|
|
|
- // fine?
|
|
|
-
|
|
|
- } else {
|
|
|
- localPaths = intent.getStringArrayExtra(KEY_LOCAL_FILE);
|
|
|
- remotePaths = intent.getStringArrayExtra(KEY_REMOTE_FILE);
|
|
|
- mimeTypes = intent.getStringArrayExtra(KEY_MIME_TYPE);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- mStorageManager = new FileDataStorageManager(account, getContentResolver());
|
|
|
-
|
|
|
- boolean forceOverwrite = intent.getBooleanExtra(KEY_FORCE_OVERWRITE, false);
|
|
|
- int localAction = intent.getIntExtra(KEY_LOCAL_BEHAVIOUR, LOCAL_BEHAVIOUR_FORGET);
|
|
|
-
|
|
|
- boolean isCreateRemoteFolder = intent.getBooleanExtra(KEY_CREATE_REMOTE_FOLDER, false);
|
|
|
- boolean isUseWifiOnly = intent.getBooleanExtra(KEY_WIFI_ONLY, true);
|
|
|
- boolean isWhileChargingOnly = intent.getBooleanExtra(KEY_WHILE_CHARGING_ONLY, false);
|
|
|
- //long uploadTimestamp = intent.getLongExtra(KEY_UPLOAD_TIMESTAMP, -1);
|
|
|
-
|
|
|
-
|
|
|
- if (intent.hasExtra(KEY_FILE) && files == null) {
|
|
|
- Log_OC.e(TAG, "Incorrect array for OCFiles provided in upload intent");
|
|
|
- return Service.START_NOT_STICKY;
|
|
|
-
|
|
|
- } else if (!intent.hasExtra(KEY_FILE)) {
|
|
|
- if (localPaths == null) {
|
|
|
- Log_OC.e(TAG, "Incorrect array for local paths provided in upload intent");
|
|
|
- return Service.START_NOT_STICKY;
|
|
|
- }
|
|
|
- if (remotePaths == null) {
|
|
|
- Log_OC.e(TAG, "Incorrect array for remote paths provided in upload intent");
|
|
|
- return Service.START_NOT_STICKY;
|
|
|
- }
|
|
|
- if (localPaths.length != remotePaths.length) {
|
|
|
- Log_OC.e(TAG, "Different number of remote paths and local paths!");
|
|
|
- return Service.START_NOT_STICKY;
|
|
|
- }
|
|
|
-
|
|
|
- files = new OCFile[localPaths.length];
|
|
|
- for (int i = 0; i < localPaths.length; i++) {
|
|
|
- files[i] = obtainNewOCFileToUpload(remotePaths[i], localPaths[i],
|
|
|
- ((mimeTypes != null) ? mimeTypes[i] : null));
|
|
|
- if (files[i] == null) {
|
|
|
- Log_OC.e(TAG, "obtainNewOCFileToUpload() returned null for remotePaths[i]:" + remotePaths[i]
|
|
|
- + " and localPaths[i]:" + localPaths[i]);
|
|
|
- return Service.START_NOT_STICKY;
|
|
|
- }
|
|
|
-
|
|
|
- mStorageManager.saveNewFile(files[i]);
|
|
|
- files[i] = mStorageManager.getFileByLocalPath(files[i].getStoragePath());
|
|
|
- }
|
|
|
- }
|
|
|
- // at this point variable "OCFile[] files" is loaded correctly.
|
|
|
-
|
|
|
- String uploadKey = null;
|
|
|
- UploadFileOperation newUpload = null;
|
|
|
- try {
|
|
|
- for (int i = 0; i < files.length; i++) {
|
|
|
- newUpload = new UploadFileOperation(
|
|
|
- account,
|
|
|
- files[i],
|
|
|
- chunked,
|
|
|
- forceOverwrite,
|
|
|
- localAction,
|
|
|
- getApplicationContext()
|
|
|
- );
|
|
|
- if (isCreateRemoteFolder) {
|
|
|
- newUpload.setRemoteFolderToBeCreated();
|
|
|
- }
|
|
|
- newUpload.addDatatransferProgressListener(this);
|
|
|
- newUpload.addDatatransferProgressListener((FileUploaderBinder) mBinder);
|
|
|
-
|
|
|
- // Save upload in database
|
|
|
- OCUpload ocUpload = new OCUpload(files[i]);
|
|
|
- ocUpload.setAccountName(account.name);
|
|
|
- ocUpload.setForceOverwrite(forceOverwrite);
|
|
|
- ocUpload.setCreateRemoteFolder(isCreateRemoteFolder);
|
|
|
- ocUpload.setLocalAction(localAction);
|
|
|
- ocUpload.setUseWifiOnly(isUseWifiOnly);
|
|
|
- ocUpload.setWhileChargingOnly(isWhileChargingOnly);
|
|
|
-// ocUpload.setUploadTimestamp(uploadTimestamp);
|
|
|
- ocUpload.setUploadStatus(UploadStatus.UPLOAD_LATER);
|
|
|
-
|
|
|
- // storagePath inside upload is the temporary path. file
|
|
|
- // contains the correct path used as db reference.
|
|
|
- long id = mUploadsStorageManager.storeUpload(ocUpload);
|
|
|
- newUpload.setOCUploadId(id);
|
|
|
-
|
|
|
- Pair<String, String> putResult = mPendingUploads.putIfAbsent(
|
|
|
- account, files[i].getRemotePath(), newUpload, String.valueOf(id)
|
|
|
- );
|
|
|
- if (putResult != null) {
|
|
|
- uploadKey = putResult.first;
|
|
|
- requestedUploads.add(uploadKey);
|
|
|
- } else {
|
|
|
- mUploadsStorageManager.removeUpload(id);
|
|
|
- }
|
|
|
- // else, file already in the queue of uploads; don't repeat the request
|
|
|
- }
|
|
|
-
|
|
|
- } catch (IllegalArgumentException e) {
|
|
|
- Log_OC.e(TAG, "Not enough information provided in intent: " + e.getMessage());
|
|
|
- return START_NOT_STICKY;
|
|
|
-
|
|
|
- } catch (IllegalStateException e) {
|
|
|
- Log_OC.e(TAG, "Bad information provided in intent: " + e.getMessage());
|
|
|
- return START_NOT_STICKY;
|
|
|
-
|
|
|
- } catch (Exception e) {
|
|
|
- Log_OC.e(TAG, "Unexpected exception while processing upload intent", e);
|
|
|
- return START_NOT_STICKY;
|
|
|
-
|
|
|
- }
|
|
|
- } else {
|
|
|
- if (!intent.hasExtra(KEY_ACCOUNT) || !intent.hasExtra(KEY_RETRY_UPLOAD) ) {
|
|
|
- Log_OC.e(TAG, "Not enough information provided in intent: no KEY_RETRY_UPLOAD_KEY");
|
|
|
- return START_NOT_STICKY;
|
|
|
- }
|
|
|
- OCUpload upload = intent.getParcelableExtra(KEY_RETRY_UPLOAD);
|
|
|
-
|
|
|
- UploadFileOperation newUpload = new UploadFileOperation(
|
|
|
- account,
|
|
|
- upload.getOCFile(),
|
|
|
- chunked,
|
|
|
- upload.isForceOverwrite(),
|
|
|
- upload.getLocalAction(),
|
|
|
- getApplicationContext()
|
|
|
- );
|
|
|
- if (upload.isCreateRemoteFolder()) {
|
|
|
- newUpload.setRemoteFolderToBeCreated();
|
|
|
- }
|
|
|
- newUpload.addDatatransferProgressListener(this);
|
|
|
- newUpload.addDatatransferProgressListener((FileUploaderBinder) mBinder);
|
|
|
- newUpload.setOCUploadId(upload.getUploadId());
|
|
|
-
|
|
|
- Pair<String, String> putResult = mPendingUploads.putIfAbsent(
|
|
|
- account, upload.getOCFile().getRemotePath(), newUpload, String.valueOf(upload.getUploadId())
|
|
|
- );
|
|
|
- if (putResult != null) {
|
|
|
- String uploadKey = putResult.first;
|
|
|
- requestedUploads.add(uploadKey);
|
|
|
-
|
|
|
- // Update upload in database
|
|
|
- upload.setUploadStatus(UploadStatus.UPLOAD_LATER);
|
|
|
- mUploadsStorageManager.updateUpload(upload);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (requestedUploads.size() > 0) {
|
|
|
- Message msg = mServiceHandler.obtainMessage();
|
|
|
- msg.arg1 = startId;
|
|
|
- msg.obj = requestedUploads;
|
|
|
- mServiceHandler.sendMessage(msg);
|
|
|
- }
|
|
|
- return Service.START_NOT_STICKY;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- @Override
|
|
|
- public void onAccountsUpdated(Account[] accounts) {
|
|
|
- // Review current upload, and cancel it if its account doen't exist
|
|
|
- if (mCurrentUpload != null &&
|
|
|
- !AccountUtils.exists(mCurrentUpload.getAccount(), getApplicationContext())) {
|
|
|
- mCurrentUpload.cancel();
|
|
|
- }
|
|
|
- // The rest of uploads are cancelled when they try to start
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Provides a binder object that clients can use to perform operations on
|
|
|
- * the queue of uploads, excepting the addition of new files.
|
|
|
- *
|
|
|
- * Implemented to perform cancellation, pause and resume of existing
|
|
|
- * uploads.
|
|
|
- */
|
|
|
- @Override
|
|
|
- public IBinder onBind(Intent arg0) {
|
|
|
- return mBinder;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Called when ALL the bound clients were onbound.
|
|
|
- */
|
|
|
- @Override
|
|
|
- public boolean onUnbind(Intent intent) {
|
|
|
- ((FileUploaderBinder) mBinder).clearListeners();
|
|
|
- return false; // not accepting rebinding (default behaviour)
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- /**
|
|
|
- * Binder to let client components to perform operations on the queue of
|
|
|
- * uploads.
|
|
|
- *
|
|
|
- * It provides by itself the available operations.
|
|
|
- */
|
|
|
- public class FileUploaderBinder extends Binder implements OnDatatransferProgressListener {
|
|
|
-
|
|
|
- /**
|
|
|
- * Map of listeners that will be reported about progress of uploads from
|
|
|
- * a {@link FileUploaderBinder} instance
|
|
|
- */
|
|
|
- private Map<String, OnDatatransferProgressListener> mBoundListeners = new HashMap<String, OnDatatransferProgressListener>();
|
|
|
-
|
|
|
-// /**
|
|
|
-// * Returns ongoing upload operation. May be null.
|
|
|
-// */
|
|
|
-// public UploadFileOperation getCurrentUploadOperation() {
|
|
|
-// return mCurrentUpload;
|
|
|
-// }
|
|
|
-
|
|
|
- /**
|
|
|
- * Cancels a pending or current upload of a remote file.
|
|
|
- *
|
|
|
- * @param account Owncloud account where the remote file will be stored.
|
|
|
- * @param file A file in the queue of pending uploads
|
|
|
- */
|
|
|
- public void cancel(Account account, OCFile file) {
|
|
|
- // TODO: Remove this comment, when ending the implementation of reliable_uploads
|
|
|
- // From FileUploader && FileUploaderService
|
|
|
- Pair<UploadFileOperation, String> removeResult = mPendingUploads.remove(account, file.getRemotePath());
|
|
|
- UploadFileOperation upload = removeResult.first;
|
|
|
- if (upload != null) {
|
|
|
- upload.cancel();
|
|
|
- } else {
|
|
|
- // updating current references (i.e., uploadStatus of current
|
|
|
- // upload) is handled by updateDataseUploadResult() which is called
|
|
|
- // after upload finishes. Following cancel call makes sure that is
|
|
|
- // does finish right now.
|
|
|
- if (mCurrentUpload != null && mCurrentUpload.isUploadInProgress() &&
|
|
|
- mCurrentUpload.getRemotePath().startsWith(file.getRemotePath()) &&
|
|
|
- account.name.equals(mCurrentAccount.name) ) {
|
|
|
- Log_OC.d(TAG, "Calling cancel for " + file.getRemotePath() + " during upload operation.");
|
|
|
- mCurrentUpload.cancel();
|
|
|
-// } else if(mCancellationPossible.get()){
|
|
|
-// Log_OC.d(TAG, "Calling cancel for " + file.getRemotePath() + " during preparing for upload.");
|
|
|
-// mCancellationRequested.set(true);
|
|
|
- } else {
|
|
|
- Log_OC.d(TAG, "Calling cancel for " + file.getRemotePath() + " while upload is pending.");
|
|
|
- // upload not in progress, but pending.
|
|
|
- // in this case we have to update the db here.
|
|
|
- //OCUpload upload = mPendingUploads.remove(buildRemoteName(account, file));
|
|
|
- OCUpload ocUpload = mUploadsStorageManager.getUploadByLocalPath(upload.getStoragePath())[0];
|
|
|
- ocUpload.setUploadStatus(UploadStatus.UPLOAD_CANCELLED);
|
|
|
- ocUpload.setLastResult(UploadResult.CANCELLED);
|
|
|
- // storagePath inside upload is the temporary path. file
|
|
|
- // contains the correct path used as db reference.
|
|
|
- ocUpload.getOCFile().setStoragePath(file.getStoragePath());
|
|
|
- mUploadsStorageManager.updateUploadStatus(ocUpload);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Cancels a pending or current upload for an account
|
|
|
- *
|
|
|
- * @param account Owncloud accountName where the remote file will be stored.
|
|
|
- */
|
|
|
- public void cancel(Account account) {
|
|
|
- Log_OC.d(TAG, "Account= " + account.name);
|
|
|
-
|
|
|
- if (mCurrentUpload != null) {
|
|
|
- Log_OC.d(TAG, "Current Upload Account= " + mCurrentUpload.getAccount().name);
|
|
|
- if (mCurrentUpload.getAccount().name.equals(account.name)) {
|
|
|
- mCurrentUpload.cancel();
|
|
|
- }
|
|
|
- }
|
|
|
- // Cancel pending uploads
|
|
|
- cancelUploadsForAccount(account);
|
|
|
- }
|
|
|
-
|
|
|
- // TODO: Review: Method from FileUploadService with some changes because the merge with FileUploader
|
|
|
- public void remove(Account account, OCFile file) {
|
|
|
- Pair<UploadFileOperation, String> removeResult = mPendingUploads.remove(account, file.getRemotePath());
|
|
|
- UploadFileOperation upload = removeResult.first;
|
|
|
- //OCUpload upload = mPendingUploads.remove(buildRemoteName(account, file));
|
|
|
- if(upload == null) {
|
|
|
- Log_OC.e(TAG, "Could not delete upload " + file + " from mPendingUploads.");
|
|
|
- }
|
|
|
- int d = mUploadsStorageManager.removeUpload(upload.getStoragePath());
|
|
|
- if(d == 0) {
|
|
|
- Log_OC.e(TAG, "Could not delete upload "+ file.getStoragePath() +" from database.");
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- public void remove(OCUpload upload) {
|
|
|
- int d = mUploadsStorageManager.removeUpload(upload.getUploadId());
|
|
|
- if(d == 0) {
|
|
|
- Log_OC.e(TAG, "Could not delete upload "+ upload.getRemotePath() +" from database.");
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // TODO: Review: Method from FileUploadService with some changes because the merge with FileUploader
|
|
|
- // TODO Complete operation to retry the upload
|
|
|
- /**
|
|
|
- * Puts upload in upload list and tell FileUploadService to upload items in list.
|
|
|
- */
|
|
|
- public void retry(Account account, OCUpload upload) {
|
|
|
-// String uploadKey = buildRemoteName(account, upload.getOCFile());
|
|
|
-// mPendingUploads.put(uploadKey, upload);
|
|
|
- FileUploadService.retry(getApplicationContext(), account, upload);
|
|
|
- }
|
|
|
-
|
|
|
- public void clearListeners() {
|
|
|
- mBoundListeners.clear();
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Returns True when the file described by 'file' is being uploaded to
|
|
|
- * the ownCloud account 'account' or waiting for it
|
|
|
- *
|
|
|
- * If 'file' is a directory, returns 'true' if some of its descendant
|
|
|
- * files is uploading or waiting to upload.
|
|
|
- *
|
|
|
- * Warning: If remote file exists and !forceOverwrite the original file
|
|
|
- * is being returned here. That is, it seems as if the original file is
|
|
|
- * being updated when actually a new file is being uploaded.
|
|
|
- *
|
|
|
- * @param account Owncloud account where the remote file will be stored.
|
|
|
- * @param file A file that could be in the queue of pending uploads
|
|
|
- */
|
|
|
- public boolean isUploading(Account account, OCFile file) {
|
|
|
- if (account == null || file == null)
|
|
|
- return false;
|
|
|
- return (mPendingUploads.contains(account, file.getRemotePath()));
|
|
|
- // Commented code from FileUploadService
|
|
|
-// String targetKey = buildRemoteName(account, file);
|
|
|
-// synchronized (mPendingUploads) {
|
|
|
-// if (file.isFolder()) {
|
|
|
-// // this can be slow if there are many uploads :(
|
|
|
-// Iterator<String> it = mPendingUploads.keySet().iterator();
|
|
|
-// boolean found = false;
|
|
|
-// while (it.hasNext() && !found) {
|
|
|
-// found = it.next().startsWith(targetKey);
|
|
|
-// }
|
|
|
-// return found;
|
|
|
-// } else {
|
|
|
-// return (mPendingUploads.containsKey(targetKey));
|
|
|
-// }
|
|
|
-// }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Adds a listener interested in the progress of the upload for a
|
|
|
- * concrete file.
|
|
|
- *
|
|
|
- * @param listener Object to notify about progress of transfer.
|
|
|
- * @param account ownCloud account holding the file of interest.
|
|
|
- * @param file {@link OCFile} of interest for listener.
|
|
|
- */
|
|
|
- public void addDatatransferProgressListener(OnDatatransferProgressListener listener, Account account,
|
|
|
- OCFile file, long uploadId) {
|
|
|
- if (account == null || file == null || listener == null)
|
|
|
- return;
|
|
|
- String targetKey = buildRemoteName(account, file, uploadId);
|
|
|
- mBoundListeners.put(targetKey, listener);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Removes a listener interested in the progress of the upload for a
|
|
|
- * concrete file.
|
|
|
- *
|
|
|
- * @param listener Object to notify about progress of transfer.
|
|
|
- * @param account ownCloud account holding the file of interest.
|
|
|
- * @param file {@link OCFile} of interest for listener.
|
|
|
- */
|
|
|
- public void removeDatatransferProgressListener(OnDatatransferProgressListener listener, Account account,
|
|
|
- OCFile file, long uploadId) {
|
|
|
- if (account == null || file == null || listener == null)
|
|
|
- return;
|
|
|
- String targetKey = buildRemoteName(account, file, uploadId);
|
|
|
- if (mBoundListeners.get(targetKey) == listener) {
|
|
|
- mBoundListeners.remove(targetKey);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- // TODO: Review: Method from FileUploadService with some changes because the merge with FileUploader
|
|
|
- @Override
|
|
|
- public void onTransferProgress(long progressRate, long totalTransferredSoFar, long totalToTransfer,
|
|
|
- String fileName) {
|
|
|
-
|
|
|
- OCFile uploadFileKey = mCurrentUpload.getFile();
|
|
|
- if(mCurrentUpload.wasRenamed()){
|
|
|
- uploadFileKey = mCurrentUpload.getOldFile();
|
|
|
- }
|
|
|
- String key = buildRemoteName(mCurrentUpload.getAccount(), uploadFileKey,
|
|
|
- mCurrentUpload.getOCUploadId());
|
|
|
- OnDatatransferProgressListener boundListener = mBoundListeners.get(key);
|
|
|
- if (boundListener != null) {
|
|
|
- boundListener.onTransferProgress(progressRate, totalTransferredSoFar,
|
|
|
- totalToTransfer, fileName);
|
|
|
- }
|
|
|
-//
|
|
|
-// Set<Entry<String, OCUpload>> uploads = mPendingUploads.entrySet();
|
|
|
-// UploadFileOperation currentUpload = mCurrentUpload;
|
|
|
-// if (currentUpload == null) {
|
|
|
-// Log_OC.e(TAG, "Found no current upload with remote path " + localFileName + ". Ignore.");
|
|
|
-// return;
|
|
|
-// }
|
|
|
-// String key = buildRemoteName(currentUpload.getAccount(), currentUpload.getFile());
|
|
|
-// OnDatatransferProgressListener boundListener = mBoundListeners.get(key);
|
|
|
-// if (boundListener != null) {
|
|
|
-// boundListener.onTransferProgress(progressRate, totalTransferredSoFar, totalToTransfer, localFileName);
|
|
|
-// }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Builds a key for the map of listeners.
|
|
|
- *
|
|
|
- * TODO remove and replace key with file.getFileId() after changing current policy (upload file, then
|
|
|
- * add to local database) to better policy (add to local database, then upload)
|
|
|
- *
|
|
|
- * @param account ownCloud account where the file to upload belongs.
|
|
|
- * @param file File to upload
|
|
|
- * @return Key
|
|
|
- */
|
|
|
- private String buildRemoteName(Account account, OCFile file, long uploadId) {
|
|
|
- String suffix = String.valueOf(uploadId);
|
|
|
- if (uploadId != -1) {
|
|
|
- suffix = "";
|
|
|
- }
|
|
|
- return account.name + file.getRemotePath() + suffix;
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- // TODO: Remove this comment: Class totally replaced by FileUploader ServiceHandler
|
|
|
- // TODO: Review merge modifications
|
|
|
- /**
|
|
|
- * Upload worker. Performs the pending uploads in the order they were
|
|
|
- * requested.
|
|
|
- *
|
|
|
- * Created with the Looper of a new thread, started in
|
|
|
- * {@link FileUploadService#onCreate()}.
|
|
|
- */
|
|
|
- private static class ServiceHandler extends Handler {
|
|
|
- // don't make it a final class, and don't remove the static ; lint will
|
|
|
- // warn about a possible memory leak
|
|
|
- FileUploadService mService;
|
|
|
-
|
|
|
- public ServiceHandler(Looper looper, FileUploadService service) {
|
|
|
- super(looper);
|
|
|
- if (service == null)
|
|
|
- throw new IllegalArgumentException("Received invalid NULL in parameter 'service'");
|
|
|
- mService = service;
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public void handleMessage(Message msg) {
|
|
|
- @SuppressWarnings("unchecked")
|
|
|
- AbstractList<String> requestedUploads = (AbstractList<String>) msg.obj;
|
|
|
- if (msg.obj != null) {
|
|
|
- Iterator<String> it = requestedUploads.iterator();
|
|
|
- while (it.hasNext()) {
|
|
|
- mService.uploadFile(it.next());
|
|
|
- }
|
|
|
- }
|
|
|
- Log_OC.d(TAG, "Stopping command after id " + msg.arg1);
|
|
|
- mService.stopSelf(msg.arg1);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // TODO: Method from FileUploader
|
|
|
- /**
|
|
|
- * Core upload method: sends the file(s) to upload
|
|
|
- *
|
|
|
- * @param uploadKey Key to access the upload to perform, contained in mPendingUploads
|
|
|
- */
|
|
|
- public void uploadFile(String uploadKey) {
|
|
|
-
|
|
|
- mCurrentUpload = mPendingUploads.get(uploadKey);
|
|
|
-
|
|
|
- if (mCurrentUpload != null) {
|
|
|
- // Detect if the account exists
|
|
|
- if (AccountUtils.exists(mCurrentUpload.getAccount(), getApplicationContext())) {
|
|
|
- Log_OC.d(TAG, "Account " + mCurrentUpload.getAccount().name + " exists");
|
|
|
-
|
|
|
- mCurrentUpload.addDatatransferProgressListener((FileUploaderBinder) mBinder);
|
|
|
- mCurrentUpload.addDatatransferProgressListener(this);
|
|
|
-
|
|
|
- notifyUploadStart(mCurrentUpload);
|
|
|
-
|
|
|
- RemoteOperationResult uploadResult = null, grantResult;
|
|
|
-
|
|
|
- try {
|
|
|
- /// prepare client object to send the request to the ownCloud server
|
|
|
- if (mCurrentAccount == null || !mCurrentAccount.equals(mCurrentUpload.getAccount())) {
|
|
|
- mCurrentAccount = mCurrentUpload.getAccount();
|
|
|
- mStorageManager = new FileDataStorageManager(
|
|
|
- mCurrentAccount,
|
|
|
- getContentResolver()
|
|
|
- );
|
|
|
- } // else, reuse storage manager from previous operation
|
|
|
-
|
|
|
- // always get client from client manager, to get fresh credentials in case of update
|
|
|
- OwnCloudAccount ocAccount = new OwnCloudAccount(mCurrentAccount, this);
|
|
|
- mUploadClient = OwnCloudClientManagerFactory.getDefaultSingleton().
|
|
|
- getClientFor(ocAccount, this);
|
|
|
-
|
|
|
-
|
|
|
- /// check the existence of the parent folder for the file to upload
|
|
|
- String remoteParentPath = new File(mCurrentUpload.getRemotePath()).getParent();
|
|
|
- remoteParentPath = remoteParentPath.endsWith(OCFile.PATH_SEPARATOR) ?
|
|
|
- remoteParentPath : remoteParentPath + OCFile.PATH_SEPARATOR;
|
|
|
- grantResult = grantFolderExistence(remoteParentPath);
|
|
|
-
|
|
|
- /// perform the upload
|
|
|
- if (grantResult.isSuccess()) {
|
|
|
- /*OCFile parent = mStorageManager.getFileByPath(remoteParentPath);
|
|
|
- mCurrentUpload.getFile().setParentId(parent.getFileId());*/
|
|
|
- uploadResult = mCurrentUpload.execute(mUploadClient);
|
|
|
- if (uploadResult.isSuccess()) {
|
|
|
- saveUploadedFile();
|
|
|
-
|
|
|
- } else if (uploadResult.getCode() == ResultCode.SYNC_CONFLICT) {
|
|
|
- mStorageManager.saveConflict(mCurrentUpload.getFile(),
|
|
|
- mCurrentUpload.getFile().getEtagInConflict());
|
|
|
- }
|
|
|
- } else {
|
|
|
- uploadResult = grantResult;
|
|
|
- }
|
|
|
-
|
|
|
- } catch (Exception e) {
|
|
|
- Log_OC.e(TAG, "Error uploading", e);
|
|
|
- uploadResult = new RemoteOperationResult(e);
|
|
|
-
|
|
|
- } finally {
|
|
|
- Pair<UploadFileOperation, String> removeResult;
|
|
|
- if (mCurrentUpload.wasRenamed()) {
|
|
|
- removeResult = mPendingUploads.removePayload(
|
|
|
- mCurrentAccount,
|
|
|
- mCurrentUpload.getOldFile().getRemotePath()
|
|
|
- );
|
|
|
- mUploadsStorageManager.updateFileIdUpload(mCurrentUpload.getOCUploadId(),
|
|
|
- mCurrentUpload.getFile().getFileId());
|
|
|
- } else {
|
|
|
- removeResult = mPendingUploads.removePayload(
|
|
|
- mCurrentAccount,
|
|
|
- mCurrentUpload.getRemotePath()
|
|
|
- );
|
|
|
- }
|
|
|
-
|
|
|
- /// notify result
|
|
|
- notifyUploadResult(mCurrentUpload, uploadResult);
|
|
|
-
|
|
|
- sendBroadcastUploadFinished(mCurrentUpload, uploadResult, removeResult.second);
|
|
|
- }
|
|
|
-
|
|
|
- } else {
|
|
|
- // Cancel the transfer
|
|
|
- Log_OC.d(TAG, "Account " + mCurrentUpload.getAccount().toString() +
|
|
|
- " doesn't exist");
|
|
|
- cancelUploadsForAccount(mCurrentUpload.getAccount());
|
|
|
-
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- // TODO: Replaced by uploadFile(String uploadKey)
|
|
|
- /**
|
|
|
- * Core upload method: sends the file(s) to upload. This function blocks
|
|
|
- * until upload succeeded or failed.
|
|
|
- *
|
|
|
- * Before uploading starts mCurrentUpload is set.
|
|
|
- *
|
|
|
- * @param OCUpload Key to access the upload to perform, contained in
|
|
|
- * mPendingUploads
|
|
|
- * @return RemoteOperationResult of upload operation.
|
|
|
- */
|
|
|
-// private RemoteOperationResult uploadFile(OCUpload OCUpload) {
|
|
|
-//
|
|
|
-// if (mCurrentUpload != null) {
|
|
|
-// Log_OC.e(TAG,
|
|
|
-// "mCurrentUpload != null. Meaning there is another upload in progress, cannot start a new one. Fix that!");
|
|
|
-// return new RemoteOperationResult(new IllegalStateException("mCurrentUpload != null when calling uploadFile()"));
|
|
|
-// }
|
|
|
-//
|
|
|
-// AccountManager aMgr = AccountManager.get(this);
|
|
|
-// Account account = OCUpload.getAccount(getApplicationContext());
|
|
|
-// String version = aMgr.getUserData(account, Constants.KEY_OC_VERSION);
|
|
|
-// OwnCloudVersion ocv = new OwnCloudVersion(version);
|
|
|
-//
|
|
|
-// boolean chunked = FileUploadService.chunkedUploadIsSupported(ocv);
|
|
|
-// String uploadKey = null;
|
|
|
-//
|
|
|
-// uploadKey = buildRemoteName(account, OCUpload.getRemotePath());
|
|
|
-// OCFile file = OCUpload.getOCFile();
|
|
|
-// Log_OC.d(TAG, "mCurrentUpload = new UploadFileOperation");
|
|
|
-// mCurrentUpload = new UploadFileOperation(account, file, chunked, OCUpload.isForceOverwrite(),
|
|
|
-// OCUpload.getLocalAction(), getApplicationContext());
|
|
|
-// if (OCUpload.isCreateRemoteFolder()) {
|
|
|
-// mCurrentUpload.setRemoteFolderToBeCreated();
|
|
|
-// }
|
|
|
-// mCurrentUpload.addDatatransferProgressListener((FileUploaderBinder) mBinder);
|
|
|
-// mCurrentUpload.addDatatransferProgressListener(this);
|
|
|
-//
|
|
|
-// mCancellationRequested.set(false);
|
|
|
-// mCancellationPossible.set(true);
|
|
|
-// notifyUploadStart(mCurrentUpload);
|
|
|
-//
|
|
|
-// RemoteOperationResult uploadResult = null, grantResult = null;
|
|
|
-// try {
|
|
|
-// // prepare client object to send requests to the ownCloud
|
|
|
-// // server
|
|
|
-// if (mUploadClient == null || !mCurrentAccount.equals(mCurrentUpload.getAccount())) {
|
|
|
-// mCurrentAccount = mCurrentUpload.getAccount();
|
|
|
-// mStorageManager = new FileDataStorageManager(mCurrentAccount, getContentResolver());
|
|
|
-// OwnCloudAccount ocAccount = new OwnCloudAccount(mCurrentAccount, this);
|
|
|
-// mUploadClient = OwnCloudClientManagerFactory.getDefaultSingleton().getClientFor(ocAccount, this);
|
|
|
-// }
|
|
|
-//
|
|
|
-// // check the existence of the parent folder for the file to
|
|
|
-// // upload
|
|
|
-// String remoteParentPath = new File(mCurrentUpload.getRemotePath()).getParent();
|
|
|
-// remoteParentPath = remoteParentPath.endsWith(OCFile.PATH_SEPARATOR) ? remoteParentPath : remoteParentPath
|
|
|
-// + OCFile.PATH_SEPARATOR;
|
|
|
-// //TODO this might take a moment and should thus be cancelable, for now: cancel afterwards.
|
|
|
-// grantResult = grantFolderExistence(mCurrentUpload, remoteParentPath);
|
|
|
-//
|
|
|
-// if(mCancellationRequested.get()) {
|
|
|
-// throw new OperationCancelledException();
|
|
|
-// }
|
|
|
-// mCancellationPossible.set(false);
|
|
|
-//
|
|
|
-// // perform the upload
|
|
|
-// if (grantResult.isSuccess()) {
|
|
|
-// OCFile parent = mStorageManager.getFileByPath(remoteParentPath);
|
|
|
-// mCurrentUpload.getFile().setParentId(parent.getFileId());
|
|
|
-// // inside this call the remote path may be changed (if remote
|
|
|
-// // file exists and !forceOverwrite) in this case the map from
|
|
|
-// // mPendingUploads is wrong. This results in an upload
|
|
|
-// // indication in the GUI showing that the original file is being
|
|
|
-// // uploaded (instead that a new one is created)
|
|
|
-// uploadResult = mCurrentUpload.execute(mUploadClient);
|
|
|
-// if (uploadResult.isSuccess()) {
|
|
|
-// saveUploadedFile(mCurrentUpload);
|
|
|
-// }
|
|
|
-// } else {
|
|
|
-// uploadResult = grantResult;
|
|
|
-// }
|
|
|
-//
|
|
|
-// } catch (AccountsException e) {
|
|
|
-// Log_OC.e(TAG, "Error while trying to get autorization for " + mCurrentAccount.name, e);
|
|
|
-// uploadResult = new RemoteOperationResult(e);
|
|
|
-//
|
|
|
-// } catch (IOException e) {
|
|
|
-// Log_OC.e(TAG, "Error while trying to get autorization for " + mCurrentAccount.name, e);
|
|
|
-// uploadResult = new RemoteOperationResult(e);
|
|
|
-//
|
|
|
-// } catch (OperationCancelledException e) {
|
|
|
-// uploadResult = new RemoteOperationResult(e);
|
|
|
-// } finally {
|
|
|
-// Log_OC.d(TAG, "Remove CurrentUploadItem from pending upload Item Map.");
|
|
|
-// if (uploadResult.isException()) {
|
|
|
-// // enforce the creation of a new client object for next
|
|
|
-// // uploads; this grant that a new socket will
|
|
|
-// // be created in the future if the current exception is due
|
|
|
-// // to an abrupt lose of network connection
|
|
|
-// mUploadClient = null;
|
|
|
-// }
|
|
|
-// }
|
|
|
-// return uploadResult;
|
|
|
-// }
|
|
|
-
|
|
|
- /**
|
|
|
- * Checks the existence of the folder where the current file will be uploaded both
|
|
|
- * in the remote server and in the local database.
|
|
|
- *
|
|
|
- * If the upload is set to enforce the creation of the folder, the method tries to
|
|
|
- * create it both remote and locally.
|
|
|
- *
|
|
|
- * @param pathToGrant Full remote path whose existence will be granted.
|
|
|
- * @return An {@link OCFile} instance corresponding to the folder where the file
|
|
|
- * will be uploaded.
|
|
|
- */
|
|
|
- private RemoteOperationResult grantFolderExistence(String pathToGrant) {
|
|
|
- RemoteOperation operation = new ExistenceCheckRemoteOperation(pathToGrant, this, false);
|
|
|
- RemoteOperationResult result = operation.execute(mUploadClient);
|
|
|
- if (!result.isSuccess() && result.getCode() == ResultCode.FILE_NOT_FOUND &&
|
|
|
- mCurrentUpload.isRemoteFolderToBeCreated()) {
|
|
|
- SyncOperation syncOp = new CreateFolderOperation( pathToGrant, true);
|
|
|
- result = syncOp.execute(mUploadClient, mStorageManager);
|
|
|
- }
|
|
|
- if (result.isSuccess()) {
|
|
|
- OCFile parentDir = mStorageManager.getFileByPath(pathToGrant);
|
|
|
- if (parentDir == null) {
|
|
|
- parentDir = createLocalFolder(pathToGrant);
|
|
|
- }
|
|
|
- if (parentDir != null) {
|
|
|
- result = new RemoteOperationResult(ResultCode.OK);
|
|
|
- } else {
|
|
|
- result = new RemoteOperationResult(ResultCode.UNKNOWN_ERROR);
|
|
|
- }
|
|
|
- }
|
|
|
- return result;
|
|
|
- }
|
|
|
-
|
|
|
- private OCFile createLocalFolder(String remotePath) {
|
|
|
- String parentPath = new File(remotePath).getParent();
|
|
|
- parentPath = parentPath.endsWith(OCFile.PATH_SEPARATOR) ?
|
|
|
- parentPath : parentPath + OCFile.PATH_SEPARATOR;
|
|
|
- OCFile parent = mStorageManager.getFileByPath(parentPath);
|
|
|
- if (parent == null) {
|
|
|
- parent = createLocalFolder(parentPath);
|
|
|
- }
|
|
|
- if (parent != null) {
|
|
|
- OCFile createdFolder = new OCFile(remotePath);
|
|
|
- createdFolder.setMimetype("DIR");
|
|
|
- createdFolder.setParentId(parent.getFileId());
|
|
|
- mStorageManager.saveFile(createdFolder);
|
|
|
- return createdFolder;
|
|
|
- }
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- /**
|
|
|
- * Saves a OC File after a successful upload.
|
|
|
- *
|
|
|
- * A PROPFIND is necessary to keep the props in the local database
|
|
|
- * synchronized with the server, specially the modification time and Etag
|
|
|
- * (where available)
|
|
|
- *
|
|
|
- * TODO move into UploadFileOperation
|
|
|
- */
|
|
|
- private void saveUploadedFile() {
|
|
|
- OCFile file = mCurrentUpload.getFile();
|
|
|
- if (file.fileExists()) {
|
|
|
- file = mStorageManager.getFileById(file.getFileId());
|
|
|
- }
|
|
|
- long syncDate = System.currentTimeMillis();
|
|
|
- file.setLastSyncDateForData(syncDate);
|
|
|
-
|
|
|
- // new PROPFIND to keep data consistent with server
|
|
|
- // in theory, should return the same we already have
|
|
|
- ReadRemoteFileOperation operation =
|
|
|
- new ReadRemoteFileOperation(mCurrentUpload.getRemotePath());
|
|
|
- RemoteOperationResult result = operation.execute(mUploadClient);
|
|
|
- if (result.isSuccess()) {
|
|
|
- updateOCFile(file, (RemoteFile) result.getData().get(0));
|
|
|
- file.setLastSyncDateForProperties(syncDate);
|
|
|
- } else {
|
|
|
- Log_OC.e(TAG, "Error reading properties of file after successful upload; this is gonna hurt...");
|
|
|
- }
|
|
|
-
|
|
|
- // / maybe this would be better as part of UploadFileOperation... or
|
|
|
- // maybe all this method
|
|
|
- if (mCurrentUpload.wasRenamed()) {
|
|
|
- OCFile oldFile = mCurrentUpload.getOldFile();
|
|
|
- if (oldFile.fileExists()) {
|
|
|
- oldFile.setStoragePath(null);
|
|
|
- mStorageManager.saveFile(oldFile);
|
|
|
- mStorageManager.saveConflict(oldFile, null);
|
|
|
-
|
|
|
- } // else: it was just an automatic renaming due to a name
|
|
|
- // coincidence; nothing else is needed, the storagePath is right
|
|
|
- // in the instance returned by mCurrentUpload.getFile()
|
|
|
- }
|
|
|
- file.setNeedsUpdateThumbnail(true);
|
|
|
- mStorageManager.saveFile(file);
|
|
|
- mStorageManager.saveConflict(file, null);
|
|
|
-
|
|
|
- mStorageManager.triggerMediaScan(file.getStoragePath());
|
|
|
-
|
|
|
- }
|
|
|
-
|
|
|
- private void updateOCFile(OCFile file, RemoteFile remoteFile) {
|
|
|
- file.setCreationTimestamp(remoteFile.getCreationTimestamp());
|
|
|
- file.setFileLength(remoteFile.getLength());
|
|
|
- file.setMimetype(remoteFile.getMimeType());
|
|
|
- file.setModificationTimestamp(remoteFile.getModifiedTimestamp());
|
|
|
- file.setModificationTimestampAtLastSyncForData(remoteFile.getModifiedTimestamp());
|
|
|
- file.setEtag(remoteFile.getEtag());
|
|
|
- file.setRemoteId(remoteFile.getRemoteId());
|
|
|
- }
|
|
|
-
|
|
|
- private OCFile obtainNewOCFileToUpload(String remotePath, String localPath, String mimeType) {
|
|
|
-
|
|
|
- // MIME type
|
|
|
- if (mimeType == null || mimeType.length() <= 0) {
|
|
|
- try {
|
|
|
- mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(
|
|
|
- remotePath.substring(remotePath.lastIndexOf('.') + 1));
|
|
|
- } catch (IndexOutOfBoundsException e) {
|
|
|
- Log_OC.e(TAG, "Trying to find out MIME type of a file without extension: " + remotePath);
|
|
|
- }
|
|
|
- }
|
|
|
- if (mimeType == null) {
|
|
|
- mimeType = "application/octet-stream";
|
|
|
- }
|
|
|
-
|
|
|
- if (isPdfFileFromContentProviderWithoutExtension(localPath, mimeType)){
|
|
|
- remotePath += FILE_EXTENSION_PDF;
|
|
|
- }
|
|
|
-
|
|
|
- OCFile newFile = new OCFile(remotePath);
|
|
|
- newFile.setStoragePath(localPath);
|
|
|
- newFile.setLastSyncDateForProperties(0);
|
|
|
- newFile.setLastSyncDateForData(0);
|
|
|
-
|
|
|
- // size
|
|
|
- if (localPath != null && localPath.length() > 0) {
|
|
|
- File localFile = new File(localPath);
|
|
|
- newFile.setFileLength(localFile.length());
|
|
|
- newFile.setLastSyncDateForData(localFile.lastModified());
|
|
|
- } // don't worry about not assigning size, the problems with localPath
|
|
|
- // are checked when the UploadFileOperation instance is created
|
|
|
-
|
|
|
-
|
|
|
- newFile.setMimetype(mimeType);
|
|
|
-
|
|
|
- return newFile;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- /**
|
|
|
- * Creates a status notification to show the upload progress
|
|
|
- *
|
|
|
- * @param upload Upload operation starting.
|
|
|
- */
|
|
|
- private void notifyUploadStart(UploadFileOperation upload) {
|
|
|
- // / create status notification with a progress bar
|
|
|
- mLastPercent = 0;
|
|
|
- mNotificationBuilder =
|
|
|
- NotificationBuilderWithProgressBar.newNotificationBuilderWithProgressBar(this);
|
|
|
- mNotificationBuilder
|
|
|
- .setOngoing(true)
|
|
|
- .setSmallIcon(R.drawable.notification_icon)
|
|
|
- .setTicker(getString(R.string.uploader_upload_in_progress_ticker))
|
|
|
- .setContentTitle(getString(R.string.uploader_upload_in_progress_ticker))
|
|
|
- .setProgress(100, 0, false)
|
|
|
- .setContentText(
|
|
|
- String.format(getString(R.string.uploader_upload_in_progress_content), 0, upload.getFileName()));
|
|
|
-
|
|
|
- /// includes a pending intent in the notification showing the details
|
|
|
- Intent showUploadListIntent = new Intent(this, UploadListActivity.class);
|
|
|
- showUploadListIntent.putExtra(FileActivity.EXTRA_FILE, upload.getFile());
|
|
|
- showUploadListIntent.putExtra(FileActivity.EXTRA_ACCOUNT, upload.getAccount());
|
|
|
- showUploadListIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
|
|
- mNotificationBuilder.setContentIntent(PendingIntent.getActivity(this, (int) System.currentTimeMillis(),
|
|
|
- showUploadListIntent, 0));
|
|
|
-
|
|
|
- // TODO: Review Old behaviour in FileUploader
|
|
|
- /// includes a pending intent in the notification showing the details view of the file
|
|
|
-// Intent showDetailsIntent = new Intent(this, FileDisplayActivity.class);
|
|
|
-// showDetailsIntent.putExtra(FileActivity.EXTRA_FILE, (Parcelable) upload.getFile());
|
|
|
-// showDetailsIntent.putExtra(FileActivity.EXTRA_ACCOUNT, upload.getAccount());
|
|
|
-// showDetailsIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
|
|
-// mNotificationBuilder.setContentIntent(PendingIntent.getActivity(
|
|
|
-// this, (int) System.currentTimeMillis(), showDetailsIntent, 0
|
|
|
-// ));
|
|
|
-
|
|
|
- mNotificationManager.notify(R.string.uploader_upload_in_progress_ticker, mNotificationBuilder.build());
|
|
|
-
|
|
|
- sendBroadcastUploadStarted(mCurrentUpload);
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
- /**
|
|
|
- * Callback method to update the progress bar in the status notification
|
|
|
- */
|
|
|
- @Override
|
|
|
- public void onTransferProgress(
|
|
|
- long progressRate, long totalTransferredSoFar, long totalToTransfer, String filePath
|
|
|
- ) {
|
|
|
- int percent = (int) (100.0 * ((double) totalTransferredSoFar) / ((double) totalToTransfer));
|
|
|
- if (percent != mLastPercent) {
|
|
|
- mNotificationBuilder.setProgress(100, percent, false);
|
|
|
- String fileName = filePath.substring(filePath.lastIndexOf(FileUtils.PATH_SEPARATOR) + 1);
|
|
|
- String text = String.format(getString(R.string.uploader_upload_in_progress_content), percent, fileName);
|
|
|
- mNotificationBuilder.setContentText(text);
|
|
|
- mNotificationManager.notify(R.string.uploader_upload_in_progress_ticker, mNotificationBuilder.build());
|
|
|
- }
|
|
|
- mLastPercent = percent;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Updates the status notification with the result of an upload operation.
|
|
|
- *
|
|
|
- * @param uploadResult Result of the upload operation.
|
|
|
- * @param upload Finished upload operation
|
|
|
- */
|
|
|
- private void notifyUploadResult(UploadFileOperation upload,
|
|
|
- RemoteOperationResult uploadResult) {
|
|
|
- Log_OC.d(TAG, "NotifyUploadResult with resultCode: " + uploadResult.getCode());
|
|
|
- // / cancelled operation or success -> silent removal of progress
|
|
|
- // notification
|
|
|
- mNotificationManager.cancel(R.string.uploader_upload_in_progress_ticker);
|
|
|
-
|
|
|
- // Show the result: success or fail notification
|
|
|
- if (!uploadResult.isCancelled()) {
|
|
|
- int tickerId = (uploadResult.isSuccess()) ? R.string.uploader_upload_succeeded_ticker
|
|
|
- : R.string.uploader_upload_failed_ticker;
|
|
|
-
|
|
|
- String content; // = null;
|
|
|
-
|
|
|
- // check credentials error
|
|
|
- boolean needsToUpdateCredentials = (
|
|
|
- uploadResult.getCode() == ResultCode.UNAUTHORIZED ||
|
|
|
- uploadResult.isIdPRedirection()
|
|
|
- );
|
|
|
- tickerId = (needsToUpdateCredentials) ?
|
|
|
- R.string.uploader_upload_failed_credentials_error : tickerId;
|
|
|
-
|
|
|
- mNotificationBuilder
|
|
|
- .setTicker(getString(tickerId))
|
|
|
- .setContentTitle(getString(tickerId))
|
|
|
- .setAutoCancel(true)
|
|
|
- .setOngoing(false)
|
|
|
- .setProgress(0, 0, false);
|
|
|
-
|
|
|
- content = ErrorMessageAdapter.getErrorCauseMessage(
|
|
|
- uploadResult, upload, getResources()
|
|
|
- );
|
|
|
-
|
|
|
- if (needsToUpdateCredentials) {
|
|
|
- // let the user update credentials with one click
|
|
|
- Intent updateAccountCredentials = new Intent(this, AuthenticatorActivity.class);
|
|
|
- updateAccountCredentials.putExtra(
|
|
|
- AuthenticatorActivity.EXTRA_ACCOUNT, upload.getAccount()
|
|
|
- );
|
|
|
- updateAccountCredentials.putExtra(
|
|
|
- AuthenticatorActivity.EXTRA_ACTION,
|
|
|
- AuthenticatorActivity.ACTION_UPDATE_EXPIRED_TOKEN);
|
|
|
- updateAccountCredentials.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
|
|
|
- updateAccountCredentials.addFlags(Intent.FLAG_FROM_BACKGROUND);
|
|
|
- mNotificationBuilder.setContentIntent(PendingIntent.getActivity(
|
|
|
- this,
|
|
|
- (int) System.currentTimeMillis(),
|
|
|
- updateAccountCredentials,
|
|
|
- PendingIntent.FLAG_ONE_SHOT));
|
|
|
-
|
|
|
- mUploadClient = null;
|
|
|
- // grant that future retries on the same account will get the fresh credentials
|
|
|
-
|
|
|
- }else {
|
|
|
- mNotificationBuilder.setContentText(content);
|
|
|
- //Changes for compilation
|
|
|
-// if (upload.isInstant()) {
|
|
|
-// DbHandler db = null;
|
|
|
-// try {
|
|
|
-// db = new DbHandler(this.getBaseContext());
|
|
|
-// String message = uploadResult.getLogMessage() + " errorCode: " +
|
|
|
-// uploadResult.getCode();
|
|
|
-// Log_OC.e(TAG, message + " Http-Code: " + uploadResult.getHttpCode());
|
|
|
-// if (uploadResult.getCode() == ResultCode.QUOTA_EXCEEDED) {
|
|
|
-// //message = getString(R.string.failed_upload_quota_exceeded_text);
|
|
|
-// if (db.updateFileState(
|
|
|
-// upload.getOriginalStoragePath(),
|
|
|
-// DbHandler.UPLOAD_STATUS_UPLOAD_FAILED,
|
|
|
-// message) == 0) {
|
|
|
-// db.putFileForLater(
|
|
|
-// upload.getOriginalStoragePath(),
|
|
|
-// upload.getAccount().name,
|
|
|
-// message
|
|
|
-// );
|
|
|
-// }
|
|
|
-// }
|
|
|
-// } finally {
|
|
|
-// if (db != null) {
|
|
|
-// db.close();
|
|
|
-// }
|
|
|
-// }
|
|
|
-// }
|
|
|
- }
|
|
|
-
|
|
|
- updateDatabaseUploadResult(uploadResult, mCurrentUpload);
|
|
|
-
|
|
|
- if(!uploadResult.isSuccess()){
|
|
|
- //in case of failure, do not show details file view (because there is no file!)
|
|
|
- Intent showUploadListIntent = new Intent(this, UploadListActivity.class);
|
|
|
- showUploadListIntent.putExtra(FileActivity.EXTRA_FILE, upload.getFile());
|
|
|
- showUploadListIntent.putExtra(FileActivity.EXTRA_ACCOUNT, upload.getAccount());
|
|
|
- showUploadListIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
|
|
- mNotificationBuilder.setContentIntent(PendingIntent.getActivity(this, (int) System.currentTimeMillis(),
|
|
|
- showUploadListIntent, 0));
|
|
|
- }
|
|
|
-
|
|
|
- mNotificationBuilder.setContentText(content);
|
|
|
- mNotificationManager.notify(tickerId, mNotificationBuilder.build());
|
|
|
-
|
|
|
- if (uploadResult.isSuccess()) {
|
|
|
-//Changes for compilation
|
|
|
-// DbHandler db = new DbHandler(this.getBaseContext());
|
|
|
-// db.removeIUPendingFile(mCurrentUpload.getOriginalStoragePath());
|
|
|
-// db.close();
|
|
|
- mPendingUploads.remove(upload.getAccount(), upload.getFile().getRemotePath());
|
|
|
- //updateDatabaseUploadResult(uploadResult, mCurrentUpload);
|
|
|
- // remove success notification, with a delay of 2 seconds
|
|
|
- NotificationDelayer.cancelWithDelay(mNotificationManager, R.string.uploader_upload_succeeded_ticker,
|
|
|
- 2000);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Updates the persistent upload database with upload result.
|
|
|
- */
|
|
|
- private void updateDatabaseUploadResult(RemoteOperationResult uploadResult, UploadFileOperation upload) {
|
|
|
- // result: success or fail notification
|
|
|
- Log_OC.d(TAG, "updateDataseUploadResult uploadResult: " + uploadResult + " upload: " + upload);
|
|
|
- if (uploadResult.isCancelled()) {
|
|
|
- mUploadsStorageManager.updateUploadStatus(
|
|
|
- upload.getOCUploadId(),
|
|
|
- UploadStatus.UPLOAD_CANCELLED,
|
|
|
- UploadResult.CANCELLED
|
|
|
- );
|
|
|
- } else {
|
|
|
-
|
|
|
- if (uploadResult.isSuccess()) {
|
|
|
- mUploadsStorageManager.updateUploadStatus(
|
|
|
- upload.getOCUploadId(),
|
|
|
- UploadStatus.UPLOAD_SUCCEEDED,
|
|
|
- UploadResult.UPLOADED
|
|
|
- );
|
|
|
- } else {
|
|
|
- // TODO: Disable for testing of menu actions in uploads view
|
|
|
- if (shouldRetryFailedUpload(uploadResult)) {
|
|
|
- mUploadsStorageManager.updateUploadStatus(
|
|
|
- upload.getOCUploadId(), UploadStatus.UPLOAD_FAILED_RETRY,
|
|
|
- UploadResult.fromOperationResult(uploadResult));
|
|
|
- } else {
|
|
|
- mUploadsStorageManager.updateUploadStatus(upload.getOCUploadId(),
|
|
|
- UploadsStorageManager.UploadStatus.UPLOAD_FAILED_GIVE_UP,
|
|
|
- UploadResult.fromOperationResult(uploadResult));
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // TODO: Disable for testing of menu actions in uploads view
|
|
|
-
|
|
|
- /**
|
|
|
- * Determines whether with given uploadResult the upload should be retried later.
|
|
|
- * @param uploadResult
|
|
|
- * @return true if upload should be retried later, false if is should be abandoned.
|
|
|
- */
|
|
|
- private boolean shouldRetryFailedUpload(RemoteOperationResult uploadResult) {
|
|
|
- if (uploadResult.isSuccess()) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- switch (uploadResult.getCode()) {
|
|
|
- case HOST_NOT_AVAILABLE:
|
|
|
- case NO_NETWORK_CONNECTION:
|
|
|
- case TIMEOUT:
|
|
|
- case WRONG_CONNECTION: // SocketException
|
|
|
- return true;
|
|
|
- default:
|
|
|
- return false;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Updates the persistent upload database that upload is in progress.
|
|
|
- */
|
|
|
- private void updateDatabaseUploadStart(UploadFileOperation upload) {
|
|
|
- mUploadsStorageManager.updateUploadStatus(
|
|
|
- upload.getOCUploadId(),
|
|
|
- UploadStatus.UPLOAD_IN_PROGRESS,
|
|
|
- UploadResult.UNKNOWN
|
|
|
- );
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Sends a broadcast in order to the interested activities can update their
|
|
|
- * view
|
|
|
- *
|
|
|
- * @param upload Finished upload operation
|
|
|
- */
|
|
|
- private void sendBroadcastUploadStarted(
|
|
|
- UploadFileOperation upload) {
|
|
|
-
|
|
|
- Intent start = new Intent(getUploadStartMessage());
|
|
|
- start.putExtra(EXTRA_REMOTE_PATH, upload.getRemotePath()); // real remote
|
|
|
- start.putExtra(EXTRA_OLD_FILE_PATH, upload.getOriginalStoragePath());
|
|
|
- start.putExtra(ACCOUNT_NAME, upload.getAccount().name);
|
|
|
-
|
|
|
- updateDatabaseUploadStart(mCurrentUpload);
|
|
|
-
|
|
|
- sendStickyBroadcast(start);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Sends a broadcast in order to the interested activities can update their
|
|
|
- * view
|
|
|
- *
|
|
|
- * @param upload Finished upload operation
|
|
|
- * @param uploadResult Result of the upload operation
|
|
|
- * @param unlinkedFromRemotePath Path in the uploads tree where the upload was unlinked from
|
|
|
- */
|
|
|
- private void sendBroadcastUploadFinished(
|
|
|
- UploadFileOperation upload,
|
|
|
- RemoteOperationResult uploadResult,
|
|
|
- String unlinkedFromRemotePath) {
|
|
|
-
|
|
|
- Intent end = new Intent(getUploadFinishMessage());
|
|
|
- end.putExtra(EXTRA_REMOTE_PATH, upload.getRemotePath()); // real remote
|
|
|
- // path, after
|
|
|
- // possible
|
|
|
- // automatic
|
|
|
- // renaming
|
|
|
- if (upload.wasRenamed()) {
|
|
|
- end.putExtra(EXTRA_OLD_REMOTE_PATH, upload.getOldFile().getRemotePath());
|
|
|
- }
|
|
|
- end.putExtra(EXTRA_OLD_FILE_PATH, upload.getOriginalStoragePath());
|
|
|
- end.putExtra(ACCOUNT_NAME, upload.getAccount().name);
|
|
|
- end.putExtra(EXTRA_UPLOAD_RESULT, uploadResult.isSuccess());
|
|
|
- if (unlinkedFromRemotePath != null) {
|
|
|
- end.putExtra(EXTRA_LINKED_TO_PATH, unlinkedFromRemotePath);
|
|
|
- }
|
|
|
-
|
|
|
- updateDatabaseUploadResult(uploadResult, mCurrentUpload);
|
|
|
-
|
|
|
- sendStickyBroadcast(end);
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- // TODO: Remove. Replace by sendBroadcastUploadFinished(UploadFileOperation, RemoteOperationResult, String)
|
|
|
-// /**
|
|
|
-// * Sends a broadcast in order to the interested activities can update their
|
|
|
-// * view
|
|
|
-// * @param uploadResult Result of the upload operation
|
|
|
-// * @param upload Finished upload operation
|
|
|
-// */
|
|
|
-// private void sendFinalBroadcast(RemoteOperationResult uploadResult, UploadFileOperation upload) {
|
|
|
-// Intent end = new Intent(getUploadFinishMessage());
|
|
|
-// end.putExtra(EXTRA_REMOTE_PATH, upload.getRemotePath()); // real remote
|
|
|
-// // path, after
|
|
|
-// // possible
|
|
|
-// // automatic
|
|
|
-// // renaming
|
|
|
-// if (upload.wasRenamed()) {
|
|
|
-// end.putExtra(EXTRA_OLD_REMOTE_PATH, upload.getOldFile().getRemotePath());
|
|
|
-// }
|
|
|
-// end.putExtra(EXTRA_OLD_FILE_PATH, upload.getOriginalStoragePath());
|
|
|
-// end.putExtra(ACCOUNT_NAME, upload.getAccount().name);
|
|
|
-// end.putExtra(EXTRA_UPLOAD_RESULT, uploadResult.isSuccess());
|
|
|
-// sendStickyBroadcast(end);
|
|
|
-// }
|
|
|
-
|
|
|
- /**
|
|
|
- * Checks if content provider, using the content:// scheme, returns a file with mime-type
|
|
|
- * 'application/pdf' but file has not extension
|
|
|
- * @param localPath Full path to a file in the local file system.
|
|
|
- * @param mimeType MIME type of the file.
|
|
|
- * @return true if is needed to add the pdf file extension to the file
|
|
|
- *
|
|
|
- * TODO - move to OCFile or Utils class
|
|
|
- */
|
|
|
- private boolean isPdfFileFromContentProviderWithoutExtension(String localPath,
|
|
|
- String mimeType) {
|
|
|
- return localPath.startsWith(UriUtils.URI_CONTENT_SCHEME) &&
|
|
|
- mimeType.equals(MIME_TYPE_PDF) &&
|
|
|
- !localPath.endsWith(FILE_EXTENSION_PDF);
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Remove uploads of an account
|
|
|
- *
|
|
|
- * @param account Downloads account to remove
|
|
|
- */
|
|
|
- private void cancelUploadsForAccount(Account account){
|
|
|
- // Cancel pending uploads
|
|
|
- mPendingUploads.remove(account);
|
|
|
- }
|
|
|
-
|
|
|
-// TODO: Remove
|
|
|
-// /**
|
|
|
-// * Remove uploads of an account
|
|
|
-// * @param accountName Name of an OC account
|
|
|
-// */
|
|
|
-// private void cancelUploadForAccount(String accountName){
|
|
|
-// // this can be slow if there are many uploads :(
|
|
|
-// Iterator<String> it = mPendingUploads.keySet().iterator();
|
|
|
-// Log_OC.d(TAG, "Number of pending updloads= " + mPendingUploads.size());
|
|
|
-// while (it.hasNext()) {
|
|
|
-// String key = it.next();
|
|
|
-// Log_OC.d(TAG, "mPendingUploads CANCELLED " + key);
|
|
|
-// if (key.startsWith(accountName)) {
|
|
|
-// synchronized (mPendingUploads) {
|
|
|
-// mPendingUploads.remove(key);
|
|
|
-// }
|
|
|
-// }
|
|
|
-// }
|
|
|
-// }
|
|
|
-
|
|
|
-
|
|
|
- // TODO: onHandleIntent not used in the new FileUploadService
|
|
|
- // TODO: Remove when clean code
|
|
|
- /**
|
|
|
- * The IntentService calls this method from the default worker thread with
|
|
|
- * the intent that started the service. When this method returns,
|
|
|
- * IntentService stops the service, as appropriate.
|
|
|
- *
|
|
|
- * Note: We use an IntentService here. It does not provide simultaneous
|
|
|
- * requests, but instead internally queues them and gets them to this
|
|
|
- * onHandleIntent method one after another. This makes implementation less
|
|
|
- * error-prone but prevents files to be added to list while another upload
|
|
|
- * is active. If everything else works fine, fixing this should be a TODO.
|
|
|
- *
|
|
|
- * Entry point to add one or several files to the queue of uploads.
|
|
|
- *
|
|
|
- * New uploads are added calling to startService(), resulting in a call to
|
|
|
- * this method. This ensures the service will keep on working although the
|
|
|
- * caller activity goes away.
|
|
|
- *
|
|
|
- * First, onHandleIntent() stores all information associated with the upload
|
|
|
- * in a {@link OCUpload} which is stored persistently using
|
|
|
- * {@link UploadsStorageManager}. Then, the oldest, pending upload from
|
|
|
- * {@link UploadsStorageManager} is taken and upload is started.
|
|
|
- * @param intentStartId
|
|
|
- */
|
|
|
-//
|
|
|
-// protected void onHandleIntent(Intent intent, int intentStartId) {
|
|
|
-// Log_OC.d(TAG, "onHandleIntent start");
|
|
|
-// //Log_OC.d(TAG, "mPendingUploads size:" + mPendingUploads.size() + " - before adding new uploads.");
|
|
|
-// Log_OC.d(TAG, "mPendingUploads size:" + mPendingUploads.toString() + " - before adding new uploads.");
|
|
|
-// if (intent == null || intent.hasExtra(KEY_RETRY)) {
|
|
|
-// Log_OC.d(TAG, "Received null intent.");
|
|
|
-// // service was restarted by OS or connectivity change was detected or
|
|
|
-// // retry of pending upload was requested.
|
|
|
-// // ==> First check persistent uploads, then perform upload.
|
|
|
-// int countAddedEntries = 0;
|
|
|
-// OCUpload[] list = mUploadsStorageManager.getPendingUploads();
|
|
|
-// for (OCUpload OCUpload : list) {
|
|
|
-// Log_OC.d(TAG, "Retrieved from DB: " + OCUpload.toFormattedString());
|
|
|
-//
|
|
|
-// String uploadKey = buildRemoteName(OCUpload);
|
|
|
-// OCUpload previous = mPendingUploads.putIfAbsent(uploadKey, OCUpload);
|
|
|
-// if(previous == null) {
|
|
|
-// Log_OC.d(TAG, "mPendingUploads added: " + OCUpload.toFormattedString());
|
|
|
-// countAddedEntries++;
|
|
|
-// } else {
|
|
|
-// //already pending. ignore.
|
|
|
-// }
|
|
|
-// }
|
|
|
-// Log_OC.d(TAG, "added " + countAddedEntries
|
|
|
-// + " entrie(s) to mPendingUploads (this should be 0 except for the first time).");
|
|
|
-// // null intent is received when charging or wifi state changes.
|
|
|
-// // fake a mUploadsStorageManager change event, so that GUI can update the reason for
|
|
|
-// // LATER status of uploads.
|
|
|
-// mUploadsStorageManager.notifyObserversNow();
|
|
|
-// } else {
|
|
|
-// Log_OC.d(TAG, "Receive upload intent.");
|
|
|
-// UploadQuantity uploadType = (UploadQuantity) intent.getSerializableExtra(KEY_UPLOAD_TYPE);
|
|
|
-// if (uploadType == null) {
|
|
|
-// Log_OC.e(TAG, "Incorrect or no upload type provided");
|
|
|
-// return;
|
|
|
-// }
|
|
|
-//
|
|
|
-// Account account = intent.getParcelableExtra(KEY_ACCOUNT);
|
|
|
-// if (!AccountUtils.exists(account, getApplicationContext())) {
|
|
|
-// Log_OC.e(TAG, "KEY_ACCOUNT no set or provided KEY_ACCOUNT does not exist");
|
|
|
-// return;
|
|
|
-// }
|
|
|
-// mStorageManager = new FileDataStorageManager(account, getContentResolver());
|
|
|
-//
|
|
|
-// OCFile[] files = null;
|
|
|
-// // if KEY_FILE given, use it
|
|
|
-// if (intent.hasExtra(KEY_FILE)) {
|
|
|
-// if (uploadType == UploadQuantity.UPLOAD_SINGLE_FILE) {
|
|
|
-// files = new OCFile[] { intent.getParcelableExtra(KEY_FILE) };
|
|
|
-// } else {
|
|
|
-// files = (OCFile[]) intent.getParcelableArrayExtra(KEY_FILE);
|
|
|
-// }
|
|
|
-//
|
|
|
-// } else { // else use KEY_LOCAL_FILE and KEY_REMOTE_FILE
|
|
|
-//
|
|
|
-// if (!intent.hasExtra(KEY_LOCAL_FILE) || !intent.hasExtra(KEY_REMOTE_FILE)) {
|
|
|
-// Log_OC.e(TAG, "Not enough information provided in intent");
|
|
|
-// return;
|
|
|
-// }
|
|
|
-//
|
|
|
-// String[] localPaths;
|
|
|
-// String[] remotePaths;
|
|
|
-// String[] mimeTypes;
|
|
|
-// if (uploadType == UploadQuantity.UPLOAD_SINGLE_FILE) {
|
|
|
-// localPaths = new String[] { intent.getStringExtra(KEY_LOCAL_FILE) };
|
|
|
-// remotePaths = new String[] { intent.getStringExtra(KEY_REMOTE_FILE) };
|
|
|
-// mimeTypes = new String[] { intent.getStringExtra(KEY_MIME_TYPE) };
|
|
|
-// } else {
|
|
|
-// localPaths = intent.getStringArrayExtra(KEY_LOCAL_FILE);
|
|
|
-// remotePaths = intent.getStringArrayExtra(KEY_REMOTE_FILE);
|
|
|
-// mimeTypes = intent.getStringArrayExtra(KEY_MIME_TYPE);
|
|
|
-// }
|
|
|
-// if (localPaths.length != remotePaths.length) {
|
|
|
-// Log_OC.e(TAG, "Different number of remote paths and local paths!");
|
|
|
-// return;
|
|
|
-// }
|
|
|
-//
|
|
|
-// files = new OCFile[localPaths.length];
|
|
|
-//
|
|
|
-// for (int i = 0; i < localPaths.length; i++) {
|
|
|
-// files[i] = obtainNewOCFileToUpload(remotePaths[i], localPaths[i],
|
|
|
-// ((mimeTypes != null) ? mimeTypes[i] : (String) null));
|
|
|
-// if (files[i] == null) {
|
|
|
-// Log_OC.e(TAG, "obtainNewOCFileToUpload() returned null for remotePaths[i]:" + remotePaths[i]
|
|
|
-// + " and localPaths[i]:" + localPaths[i]);
|
|
|
-// return;
|
|
|
-// }
|
|
|
-// mStorageManager.saveFile(files[i]);
|
|
|
-// files[i] = mStorageManager.getFileByLocalPath(files[i].getStoragePath());
|
|
|
-// }
|
|
|
-// }
|
|
|
-//
|
|
|
-// // at this point variable "OCFile[] files" is loaded correctly.
|
|
|
-//
|
|
|
-// boolean forceOverwrite = intent.getBooleanExtra(KEY_FORCE_OVERWRITE, false);
|
|
|
-// boolean isCreateRemoteFolder = intent.getBooleanExtra(KEY_CREATE_REMOTE_FOLDER, false);
|
|
|
-// boolean isUseWifiOnly = intent.getBooleanExtra(KEY_WIFI_ONLY, true);
|
|
|
-// boolean isWhileChargingOnly = intent.getBooleanExtra(KEY_WHILE_CHARGING_ONLY, false);
|
|
|
-// long uploadTimestamp = intent.getLongExtra(KEY_UPLOAD_TIMESTAMP, -1);
|
|
|
-//
|
|
|
-// LocalBehaviour localAction = (LocalBehaviour) intent.getSerializableExtra(KEY_LOCAL_BEHAVIOUR);
|
|
|
-// if (localAction == null)
|
|
|
-// localAction = LocalBehaviour.LOCAL_BEHAVIOUR_COPY;
|
|
|
-//
|
|
|
-// // save always persistently path of upload, so it can be retried if
|
|
|
-// // failed.
|
|
|
-// for (int i = 0; i < files.length; i++) {
|
|
|
-// OCUpload upload = new OCUpload(files[i]);
|
|
|
-// upload.setAccountName(account.name);
|
|
|
-// upload.setForceOverwrite(forceOverwrite);
|
|
|
-// upload.setCreateRemoteFolder(isCreateRemoteFolder);
|
|
|
-// upload.setLocalAction(localAction);
|
|
|
-// upload.setUseWifiOnly(isUseWifiOnly);
|
|
|
-// upload.setWhileChargingOnly(isWhileChargingOnly);
|
|
|
-// upload.setUploadTimestamp(uploadTimestamp);
|
|
|
-// upload.setUploadStatus(UploadStatus.UPLOAD_LATER);
|
|
|
-//
|
|
|
-// String uploadKey = buildRemoteName(upload);
|
|
|
-// OCUpload previous = mPendingUploads.putIfAbsent(uploadKey, upload);
|
|
|
-//
|
|
|
-// if(previous == null)
|
|
|
-// {
|
|
|
-// Log_OC.d(TAG, "mPendingUploads added: " + upload.toFormattedString());
|
|
|
-//
|
|
|
-// // if upload was not queued before, we can add it to
|
|
|
-// // database because the user wants the file to be uploaded.
|
|
|
-// // however, it can happened that the user uploaded the same
|
|
|
-// // file before in which case there is an old db entry.
|
|
|
-// // delete that to be sure we have the latest one.
|
|
|
-// if(mUploadsStorageManager.removeUpload(upload.getLocalPath())>0) {
|
|
|
-// Log_OC.w(TAG, "There was an old DB entry " + upload.getLocalPath()
|
|
|
-// + " which had to be removed in order to add new one.");
|
|
|
-// }
|
|
|
-// boolean success = mUploadsStorageManager.storeUpload(upload);
|
|
|
-// if(!success) {
|
|
|
-// Log_OC.e(TAG, "Could not add upload " + upload.getLocalPath()
|
|
|
-// + " to database. This should not happen.");
|
|
|
-// }
|
|
|
-// } else {
|
|
|
-// Log_OC.w(TAG, "FileUploadService got upload intent for file which is already queued: "
|
|
|
-// + upload.getRemotePath());
|
|
|
-// // upload already pending. ignore.
|
|
|
-// }
|
|
|
-// }
|
|
|
-// }
|
|
|
-// // at this point mPendingUploads is filled.
|
|
|
-//
|
|
|
-//
|
|
|
-//
|
|
|
-// Iterator<String> it;
|
|
|
-// if (intent != null && intent.getStringExtra(KEY_RETRY_REMOTE_PATH) != null) {
|
|
|
-// ArrayList<String> list = new ArrayList<String>(1);
|
|
|
-// String remotePath = intent.getStringExtra(KEY_RETRY_REMOTE_PATH);
|
|
|
-// list.add(remotePath);
|
|
|
-// it = list.iterator();
|
|
|
-// // update db status for upload
|
|
|
-// OCUpload OCUpload = mPendingUploads.get(remotePath);
|
|
|
-// OCUpload.setUploadStatus(UploadStatus.UPLOAD_LATER);
|
|
|
-// OCUpload.setLastResult(null);
|
|
|
-// mUploadsStorageManager.updateUploadStatus(OCUpload);
|
|
|
-//
|
|
|
-// Log_OC.d(TAG, "Start uploading " + remotePath);
|
|
|
-// } else {
|
|
|
-// it = mPendingUploads.keySet().iterator();
|
|
|
-// }
|
|
|
-// if (it.hasNext()) {
|
|
|
-// while (it.hasNext()) {
|
|
|
-// String upload = it.next();
|
|
|
-// OCUpload OCUpload = mPendingUploads.get(upload);
|
|
|
-//
|
|
|
-// if (OCUpload == null) {
|
|
|
-// Log_OC.e(TAG, "Cannot upload null. Fix that!");
|
|
|
-// continue;
|
|
|
-// }
|
|
|
-//
|
|
|
-// UploadTask uploadTask = new UploadTask(OCUpload);
|
|
|
-// mUploadExecutor.submit(uploadTask);
|
|
|
-// }
|
|
|
-// StopSelfTask stopSelfTask = new StopSelfTask(intentStartId);
|
|
|
-// mUploadExecutor.submit(stopSelfTask);
|
|
|
-//
|
|
|
-// } else {
|
|
|
-// stopSelf(intentStartId);
|
|
|
-// }
|
|
|
-//
|
|
|
-// Log_OC.d(TAG, "onHandleIntent end");
|
|
|
-// }
|
|
|
-
|
|
|
- // TODO: StopSelfTask not used in the new FileUploadService
|
|
|
- // TODO: Remove when clean code
|
|
|
- /**
|
|
|
- * Stops this services if latest intent id is intentStartId.
|
|
|
- */
|
|
|
-// public class StopSelfTask implements Runnable {
|
|
|
-// int intentStartId;
|
|
|
-//
|
|
|
-// public StopSelfTask(int intentStartId) {
|
|
|
-// this.intentStartId = intentStartId;
|
|
|
-// }
|
|
|
-//
|
|
|
-// @Override
|
|
|
-// public void run() {
|
|
|
-// stopSelf(intentStartId);
|
|
|
-// }
|
|
|
-// }
|
|
|
-
|
|
|
- // TODO: UploaTask not used in the new FileUploadService
|
|
|
- // TODO: Remove when clean code
|
|
|
- /**
|
|
|
- * Tries uploading OCUpload, creates notifications, and updates mUploadsStorageManager.
|
|
|
- */
|
|
|
-// public class UploadTask implements Runnable {
|
|
|
-// OCUpload OCUpload;
|
|
|
-//
|
|
|
-// public UploadTask(OCUpload OCUpload) {
|
|
|
-// this.OCUpload = OCUpload;
|
|
|
-// }
|
|
|
-//
|
|
|
-// @Override
|
|
|
-// public void run() {
|
|
|
-// Log_OC.d(TAG, "mPendingUploads size:" + mPendingUploads.size() + " - before uploading.");
|
|
|
-// switch (canUploadFileNow(OCUpload)) {
|
|
|
-// case NOW:
|
|
|
-// Log_OC.d(TAG, "Calling uploadFile for " + OCUpload.getRemotePath());
|
|
|
-// RemoteOperationResult uploadResult = uploadFile(OCUpload);
|
|
|
-// //TODO store renamed upload path?
|
|
|
-// updateDatabaseUploadResult(uploadResult, mCurrentUpload);
|
|
|
-// notifyUploadResult(uploadResult, mCurrentUpload);
|
|
|
-// sendFinalBroadcast(uploadResult, mCurrentUpload);
|
|
|
-// // TODO: Disable for testing of menu actions in uploads view
|
|
|
-//// if (!shouldRetryFailedUpload(uploadResult)) {
|
|
|
-//// Log_OC.d(TAG, "Upload with result " + uploadResult.getCode() + ": " + uploadResult.getLogMessage()
|
|
|
-//// + " will be abandoned.");
|
|
|
-//// mPendingUploads.remove(buildRemoteName(OCUpload));
|
|
|
-//// }
|
|
|
-// Log_OC.d(TAG, "mCurrentUpload = null");
|
|
|
-// mCurrentUpload = null;
|
|
|
-// break;
|
|
|
-// case LATER:
|
|
|
-// // Schedule retry for later upload. Delay can be due to:
|
|
|
-// // KEY_WIFI_ONLY - done by ConnectivityActionReceiver
|
|
|
-// // KEY_WHILE_CHARGING_ONLY - TODO add PowerConnectionReceiver
|
|
|
-// // KEY_UPLOAD_TIMESTAMP - TODO use AlarmManager to wake up this service
|
|
|
-// break;
|
|
|
-// case FILE_GONE:
|
|
|
-// mUploadsStorageManager.updateUploadStatus(
|
|
|
-// OCUpload.getLocalPath(),
|
|
|
-// UploadStatus.UPLOAD_FAILED_GIVE_UP,
|
|
|
-// com.owncloud.android.db.UploadResult.FILE_ERROR
|
|
|
-// );
|
|
|
-// if (mPendingUploads.remove(OCUpload.getRemotePath()) == null) {
|
|
|
-// Log_OC.w(TAG, "Could remove " + OCUpload.getRemotePath()
|
|
|
-// + " from mPendingUploads because it does not exist.");
|
|
|
-// }
|
|
|
-//
|
|
|
-// break;
|
|
|
-// case ERROR:
|
|
|
-// Log_OC.e(TAG, "canUploadFileNow() returned ERROR. Fix that!");
|
|
|
-// break;
|
|
|
-// }
|
|
|
-// Log_OC.d(TAG, "mPendingUploads size:" + mPendingUploads.size() + " - after uploading.");
|
|
|
-// }
|
|
|
-//
|
|
|
-// }
|
|
|
-
|
|
|
- /**
|
|
|
- * Returns the reason as String why state of OCUpload is LATER. If
|
|
|
- * upload state != LATER return null.
|
|
|
- */
|
|
|
- static public String getUploadLaterReason(Context context, OCUpload OCUpload) {
|
|
|
- StringBuilder reason = new StringBuilder();
|
|
|
- Date now = new Date();
|
|
|
- if (now.getTime() < OCUpload.getUploadTimestamp()) {
|
|
|
- reason.append(context.getString(R.string.uploads_view_later_reason_waiting_for) +
|
|
|
- DisplayUtils.unixTimeToHumanReadable(OCUpload.getUploadTimestamp()));
|
|
|
- }
|
|
|
- if (OCUpload.isUseWifiOnly() && !UploadUtils.isConnectedViaWiFi(context)) {
|
|
|
- if (reason.length() > 0) {
|
|
|
- reason.append(context.getString(R.string.uploads_view_later_reason_add_wifi_reason));
|
|
|
- } else {
|
|
|
- reason.append(context.getString(R.string.uploads_view_later_reason_waiting_for_wifi));
|
|
|
- }
|
|
|
- }
|
|
|
- if (OCUpload.isWhileChargingOnly() && !UploadUtils.isCharging(context)) {
|
|
|
- if (reason.length() > 0) {
|
|
|
- reason.append(context.getString(R.string.uploads_view_later_reason_add_charging_reason));
|
|
|
- } else {
|
|
|
- reason.append(context.getString(R.string.uploads_view_later_reason_waiting_for_charging));
|
|
|
- }
|
|
|
- }
|
|
|
- reason.append(".");
|
|
|
- if (reason.length() > 1) {
|
|
|
- return reason.toString();
|
|
|
- }
|
|
|
- if (OCUpload.getUploadStatus() == UploadStatus.UPLOAD_LATER) {
|
|
|
- return context.getString(R.string.uploads_view_later_waiting_to_upload);
|
|
|
- }
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
- enum CanUploadFileNowStatus {NOW, LATER, FILE_GONE, ERROR};
|
|
|
-
|
|
|
- /**
|
|
|
- * Returns true when the file may be uploaded now. This methods checks all
|
|
|
- * restraints of the passed {@link OCUpload}, these include
|
|
|
- * isUseWifiOnly(), check if local file exists, check if file was already
|
|
|
- * uploaded...
|
|
|
- *
|
|
|
- * If return value is CanUploadFileNowStatus.NOW, uploadFile() may be
|
|
|
- * called.
|
|
|
- *
|
|
|
- * @return CanUploadFileNowStatus.NOW is upload may proceed, <br>
|
|
|
- * CanUploadFileNowStatus.LATER if upload should be performed at a
|
|
|
- * later time, <br>
|
|
|
- * CanUploadFileNowStatus.ERROR if a severe error happened, calling
|
|
|
- * entity should remove upload from queue.
|
|
|
- *
|
|
|
- */
|
|
|
- private CanUploadFileNowStatus canUploadFileNow(OCUpload OCUpload) {
|
|
|
-
|
|
|
- if (OCUpload.getUploadStatus() == UploadStatus.UPLOAD_SUCCEEDED) {
|
|
|
- Log_OC.w(TAG, "Already succeeded uploadObject was again scheduled for upload. Fix that!");
|
|
|
- return CanUploadFileNowStatus.ERROR;
|
|
|
- }
|
|
|
-
|
|
|
- if (OCUpload.isUseWifiOnly()
|
|
|
- && !UploadUtils.isConnectedViaWiFi(getApplicationContext())) {
|
|
|
- Log_OC.d(TAG, "Do not start upload because it is wifi-only.");
|
|
|
- return CanUploadFileNowStatus.LATER;
|
|
|
- }
|
|
|
-
|
|
|
- if(OCUpload.isWhileChargingOnly() && !UploadUtils.isCharging(getApplicationContext())) {
|
|
|
- Log_OC.d(TAG, "Do not start upload because it is while charging only.");
|
|
|
- return CanUploadFileNowStatus.LATER;
|
|
|
- }
|
|
|
- Date now = new Date();
|
|
|
- if (now.getTime() < OCUpload.getUploadTimestamp()) {
|
|
|
- Log_OC.d(
|
|
|
- TAG,
|
|
|
- "Do not start upload because it is schedule for "
|
|
|
- + DisplayUtils.unixTimeToHumanReadable(OCUpload.getUploadTimestamp()));
|
|
|
- return CanUploadFileNowStatus.LATER;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- if (!new File(OCUpload.getLocalPath()).exists()) {
|
|
|
- Log_OC.d(TAG, "Do not start upload because local file does not exist.");
|
|
|
- return CanUploadFileNowStatus.FILE_GONE;
|
|
|
- }
|
|
|
- return CanUploadFileNowStatus.NOW;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Call if all pending uploads are to be retried.
|
|
|
- */
|
|
|
-// public static void retry(Context context) {
|
|
|
-// retry(context, null);
|
|
|
-// }
|
|
|
-
|
|
|
- /**
|
|
|
- * Call to retry upload identified by remotePath
|
|
|
- */
|
|
|
- private static void retry(Context context, Account account, OCUpload upload) {
|
|
|
- Log_OC.d(TAG, "FileUploadService.retry()");
|
|
|
- Intent i = new Intent(context, FileUploadService.class);
|
|
|
- i.putExtra(FileUploadService.KEY_RETRY, true);
|
|
|
- if(upload!= null) {
|
|
|
- i.putExtra(FileUploadService.KEY_ACCOUNT, account);
|
|
|
- i.putExtra(FileUploadService.KEY_RETRY_UPLOAD, upload);
|
|
|
- }
|
|
|
- context.startService(i);
|
|
|
- }
|
|
|
-
|
|
|
-}
|