Эх сурвалжийг харах

Merge pull request #811 from owncloud/download_folder_cancel_downloads

'Cancel folder download' cancels downloads of files already in the FileD...
David A. Velasco 10 жил өмнө
parent
commit
9795a2bb2b

+ 3 - 1
src/com/owncloud/android/files/FileOperationsHelper.java

@@ -29,6 +29,7 @@ import android.widget.Toast;
 
 import com.owncloud.android.R;
 import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.files.services.FileDownloader;
 import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
 import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
 
@@ -304,8 +305,9 @@ public class FileOperationsHelper {
             Intent intent = new Intent(mFileActivity, OperationsService.class);
             intent.setAction(OperationsService.ACTION_CANCEL_SYNC_FOLDER);
             intent.putExtra(OperationsService.EXTRA_ACCOUNT, account);
-            intent.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
+            intent.putExtra(OperationsService.EXTRA_FILE, file);
             mFileActivity.startService(intent);
+
         }
     }
 

+ 88 - 28
src/com/owncloud/android/files/services/FileDownloader.java

@@ -21,6 +21,7 @@ package com.owncloud.android.files.services;
 import java.io.File;
 import java.io.IOException;
 import java.util.AbstractList;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
@@ -69,7 +70,9 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
     
     public static final String EXTRA_ACCOUNT = "ACCOUNT";
     public static final String EXTRA_FILE = "FILE";
-    
+
+    public static final String ACTION_CANCEL_FILE_DOWNLOAD = "CANCEL_FILE_DOWNLOAD";
+
     private static final String DOWNLOAD_ADDED_MESSAGE = "DOWNLOAD_ADDED";
     private static final String DOWNLOAD_FINISH_MESSAGE = "DOWNLOAD_FINISH";
     public static final String EXTRA_DOWNLOAD_RESULT = "RESULT";    
@@ -92,6 +95,9 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
     private NotificationManager mNotificationManager;
     private NotificationCompat.Builder mNotificationBuilder;
     private int mLastPercent;
+
+    private Account mAccount;
+    private OCFile mFile;
     
     
     public static String getDownloadAddedMessage() {
@@ -143,30 +149,43 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
            ) {
             Log_OC.e(TAG, "Not enough information provided in intent");
             return START_NOT_STICKY;
-        }
-        Account account = intent.getParcelableExtra(EXTRA_ACCOUNT);
-        OCFile file = intent.getParcelableExtra(EXTRA_FILE);
-        
-        AbstractList<String> requestedDownloads = new Vector<String>(); // dvelasco: now this always contains just one element, but that can change in a near future (download of multiple selection)
-        String downloadKey = buildRemoteName(account, file);
-        try {
-            DownloadFileOperation newDownload = new DownloadFileOperation(account, file); 
-            mPendingDownloads.putIfAbsent(downloadKey, newDownload);
-            newDownload.addDatatransferProgressListener(this);
-            newDownload.addDatatransferProgressListener((FileDownloaderBinder)mBinder);
-            requestedDownloads.add(downloadKey);
-            sendBroadcastNewDownload(newDownload);
-            
-        } catch (IllegalArgumentException e) {
-            Log_OC.e(TAG, "Not enough information provided in intent: " + e.getMessage());
-            return START_NOT_STICKY;
-        }
-        
-        if (requestedDownloads.size() > 0) {
-            Message msg = mServiceHandler.obtainMessage();
-            msg.arg1 = startId;
-            msg.obj = requestedDownloads;
-            mServiceHandler.sendMessage(msg);
+        } else {
+            mAccount = intent.getParcelableExtra(EXTRA_ACCOUNT);
+            mFile = intent.getParcelableExtra(EXTRA_FILE);
+
+            if (ACTION_CANCEL_FILE_DOWNLOAD.equals(intent.getAction())) {
+
+                new Thread(new Runnable() {
+                    public void run() {
+                        // Cancel the download
+                        cancel(mAccount,mFile);
+                    }
+                }).start();
+
+            } else {
+
+                AbstractList<String> requestedDownloads = new Vector<String>(); // dvelasco: now this always contains just one element, but that can change in a near future (download of multiple selection)
+                String downloadKey = buildRemoteName(mAccount, mFile);
+                try {
+                    DownloadFileOperation newDownload = new DownloadFileOperation(mAccount, mFile);
+                    mPendingDownloads.putIfAbsent(downloadKey, newDownload);
+                    newDownload.addDatatransferProgressListener(this);
+                    newDownload.addDatatransferProgressListener((FileDownloaderBinder) mBinder);
+                    requestedDownloads.add(downloadKey);
+                    sendBroadcastNewDownload(newDownload);
+
+                } catch (IllegalArgumentException e) {
+                    Log_OC.e(TAG, "Not enough information provided in intent: " + e.getMessage());
+                    return START_NOT_STICKY;
+                }
+
+                if (requestedDownloads.size() > 0) {
+                    Message msg = mServiceHandler.obtainMessage();
+                    msg.arg1 = startId;
+                    msg.obj = requestedDownloads;
+                    mServiceHandler.sendMessage(msg);
+                }
+            }
         }
 
         return START_NOT_STICKY;
@@ -205,11 +224,11 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
          * Map of listeners that will be reported about progress of downloads from a {@link FileDownloaderBinder} instance 
          */
         private Map<String, OnDatatransferProgressListener> mBoundListeners = new HashMap<String, OnDatatransferProgressListener>();
-        
-        
+
+
         /**
          * Cancels a pending or current download of a remote file.
-         * 
+         *
          * @param account       Owncloud account where the remote file is stored.
          * @param file          A file in the queue of pending downloads
          */
@@ -555,4 +574,45 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
         sendStickyBroadcast(added);
     }
 
+    /**
+     * Cancel operation
+     * @param account       Owncloud account where the remote file is stored.
+     * @param file          File OCFile
+     */
+    public void cancel(Account account, OCFile file){
+        if(Looper.myLooper() == Looper.getMainLooper()) {
+            Log_OC.d(TAG, "Current Thread is Main Thread.");
+        } else {
+            Log_OC.d(TAG, "Current Thread is NOT Main Thread.");
+        }
+
+        DownloadFileOperation download = null;
+        String targetKey = buildRemoteName(account, file);
+        ArrayList<String> keyItems = new ArrayList<String>();
+        synchronized (mPendingDownloads) {
+            if (file.isFolder()) {
+                Log_OC.d(TAG, "Folder download. Canceling pending downloads (from folder)");
+                Iterator<String> it = mPendingDownloads.keySet().iterator();
+                boolean found = false;
+                while (it.hasNext()) {
+                    String keyDownloadOperation = it.next();
+                    found = keyDownloadOperation.startsWith(targetKey);
+                    if (found) {
+                        keyItems.add(keyDownloadOperation);
+                    }
+                }
+            } else {
+                Log_OC.d(TAG, "Canceling file download");
+                keyItems.add(buildRemoteName(account, file));
+            }
+        }
+        for (String item: keyItems) {
+            download = mPendingDownloads.remove(item);
+            Log_OC.d(TAG, "Key removed: " + item);
+
+            if (download != null) {
+                download.cancel();
+            }
+        }
+    }
 }

+ 5 - 2
src/com/owncloud/android/operations/SynchronizeFolderOperation.java

@@ -27,6 +27,7 @@ import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.files.services.FileDownloader;
 import com.owncloud.android.lib.common.OwnCloudClient;
 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;
 import com.owncloud.android.lib.common.utils.Log_OC;
@@ -145,6 +146,10 @@ public class SynchronizeFolderOperation extends SyncOperation {
 
         synchronized(mCancellationRequested) {
             if (mCancellationRequested.get()) {
+                // Cancel each operation in mFoldersToWalkDown
+                for (SyncOperation  synchOp: mFoldersToWalkDown) {
+                    ((SynchronizeFolderOperation) synchOp).cancel();
+                }
                 return new RemoteOperationResult(new OperationCancelledException());
             }
         }
@@ -502,8 +507,6 @@ public class SynchronizeFolderOperation extends SyncOperation {
      * Cancel operation
      */
     public void cancel(){
-        // WIP Cancel the sync operation
         mCancellationRequested.set(true);
     }
-
 }

+ 16 - 7
src/com/owncloud/android/services/OperationsService.java

@@ -26,6 +26,7 @@ import java.util.concurrent.ConcurrentMap;
 import com.owncloud.android.MainApp;
 import com.owncloud.android.R;
 import com.owncloud.android.datamodel.FileDataStorageManager;
+import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.files.services.FileDownloader;
 import com.owncloud.android.lib.common.OwnCloudAccount;
 import com.owncloud.android.lib.common.OwnCloudClient;
@@ -84,7 +85,8 @@ public class OperationsService extends Service {
     public static final String EXTRA_SYNC_FILE_CONTENTS = "SYNC_FILE_CONTENTS";
     public static final String EXTRA_RESULT = "RESULT";
     public static final String EXTRA_NEW_PARENT_PATH = "NEW_PARENT_PATH";
-    
+    public static final String EXTRA_FILE = "FILE";
+
     // TODO review if ALL OF THEM are necessary
     public static final String EXTRA_SUCCESS_IF_ABSENT = "SUCCESS_IF_ABSENT";
     public static final String EXTRA_USERNAME = "USERNAME";
@@ -187,15 +189,15 @@ public class OperationsService extends Service {
                 mSyncFolderHandler.sendMessage(msg);
             }
         } else if (ACTION_CANCEL_SYNC_FOLDER.equals(intent.getAction())) {
-            if (!intent.hasExtra(EXTRA_ACCOUNT) || !intent.hasExtra(EXTRA_REMOTE_PATH)) {
+            if (!intent.hasExtra(EXTRA_ACCOUNT) || !intent.hasExtra(EXTRA_FILE)) {
                 Log_OC.e(TAG, "Not enough information provided in intent");
                 return START_NOT_STICKY;
             }
             Account account = intent.getParcelableExtra(EXTRA_ACCOUNT);
-            String remotePath = intent.getStringExtra(EXTRA_REMOTE_PATH);
+            OCFile file = intent.getParcelableExtra(EXTRA_FILE);
 
             // Cancel operation
-            mSyncFolderHandler.cancel(account,remotePath);
+            mSyncFolderHandler.cancel(account,file);
         } else {
             Message msg = mOperationsHandler.obtainMessage();
             msg.arg1 = startId;
@@ -482,16 +484,23 @@ public class OperationsService extends Service {
          * Cancels a pending or current sync operation.
          *
          * @param account       Owncloud account where the remote file is stored.
-         * @param remotePath    A remote file path
+         * @param file          File
          */
-        public void cancel(Account account, String remotePath) {
+        public void cancel(Account account, OCFile file) {
             SynchronizeFolderOperation syncOperation = null;
             synchronized (mPendingOperations) {
-                syncOperation = mPendingOperations.remove(buildRemoteName(account, remotePath));
+                syncOperation = mPendingOperations.remove(buildRemoteName(account, file.getRemotePath()));
             }
             if (syncOperation != null) {
                 syncOperation.cancel();
             }
+
+            Intent intent = new Intent( MainApp.getAppContext(), FileDownloader.class);
+            intent.setAction(FileDownloader.ACTION_CANCEL_FILE_DOWNLOAD);
+            intent.putExtra(FileDownloader.EXTRA_ACCOUNT, account);
+            intent.putExtra(FileDownloader.EXTRA_FILE, file);
+            MainApp.getAppContext().startService(intent);
+
         }
 
         /**