From: masensio Date: Thu, 19 Feb 2015 11:54:59 +0000 (+0100) Subject: Merge branch 'develop' into cancel_transfer_for_deleted_users X-Git-Tag: oc-android-1.7.1_signed^2~40^2~7 X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/commitdiff_plain/cb175f29949dbac17a3870a71ecff60df5c9bdc4?ds=inline;hp=-c Merge branch 'develop' into cancel_transfer_for_deleted_users Conflicts: AndroidManifest.xml --- cb175f29949dbac17a3870a71ecff60df5c9bdc4 diff --combined AndroidManifest.xml index b520d092,780875b7..f0d1e9dc --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@@ -3,7 -3,7 +3,7 @@@ ownCloud Android client application Copyright (C) 2012 Bartek Przybylski -- Copyright (C) 2012-2014 ownCloud Inc. ++ Copyright (C) 2012-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, @@@ -18,8 -18,8 +18,8 @@@ along with this program. If not, see . --> + android:versionCode="10700000" + android:versionName="1.7.0" xmlns:android="http://schemas.android.com/apk/res/android"> @@@ -86,7 -86,7 +86,6 @@@ android:name=".ui.activity.Preferences" android:theme="@style/Theme.ownCloud" > - - diff --combined src/com/owncloud/android/files/services/FileDownloader.java index efe271d8,cd7afa62..a126028b --- a/src/com/owncloud/android/files/services/FileDownloader.java +++ b/src/com/owncloud/android/files/services/FileDownloader.java @@@ -25,10 -25,8 +25,10 @@@ import java.util.HashMap import java.util.Iterator; import java.util.Map; import java.util.Vector; +import java.util.concurrent.ConcurrentMap; 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; @@@ -111,15 -109,31 +111,31 @@@ public class FileDownloader extends Ser @Override public void onCreate() { super.onCreate(); + Log_OC.d(TAG, "Creating service"); mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); - HandlerThread thread = new HandlerThread("FileDownloaderThread", - Process.THREAD_PRIORITY_BACKGROUND); + HandlerThread thread = new HandlerThread("FileDownloaderThread", Process.THREAD_PRIORITY_BACKGROUND); thread.start(); mServiceLooper = thread.getLooper(); mServiceHandler = new ServiceHandler(mServiceLooper, this); mBinder = new FileDownloaderBinder(); } + + /** + * Service clean up + */ + @Override + public void onDestroy() { + Log_OC.v(TAG, "Destroying service" ); + mBinder = null; + mServiceHandler = null; + mServiceLooper.quit(); + mServiceLooper = null; + mNotificationManager = null; + super.onDestroy(); + } + + /** * Entry point to add one or several files to the queue of downloads. * @@@ -128,6 -142,8 +144,8 @@@ */ @Override public int onStartCommand(Intent intent, int flags, int startId) { + Log_OC.d(TAG, "Starting command with id " + startId); + if ( !intent.hasExtra(EXTRA_ACCOUNT) || !intent.hasExtra(EXTRA_FILE) ) { @@@ -235,8 -251,7 +253,8 @@@ ); Log_OC.v( "NOW " + TAG + ", thread " + Thread.currentThread().getName(), "Removing download of " + file.getRemotePath());*/ - Pair removeResult = mPendingDownloads.remove(account, file.getRemotePath()); + Pair removeResult = + mPendingDownloads.remove(account, file.getRemotePath()); DownloadFileOperation download = removeResult.first; if (download != null) { /*Log_OC.v( "NOW " + TAG + ", thread " + Thread.currentThread().getName(), @@@ -252,42 -267,7 +270,42 @@@ } } } - + + /** + * 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 (mCurrentDownload != null) { + Log_OC.d(TAG, "Current Download Account= " + mCurrentDownload.getAccount().name); + if (mCurrentDownload.getAccount().name.equals(account.name)) { + mCurrentDownload.cancel(); + } + } + // Cancel pending downloads + ConcurrentMap downloadsAccount = mPendingDownloads.get(account); + Iterator it = downloadsAccount.keySet().iterator(); + Log_OC.d(TAG, "Number of pending downloads= " + downloadsAccount.size()); + while (it.hasNext()) { + String key = it.next(); + Log_OC.d(TAG, "download CANCELLED " + key); + if (key.startsWith(account.name)) { + DownloadFileOperation download; + synchronized (mPendingDownloads) { + download = mPendingDownloads.get(key); + if (download != null) { + String remotePath = download.getRemotePath(); + if (mPendingDownloads.contains(account, remotePath)) { + mPendingDownloads.remove(account, remotePath); + } + } + } + } + } + } public void clearListeners() { mBoundListeners.clear(); @@@ -353,17 -333,6 +371,17 @@@ boundListener.onTransferProgress(progressRate, totalTransferredSoFar, totalToTransfer, fileName); } } + + /** + * Review downloads and cancel it if its account doesn't exist + */ + public void reviewDownloads() { + if (mCurrentDownload != null && + !AccountUtils.exists(mCurrentDownload.getAccount(), getApplicationContext())) { + mCurrentDownload.cancel(); + } + // The rest of downloads are cancelled when they try to start + } } @@@ -391,19 -360,18 +409,18 @@@ Iterator it = requestedDownloads.iterator(); while (it.hasNext()) { String next = it.next(); - /*Log_OC.v( "NOW " + TAG + ", thread " + Thread.currentThread().getName(), - "Handling download file " + next);*/ mService.downloadFile(next); } } + Log_OC.d(TAG, "Stopping after command with id " + msg.arg1); mService.stopSelf(msg.arg1); } } - + /** * Core download method: requests a file to download and stores it. - * + * * @param downloadKey Key to access the download to perform, contained in mPendingDownloads */ private void downloadFile(String downloadKey) { @@@ -413,61 -381,54 +430,61 @@@ mCurrentDownload = mPendingDownloads.get(downloadKey); if (mCurrentDownload != null) { - - notifyDownloadStart(mCurrentDownload); - - RemoteOperationResult downloadResult = null; - try { - /// prepare client object to send the request to the ownCloud server - if (mCurrentAccount == null || !mCurrentAccount.equals(mCurrentDownload.getAccount())) { - mCurrentAccount = mCurrentDownload.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); - mDownloadClient = OwnCloudClientManagerFactory.getDefaultSingleton(). - getClientFor(ocAccount, this); - + // Detect if the account exists + if (AccountUtils.exists(mCurrentDownload.getAccount(), getApplicationContext())) { + Log_OC.d(TAG, "Account " + mCurrentDownload.getAccount().toString() + " exists"); + notifyDownloadStart(mCurrentDownload); - /// perform the download - /*Log_OC.v( "NOW " + TAG + ", thread " + Thread.currentThread().getName(), + RemoteOperationResult downloadResult = null; + try { + /// prepare client object to send the request to the ownCloud server + if (mCurrentAccount == null || !mCurrentAccount.equals(mCurrentDownload.getAccount())) { + mCurrentAccount = mCurrentDownload.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); + mDownloadClient = OwnCloudClientManagerFactory.getDefaultSingleton(). + getClientFor(ocAccount, this); + + + /// perform the download + /*Log_OC.v( "NOW " + TAG + ", thread " + Thread.currentThread().getName(), "Executing download of " + mCurrentDownload.getRemotePath());*/ - downloadResult = mCurrentDownload.execute(mDownloadClient); - if (downloadResult.isSuccess()) { - saveDownloadedFile(); - } - - } catch (AccountsException e) { - Log_OC.e(TAG, "Error while trying to get authorization for " + mCurrentAccount.name, e); - downloadResult = new RemoteOperationResult(e); - } catch (IOException e) { - Log_OC.e(TAG, "Error while trying to get authorization for " + mCurrentAccount.name, e); - downloadResult = new RemoteOperationResult(e); - - } finally { + downloadResult = mCurrentDownload.execute(mDownloadClient); + if (downloadResult.isSuccess()) { + saveDownloadedFile(); + } + + } catch (AccountsException e) { + Log_OC.e(TAG, "Error while trying to get authorization for " + mCurrentAccount.name, e); + downloadResult = new RemoteOperationResult(e); + } catch (IOException e) { + Log_OC.e(TAG, "Error while trying to get authorization for " + mCurrentAccount.name, e); + downloadResult = new RemoteOperationResult(e); + + } finally { /*Log_OC.v( "NOW " + TAG + ", thread " + Thread.currentThread().getName(), "Removing payload " + mCurrentDownload.getRemotePath());*/ - Pair removeResult = - mPendingDownloads.removePayload(mCurrentAccount, mCurrentDownload.getRemotePath()); + Pair removeResult = + mPendingDownloads.removePayload(mCurrentAccount, mCurrentDownload.getRemotePath()); - /// notify result - notifyDownloadResult(mCurrentDownload, downloadResult); + /// notify result + notifyDownloadResult(mCurrentDownload, downloadResult); - sendBroadcastDownloadFinished(mCurrentDownload, downloadResult, removeResult.second); - } + sendBroadcastDownloadFinished(mCurrentDownload, downloadResult, removeResult.second); + } + } else { + // Cancel the transfer + Log_OC.d(TAG, "Account " + mCurrentDownload.getAccount().toString() + " doesn't exist"); + cancelDownloadsForAccount(mCurrentDownload.getAccount()); + } } } @@@ -665,32 -626,4 +682,32 @@@ sendStickyBroadcast(added); } + /** + * Remove downloads of an account + * @param account + */ + private void cancelDownloadsForAccount(Account account){ + // Cancel pending downloads + ConcurrentMap downloadsAccount = mPendingDownloads.get(account); + Iterator it = downloadsAccount.keySet().iterator(); + Log_OC.d(TAG, "Number of pending downloads= " + downloadsAccount.size()); + while (it.hasNext()) { + String key = it.next(); + Log_OC.d(TAG, "download CANCELLED " + key); + if (key.startsWith(account.name)) { + DownloadFileOperation download; + synchronized (mPendingDownloads) { + download = mPendingDownloads.get(key); + if (download != null) { + String remotePath = download.getRemotePath(); + if (mPendingDownloads.contains(account, remotePath)) { + mPendingDownloads.remove(account, remotePath); + } + } + } + } + } + } + + } diff --combined src/com/owncloud/android/files/services/FileUploader.java index 3ce1aace,6f77a9c1..ef8bda45 --- a/src/com/owncloud/android/files/services/FileUploader.java +++ b/src/com/owncloud/android/files/services/FileUploader.java @@@ -1,6 -1,6 +1,6 @@@ /* ownCloud Android client application * Copyright (C) 2012 Bartek Przybylski - * Copyright (C) 2012-2013 ownCloud Inc. + * Copyright (C) 2012-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, @@@ -56,7 -56,6 +56,7 @@@ import com.owncloud.android.lib.common. import com.owncloud.android.lib.common.OwnCloudClientManagerFactory; import com.owncloud.android.lib.common.accounts.AccountUtils.Constants; import com.owncloud.android.lib.common.network.OnDatatransferProgressListener; +import com.owncloud.android.lib.common.operations.OperationCancelledException; 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; @@@ -125,14 -124,14 +125,14 @@@ public class FileUploader extends Servi private static final String MIME_TYPE_PDF = "application/pdf"; private static final String FILE_EXTENSION_PDF = ".pdf"; - + public static String getUploadFinishMessage() { return FileUploader.class.getName().toString() + UPLOAD_FINISH_MESSAGE; } - + /** * Builds a key for mPendingUploads from the account and file to upload - * + * * @param account Account where the file to upload is stored * @param file File to upload */ @@@ -146,7 -145,7 +146,7 @@@ /** * 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 @@@ -162,7 -161,7 +162,7 @@@ @Override public void onCreate() { super.onCreate(); - Log_OC.i(TAG, "mPendingUploads size:" + mPendingUploads.size()); + Log_OC.d(TAG, "Creating service"); mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE); HandlerThread thread = new HandlerThread("FileUploaderThread", Process.THREAD_PRIORITY_BACKGROUND); thread.start(); @@@ -172,14 -171,31 +172,31 @@@ } /** + * Service clean up + */ + @Override + public void onDestroy() { + Log_OC.v(TAG, "Destroying service" ); + mBinder = null; + mServiceHandler = null; + mServiceLooper.quit(); + mServiceLooper = null; + mNotificationManager = null; + super.onDestroy(); + } + + + /** * 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. */ @Override public int onStartCommand(Intent intent, int flags, int startId) { + Log_OC.d(TAG, "Starting command with id " + startId); + if (!intent.hasExtra(KEY_ACCOUNT) || !intent.hasExtra(KEY_UPLOAD_TYPE) || !(intent.hasExtra(KEY_LOCAL_FILE) || intent.hasExtra(KEY_FILE))) { Log_OC.e(TAG, "Not enough information provided in intent"); @@@ -230,7 -246,7 +247,7 @@@ boolean forceOverwrite = intent.getBooleanExtra(KEY_FORCE_OVERWRITE, false); boolean isInstant = intent.getBooleanExtra(KEY_INSTANT_UPLOAD, false); int localAction = intent.getIntExtra(KEY_LOCAL_BEHAVIOUR, LOCAL_BEHAVIOUR_COPY); - + if (intent.hasExtra(KEY_FILE) && files == null) { Log_OC.e(TAG, "Incorrect array for OCFiles provided in upload intent"); return Service.START_NOT_STICKY; @@@ -263,7 -279,7 +280,7 @@@ AccountManager aMgr = AccountManager.get(this); String version = aMgr.getUserData(account, Constants.KEY_OC_VERSION); OwnCloudVersion ocv = new OwnCloudVersion(version); - + boolean chunked = FileUploader.chunkedUploadIsSupported(ocv); AbstractList requestedUploads = new Vector(); String uploadKey = null; @@@ -271,7 -287,7 +288,7 @@@ try { for (int i = 0; i < files.length; i++) { uploadKey = buildRemoteName(account, files[i].getRemotePath()); - newUpload = new UploadFileOperation(account, files[i], chunked, isInstant, forceOverwrite, localAction, + newUpload = new UploadFileOperation(account, files[i], chunked, isInstant, forceOverwrite, localAction, getApplicationContext()); if (isInstant) { newUpload.setRemoteFolderToBeCreated(); @@@ -310,7 -326,7 +327,7 @@@ /** * 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. */ @@@ -318,7 -334,7 +335,7 @@@ public IBinder onBind(Intent arg0) { return mBinder; } - + /** * Called when ALL the bound clients were onbound. */ @@@ -327,23 -343,24 +344,23 @@@ ((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 mBoundListeners = new HashMap(); - + /** * 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 */ @@@ -353,48 -370,25 +370,48 @@@ upload = mPendingUploads.remove(buildRemoteName(account, file)); } if (upload != null) { - upload.cancel(); + mCurrentUpload.cancel(); + } + } + + /** + * 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 + Iterator it = mPendingUploads.keySet().iterator(); + Log_OC.d(TAG, "Number of pending uploads= " + mPendingUploads.size()); + while (it.hasNext()) { + String key = it.next(); + Log_OC.d(TAG, "mPendingUploads CANCELLED " + key); + if (key.startsWith(account.name)) { + synchronized (mPendingUploads) { + mPendingUploads.remove(key); + } + } } } - - - + 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. - * + * * @param account ownCloud account where the remote file will be stored. * @param file A file that could be in the queue of pending uploads */ @@@ -420,7 -414,7 +437,7 @@@ /** * 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. @@@ -430,12 -424,12 +447,12 @@@ String targetKey = buildRemoteName(account, file); 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. @@@ -451,30 -445,20 +468,30 @@@ @Override public void onTransferProgress(long progressRate, long totalTransferredSoFar, long totalToTransfer, - String fileName) { + String fileName) { String key = buildRemoteName(mCurrentUpload.getAccount(), mCurrentUpload.getFile()); OnDatatransferProgressListener boundListener = mBoundListeners.get(key); if (boundListener != null) { boundListener.onTransferProgress(progressRate, totalTransferredSoFar, totalToTransfer, fileName); } } - + + /** + * Review uploads and cancel it if its account doesn't exist + */ + public void reviewUploads() { + if (mCurrentUpload != null && + !AccountUtils.exists(mCurrentUpload.getAccount(), getApplicationContext())) { + mCurrentUpload.cancel(); + } + // The rest of uploads are cancelled when they try to start + } } /** * Upload worker. Performs the pending uploads in the order they were * requested. - * + * * Created with the Looper of a new thread, started in * {@link FileUploader#onCreate()}. */ @@@ -500,13 -484,14 +517,14 @@@ mService.uploadFile(it.next()); } } + Log_OC.d(TAG, "Stopping command after id " + msg.arg1); mService.stopSelf(msg.arg1); } } /** * Core upload method: sends the file(s) to upload - * + * * @param uploadKey Key to access the upload to perform, contained in * mPendingUploads */ @@@ -518,72 -503,63 +536,72 @@@ if (mCurrentUpload != null) { - notifyUploadStart(mCurrentUpload); + // Detect if the account exists + if (AccountUtils.exists(mCurrentUpload.getAccount(), getApplicationContext())) { + Log_OC.d(TAG, "Account " + mCurrentUpload.getAccount().toString() + " exists"); - RemoteOperationResult uploadResult = null, grantResult = null; - - try { - /// prepare client object to send requests to the ownCloud server - if (mUploadClient == null || !mLastAccount.equals(mCurrentUpload.getAccount())) { - mLastAccount = mCurrentUpload.getAccount(); - mStorageManager = - new FileDataStorageManager(mLastAccount, getContentResolver()); - OwnCloudAccount ocAccount = new OwnCloudAccount(mLastAccount, 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(); + notifyUploadStart(mCurrentUpload); + + RemoteOperationResult uploadResult = null, grantResult = null; + + try { + /// prepare client object to send requests to the ownCloud server + if (mUploadClient == null || !mLastAccount.equals(mCurrentUpload.getAccount())) { + mLastAccount = mCurrentUpload.getAccount(); + mStorageManager = + new FileDataStorageManager(mLastAccount, getContentResolver()); + OwnCloudAccount ocAccount = new OwnCloudAccount(mLastAccount, 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 { + uploadResult = grantResult; + } + + } catch (AccountsException e) { + Log_OC.e(TAG, "Error while trying to get autorization for " + mLastAccount.name, e); + uploadResult = new RemoteOperationResult(e); + + } catch (IOException e) { + Log_OC.e(TAG, "Error while trying to get autorization for " + mLastAccount.name, e); + uploadResult = new RemoteOperationResult(e); + + } finally { + synchronized (mPendingUploads) { + mPendingUploads.remove(uploadKey); + Log_OC.i(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; } - } else { - uploadResult = grantResult; - } - - } catch (AccountsException e) { - Log_OC.e(TAG, "Error while trying to get autorization for " + mLastAccount.name, e); - uploadResult = new RemoteOperationResult(e); - - } catch (IOException e) { - Log_OC.e(TAG, "Error while trying to get autorization for " + mLastAccount.name, e); - uploadResult = new RemoteOperationResult(e); - - } finally { - synchronized (mPendingUploads) { - mPendingUploads.remove(uploadKey); - Log_OC.i(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; } - } - - /// notify result - - notifyUploadResult(uploadResult, mCurrentUpload); - sendFinalBroadcast(mCurrentUpload, uploadResult); + /// notify result + notifyUploadResult(uploadResult, mCurrentUpload); + sendFinalBroadcast(mCurrentUpload, uploadResult); + + } else { + // Cancel the transfer + Log_OC.d(TAG, "Account " + mCurrentUpload.getAccount().toString() + " doesn't exist"); + cancelUploadForAccount(mCurrentUpload.getAccount().name); + + } } } @@@ -591,18 -567,17 +609,18 @@@ /** * 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()) { + if (!result.isSuccess() && result.getCode() == ResultCode.FILE_NOT_FOUND && + mCurrentUpload.isRemoteFolderToBeCreated()) { SyncOperation syncOp = new CreateFolderOperation( pathToGrant, true); result = syncOp.execute(mUploadClient, mStorageManager); } @@@ -620,11 -595,10 +638,11 @@@ return result; } - + private OCFile createLocalFolder(String remotePath) { String parentPath = new File(remotePath).getParent(); - parentPath = parentPath.endsWith(OCFile.PATH_SEPARATOR) ? parentPath : parentPath + OCFile.PATH_SEPARATOR; + parentPath = parentPath.endsWith(OCFile.PATH_SEPARATOR) ? + parentPath : parentPath + OCFile.PATH_SEPARATOR; OCFile parent = mStorageManager.getFileByPath(parentPath); if (parent == null) { parent = createLocalFolder(parentPath); @@@ -638,15 -612,15 +656,15 @@@ } 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 refactor this ugly thing */ private void saveUploadedFile() { @@@ -665,7 -639,7 +683,7 @@@ updateOCFile(file, (RemoteFile) result.getData().get(0)); file.setLastSyncDateForProperties(syncDate); } - + // / maybe this would be better as part of UploadFileOperation... or // maybe all this method if (mCurrentUpload.wasRenamed()) { @@@ -675,8 -649,8 +693,8 @@@ mStorageManager.saveFile(oldFile); } // 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() + // coincidence; nothing else is needed, the storagePath is right + // in the instance returned by mCurrentUpload.getFile() } file.setNeedsUpdateThumbnail(true); mStorageManager.saveFile(file); @@@ -693,7 -667,7 +711,7 @@@ } private OCFile obtainNewOCFileToUpload(String remotePath, String localPath, String mimeType, - FileDataStorageManager storageManager) { + FileDataStorageManager storageManager) { // MIME type if (mimeType == null || mimeType.length() <= 0) { @@@ -723,7 -697,7 +741,7 @@@ 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 + // are checked when the UploadFileOperation instance is created newFile.setMimetype(mimeType); @@@ -733,13 -707,13 +751,13 @@@ /** * 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 = + mNotificationBuilder = NotificationBuilderWithProgressBar.newNotificationBuilderWithProgressBar(this); mNotificationBuilder .setOngoing(true) @@@ -756,7 -730,7 +774,7 @@@ showDetailsIntent.putExtra(FileActivity.EXTRA_ACCOUNT, upload.getAccount()); showDetailsIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); mNotificationBuilder.setContentIntent(PendingIntent.getActivity( - this, (int) System.currentTimeMillis(), showDetailsIntent, 0 + this, (int) System.currentTimeMillis(), showDetailsIntent, 0 )); mNotificationManager.notify(R.string.uploader_upload_in_progress_ticker, mNotificationBuilder.build()); @@@ -780,7 -754,7 +798,7 @@@ /** * Updates the status notification with the result of an upload operation. - * + * * @param uploadResult Result of the upload operation. * @param upload Finished upload operation */ @@@ -789,33 -763,33 +807,33 @@@ 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; - + 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() + uploadResult.getCode() == ResultCode.UNAUTHORIZED || + uploadResult.isIdPRedirection() ); - tickerId = (needsToUpdateCredentials) ? + 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); - + .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); @@@ -823,24 -797,24 +841,24 @@@ AuthenticatorActivity.EXTRA_ACCOUNT, upload.getAccount() ); updateAccountCredentials.putExtra( - AuthenticatorActivity.EXTRA_ACTION, + AuthenticatorActivity.EXTRA_ACTION, AuthenticatorActivity.ACTION_UPDATE_EXPIRED_TOKEN ); updateAccountCredentials.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 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 + this, + (int) System.currentTimeMillis(), + updateAccountCredentials, + PendingIntent.FLAG_ONE_SHOT )); - - mUploadClient = null; - // grant that future retries on the same account will get the fresh credentials + + mUploadClient = null; + // grant that future retries on the same account will get the fresh credentials } else { mNotificationBuilder.setContentText(content); - + if (upload.isInstant()) { DbHandler db = null; try { @@@ -851,12 -825,12 +869,12 @@@ if (uploadResult.getCode() == ResultCode.QUOTA_EXCEEDED) { //message = getString(R.string.failed_upload_quota_exceeded_text); if (db.updateFileState( - upload.getOriginalStoragePath(), + upload.getOriginalStoragePath(), DbHandler.UPLOAD_STATUS_UPLOAD_FAILED, message) == 0) { db.putFileForLater( - upload.getOriginalStoragePath(), - upload.getAccount().name, + upload.getOriginalStoragePath(), + upload.getAccount().name, message ); } @@@ -868,22 -842,22 +886,22 @@@ } } } - + mNotificationBuilder.setContentText(content); mNotificationManager.notify(tickerId, mNotificationBuilder.build()); - + if (uploadResult.isSuccess()) { - + DbHandler db = new DbHandler(this.getBaseContext()); db.removeIUPendingFile(mCurrentUpload.getOriginalStoragePath()); db.close(); // remove success notification, with a delay of 2 seconds NotificationDelayer.cancelWithDelay( - mNotificationManager, - R.string.uploader_upload_succeeded_ticker, + mNotificationManager, + R.string.uploader_upload_succeeded_ticker, 2000); - + } } } @@@ -891,17 -865,17 +909,17 @@@ /** * 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 */ private void sendFinalBroadcast(UploadFileOperation upload, RemoteOperationResult uploadResult) { Intent end = new Intent(getUploadFinishMessage()); end.putExtra(EXTRA_REMOTE_PATH, upload.getRemotePath()); // real remote - // path, after - // possible - // automatic - // renaming + // path, after + // possible + // automatic + // renaming if (upload.wasRenamed()) { end.putExtra(EXTRA_OLD_REMOTE_PATH, upload.getOldFile().getRemotePath()); } @@@ -919,27 -893,9 +937,27 @@@ * @return true if is needed to add the pdf file extension to the file */ private boolean isPdfFileFromContentProviderWithoutExtension(String localPath, String mimeType) { - return localPath.startsWith(UriUtils.URI_CONTENT_SCHEME) && - mimeType.equals(MIME_TYPE_PDF) && + return localPath.startsWith(UriUtils.URI_CONTENT_SCHEME) && + mimeType.equals(MIME_TYPE_PDF) && !localPath.endsWith(FILE_EXTENSION_PDF); } + /** + * Remove uploads of an account + * @param accountName + */ + private void cancelUploadForAccount(String accountName){ + // this can be slow if there are many uploads :( + Iterator 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); + } + } + } + } } diff --combined src/com/owncloud/android/ui/activity/FileDisplayActivity.java index 3b796966,ef9de9ea..3bc1aed9 --- a/src/com/owncloud/android/ui/activity/FileDisplayActivity.java +++ b/src/com/owncloud/android/ui/activity/FileDisplayActivity.java @@@ -1,6 -1,6 +1,6 @@@ /* ownCloud Android client application * Copyright (C) 2011 Bartek Przybylski - * Copyright (C) 2012-2014 ownCloud Inc. + * Copyright (C) 2012-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, @@@ -96,6 -96,7 +96,6 @@@ import com.owncloud.android.operations. import com.owncloud.android.operations.UnshareLinkOperation; import com.owncloud.android.services.observer.FileObserverService; import com.owncloud.android.syncadapter.FileSyncAdapter; -import com.owncloud.android.ui.adapter.FileListListAdapter; import com.owncloud.android.ui.dialog.CreateFolderDialogFragment; import com.owncloud.android.ui.dialog.SslUntrustedCertDialog; import com.owncloud.android.ui.dialog.SslUntrustedCertDialog.OnSslUntrustedCertListener; @@@ -255,7 -256,7 +255,7 @@@ OnSslUntrustedCertListener, OnEnforceab setNavigationListWithFolder(file); if (!stateWasRecovered) { - Log_OC.e(TAG, "Initializing Fragments in onAccountChanged.."); + Log_OC.d(TAG, "Initializing Fragments in onAccountChanged.."); initFragmentsWithFile(); if (file.isFolder()) { startSyncFolderOperation(file, false); @@@ -554,19 -555,19 +554,19 @@@ } private void startSynchronization() { - Log_OC.e(TAG, "Got to start sync"); + Log_OC.d(TAG, "Got to start sync"); if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.KITKAT) { - Log_OC.e(TAG, "Canceling all syncs for " + MainApp.getAuthority()); + Log_OC.d(TAG, "Canceling all syncs for " + MainApp.getAuthority()); ContentResolver.cancelSync(null, MainApp.getAuthority()); // cancel the current synchronizations of any ownCloud account Bundle bundle = new Bundle(); bundle.putBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, true); bundle.putBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, true); - Log_OC.e(TAG, "Requesting sync for " + getAccount().name + " at " + MainApp.getAuthority()); + Log_OC.d(TAG, "Requesting sync for " + getAccount().name + " at " + MainApp.getAuthority()); ContentResolver.requestSync( getAccount(), MainApp.getAuthority(), bundle); } else { - Log_OC.e(TAG, "Requesting sync for " + getAccount().name + " at " + MainApp.getAuthority() + " with new API"); + Log_OC.d(TAG, "Requesting sync for " + getAccount().name + " at " + MainApp.getAuthority() + " with new API"); SyncRequest.Builder builder = new SyncRequest.Builder(); builder.setSyncAdapter(getAccount(), MainApp.getAuthority()); builder.setExpedited(true); @@@ -648,7 -649,6 +648,7 @@@ if (filePaths != null) { String[] remotePaths = new String[filePaths.length]; String remotePathBase = ""; + for (int j = mDirectories.getCount() - 2; j >= 0; --j) { remotePathBase += OCFile.PATH_SEPARATOR + mDirectories.getItem(j); } @@@ -699,7 -699,7 +699,7 @@@ } finally { if (filepath == null) { - Log_OC.e(TAG, "Couldnt resolve path to file"); + Log_OC.e(TAG, "Couldn't resolve path to file"); Toast t = Toast.makeText(this, getString(R.string.filedisplay_unexpected_bad_get_content), Toast.LENGTH_LONG); t.show(); return; @@@ -786,7 -786,7 +786,7 @@@ @Override protected void onSaveInstanceState(Bundle outState) { // responsibility of restore is preferred in onCreate() before than in onRestoreInstanceState when there are Fragments involved - Log_OC.e(TAG, "onSaveInstanceState() start"); + Log_OC.d(TAG, "onSaveInstanceState() start"); super.onSaveInstanceState(outState); outState.putParcelable(FileDisplayActivity.KEY_WAITING_TO_PREVIEW, mWaitingToPreview); outState.putBoolean(FileDisplayActivity.KEY_SYNC_IN_PROGRESS, mSyncInProgress); @@@ -801,7 -801,7 +801,7 @@@ @Override protected void onResume() { super.onResume(); - Log_OC.e(TAG, "onResume() start"); + Log_OC.d(TAG, "onResume() start"); // refresh list of files refreshListOfFilesFragment(); @@@ -833,7 -833,7 +833,7 @@@ @Override protected void onPause() { - Log_OC.e(TAG, "onPause() start"); + Log_OC.d(TAG, "onPause() start"); if (mSyncBroadcastReceiver != null) { unregisterReceiver(mSyncBroadcastReceiver); //LocalBroadcastManager.getInstance(this).unregisterReceiver(mSyncBroadcastReceiver);