Merge branch 'develop' into download_folder
[pub/Android/ownCloud.git] / src / com / owncloud / android / files / services / FileDownloader.java
index 1c53bea..eb870e1 100644 (file)
@@ -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;
@@ -34,19 +35,21 @@ import com.owncloud.android.datamodel.FileDataStorageManager;
 import com.owncloud.android.datamodel.OCFile;
 
 import com.owncloud.android.lib.common.network.OnDatatransferProgressListener;
-import com.owncloud.android.lib.common.OwnCloudClientFactory;
+import com.owncloud.android.lib.common.OwnCloudAccount;
 import com.owncloud.android.lib.common.OwnCloudClient;
-import com.owncloud.android.operations.DownloadFileOperation;
+import com.owncloud.android.lib.common.OwnCloudClientManagerFactory;
+import com.owncloud.android.notifications.NotificationBuilderWithProgressBar;
+import com.owncloud.android.notifications.NotificationDelayer;
 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.FileUtils;
+import com.owncloud.android.operations.DownloadFileOperation;
 import com.owncloud.android.ui.activity.FileActivity;
 import com.owncloud.android.ui.activity.FileDisplayActivity;
 import com.owncloud.android.ui.preview.PreviewImageActivity;
 import com.owncloud.android.ui.preview.PreviewImageFragment;
 import com.owncloud.android.utils.ErrorMessageAdapter;
-import com.owncloud.android.utils.Log_OC;
-import com.owncloud.android.utils.NotificationBuilderWithProgressBar;
 
 import android.accounts.Account;
 import android.accounts.AccountsException;
@@ -67,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";    
@@ -90,7 +95,7 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
     private NotificationManager mNotificationManager;
     private NotificationCompat.Builder mNotificationBuilder;
     private int mLastPercent;
-    
+
     
     public static String getDownloadAddedMessage() {
         return FileDownloader.class.getName().toString() + DOWNLOAD_ADDED_MESSAGE;
@@ -141,30 +146,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 {
+            final Account account = intent.getParcelableExtra(EXTRA_ACCOUNT);
+            final OCFile file = intent.getParcelableExtra(EXTRA_FILE);
+
+            if (ACTION_CANCEL_FILE_DOWNLOAD.equals(intent.getAction())) {
+
+                new Thread(new Runnable() {
+                    public void run() {
+                        // Cancel the download
+                        cancel(account, file);
+                    }
+                }).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(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);
+                }
+            }
         }
 
         return START_NOT_STICKY;
@@ -203,11 +221,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
          */
@@ -346,8 +364,11 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
                 /// prepare client object to send the request to the ownCloud server
                 if (mDownloadClient == null || !mLastAccount.equals(mCurrentDownload.getAccount())) {
                     mLastAccount = mCurrentDownload.getAccount();
-                    mStorageManager = new FileDataStorageManager(mLastAccount, getContentResolver());
-                    mDownloadClient = OwnCloudClientFactory.createOwnCloudClient(mLastAccount, getApplicationContext());
+                    mStorageManager = 
+                            new FileDataStorageManager(mLastAccount, getContentResolver());
+                    OwnCloudAccount ocAccount = new OwnCloudAccount(mLastAccount, this);
+                    mDownloadClient = OwnCloudClientManagerFactory.getDefaultSingleton().
+                            getClientFor(ocAccount, this);
                 }
 
                 /// perform the download
@@ -386,13 +407,16 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
         long syncDate = System.currentTimeMillis();
         file.setLastSyncDateForProperties(syncDate);
         file.setLastSyncDateForData(syncDate);
+        file.setNeedsUpdateThumbnail(true);
         file.setModificationTimestamp(mCurrentDownload.getModificationTimestamp());
         file.setModificationTimestampAtLastSyncForData(mCurrentDownload.getModificationTimestamp());
         // file.setEtag(mCurrentDownload.getEtag());    // TODO Etag, where available
         file.setMimetype(mCurrentDownload.getMimeType());
         file.setStoragePath(mCurrentDownload.getSavePath());
         file.setFileLength((new File(mCurrentDownload.getSavePath()).length()));
+        file.setRemoteId(mCurrentDownload.getFile().getRemoteId());
         mStorageManager.saveFile(file);
+        mStorageManager.triggerMediaScan(file.getStoragePath());
     }
 
 
@@ -461,12 +485,14 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
      */
     private void notifyDownloadResult(DownloadFileOperation download, RemoteOperationResult downloadResult) {
         mNotificationManager.cancel(R.string.downloader_download_in_progress_ticker);
-        if (!downloadResult.isCancelled() && !downloadResult.isSuccess()) {
-            int tickerId = R.string.downloader_download_failed_ticker;
+        if (!downloadResult.isCancelled()) {
+            int tickerId = (downloadResult.isSuccess()) ? R.string.downloader_download_succeeded_ticker : 
+                R.string.downloader_download_failed_ticker;
             
-            boolean needsToUpdateCredentials = (downloadResult.getCode() == ResultCode.UNAUTHORIZED ||
-                                                  (downloadResult.isIdPRedirection()
-                                                        && mDownloadClient.getCredentials() == null));
+            boolean needsToUpdateCredentials = (
+                    downloadResult.getCode() == ResultCode.UNAUTHORIZED ||
+                    downloadResult.isIdPRedirection()
+            );
             tickerId = (needsToUpdateCredentials) ? 
                     R.string.downloader_download_failed_credentials_error : tickerId;
             
@@ -501,8 +527,17 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
             }
             
             mNotificationBuilder.setContentText(ErrorMessageAdapter.getErrorCauseMessage(downloadResult, download, getResources()));
-            
             mNotificationManager.notify(tickerId, mNotificationBuilder.build());
+            
+            // Remove success notification
+            if (downloadResult.isSuccess()) {   
+                // Sleep 2 seconds, so show the notification before remove it
+                NotificationDelayer.cancelWithDelay(
+                        mNotificationManager, 
+                        R.string.downloader_download_succeeded_ticker, 
+                        2000);
+            }
+                
         }
     }
     
@@ -536,4 +571,40 @@ 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){
+        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 {
+                // this is not really expected...
+                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();
+            }
+        }
+    }
 }