Pārlūkot izejas kodu

Merge pull request #1688 from owncloud/1628_prevent_that_upload_delayed_waiting_Wifi_notifies_an_error

Prevent that uploads delayed waiting for Wifi are shown as failed uploads
David A. Velasco 9 gadi atpakaļ
vecāks
revīzija
46b1c5ceea

+ 27 - 9
src/com/owncloud/android/datamodel/UploadsStorageManager.java

@@ -363,12 +363,15 @@ public class UploadsStorageManager extends Observable {
      * Get all uploads which are currently being uploaded or waiting in the queue to be uploaded.
      */
     public OCUpload[] getCurrentAndPendingUploads() {
-        return getUploads(ProviderTableMeta.UPLOADS_STATUS + "==" + UploadStatus.UPLOAD_IN_PROGRESS.value, null);
+        return getUploads(
+            ProviderTableMeta.UPLOADS_STATUS + "==" + UploadStatus.UPLOAD_IN_PROGRESS.value + " OR " +
+            ProviderTableMeta.UPLOADS_LAST_RESULT + "==" + UploadResult.DELAYED_FOR_WIFI.getValue(),
+            null
+        );
     }
 
     /**
-     * Get all unrecoverably failed. Upload of these should/must/will not be
-     * retried.
+     * Get all failed uploads.
      */
     public OCUpload[] getFailedUploads() {
         return getUploads(ProviderTableMeta.UPLOADS_STATUS + "==" + UploadStatus.UPLOAD_FAILED.value, null);
@@ -381,16 +384,30 @@ public class UploadsStorageManager extends Observable {
         return getUploads(ProviderTableMeta.UPLOADS_STATUS + "==" + UploadStatus.UPLOAD_SUCCEEDED.value, null);
     }
 
+    /**
+     * Get all failed uploads, except for those that were not performed due to lack of Wifi connection
+     * @return      Array of failed uploads, except for those that were not performed due to lack of Wifi connection.
+     */
+    public OCUpload[] getFailedButNotDelayedForWifiUploads() {
+        return getUploads(
+            ProviderTableMeta.UPLOADS_STATUS + "==" + UploadStatus.UPLOAD_FAILED.value + " AND " +
+                ProviderTableMeta.UPLOADS_LAST_RESULT + "<>" + UploadResult.DELAYED_FOR_WIFI.getValue(),
+            null
+        );
+    }
+
     private ContentResolver getDB() {
         return mContentResolver;
     }
 
-    public long clearFailedUploads() {
+    public long clearFailedButNotDelayedForWifiUploads() {
         long result = getDB().delete(
-                ProviderTableMeta.CONTENT_URI_UPLOADS,
-                ProviderTableMeta.UPLOADS_STATUS + "==" + UploadStatus.UPLOAD_FAILED.value, null
+            ProviderTableMeta.CONTENT_URI_UPLOADS,
+            ProviderTableMeta.UPLOADS_STATUS + "==" + UploadStatus.UPLOAD_FAILED.value + " AND " +
+                ProviderTableMeta.UPLOADS_LAST_RESULT + "<>" + UploadResult.DELAYED_FOR_WIFI.getValue(),
+            null
         );
-        Log_OC.d(TAG, "delete all failed uploads");
+        Log_OC.d(TAG, "delete all failed uploads but those delayed for Wifi");
         if (result > 0) {
             notifyObserversNow();
         }
@@ -409,13 +426,14 @@ public class UploadsStorageManager extends Observable {
         return result;
     }
 
-    public long clearAllFinishedUploads() {
+    public long clearAllFinishedButNotDelayedForWifiUploads() {
         String[] whereArgs = new String[2];
         whereArgs[0] = String.valueOf(UploadStatus.UPLOAD_SUCCEEDED.value);
         whereArgs[1] = String.valueOf(UploadStatus.UPLOAD_FAILED.value);
         long result = getDB().delete(
                 ProviderTableMeta.CONTENT_URI_UPLOADS,
-                ProviderTableMeta.UPLOADS_STATUS + "=? OR " + ProviderTableMeta.UPLOADS_STATUS + "=?",
+                ProviderTableMeta.UPLOADS_STATUS + "=? OR " + ProviderTableMeta.UPLOADS_STATUS + "=? AND " +
+                ProviderTableMeta.UPLOADS_LAST_RESULT + "<>" + UploadResult.DELAYED_FOR_WIFI.getValue(),
                 whereArgs
         );
         Log_OC.d(TAG, "delete all finished uploads");

+ 3 - 4
src/com/owncloud/android/files/services/FileDownloader.java

@@ -50,8 +50,7 @@ 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.notifications.NotificationBuilderWithProgressBar;
-import com.owncloud.android.notifications.NotificationDelayer;
+import com.owncloud.android.ui.notifications.NotificationUtils;
 import com.owncloud.android.operations.DownloadFileOperation;
 import com.owncloud.android.ui.activity.FileActivity;
 import com.owncloud.android.ui.activity.FileDisplayActivity;
@@ -483,7 +482,7 @@ public class FileDownloader extends Service
         /// create status notification with a progress bar
         mLastPercent = 0;
         mNotificationBuilder =
-                NotificationBuilderWithProgressBar.newNotificationBuilderWithProgressBar(this);
+                NotificationUtils.newNotificationBuilder(this);
         mNotificationBuilder
                 .setSmallIcon(R.drawable.notification_icon)
                 .setTicker(getString(R.string.downloader_download_in_progress_ticker))
@@ -591,7 +590,7 @@ public class FileDownloader extends Service
             // Remove success notification
             if (downloadResult.isSuccess()) {
                 // Sleep 2 seconds, so show the notification before remove it
-                NotificationDelayer.cancelWithDelay(
+                NotificationUtils.cancelWithDelay(
                         mNotificationManager,
                         R.string.downloader_download_succeeded_ticker,
                         2000);

+ 11 - 6
src/com/owncloud/android/files/services/FileUploader.java

@@ -61,8 +61,7 @@ import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCo
 import com.owncloud.android.lib.common.utils.Log_OC;
 import com.owncloud.android.lib.resources.files.FileUtils;
 import com.owncloud.android.lib.resources.status.OwnCloudVersion;
-import com.owncloud.android.notifications.NotificationBuilderWithProgressBar;
-import com.owncloud.android.notifications.NotificationDelayer;
+import com.owncloud.android.ui.notifications.NotificationUtils;
 import com.owncloud.android.operations.UploadFileOperation;
 import com.owncloud.android.ui.activity.FileActivity;
 import com.owncloud.android.ui.activity.UploadListActivity;
@@ -959,7 +958,7 @@ public class FileUploader extends Service
         // / create status notification with a progress bar
         mLastPercent = 0;
         mNotificationBuilder =
-                NotificationBuilderWithProgressBar.newNotificationBuilderWithProgressBar(this);
+                NotificationUtils.newNotificationBuilder(this);
         mNotificationBuilder
                 .setOngoing(true)
                 .setSmallIcon(R.drawable.notification_icon)
@@ -978,7 +977,11 @@ public class FileUploader extends Service
         mNotificationBuilder.setContentIntent(PendingIntent.getActivity(this, (int) System.currentTimeMillis(),
             showUploadListIntent, 0));
 
-        mNotificationManager.notify(R.string.uploader_upload_in_progress_ticker, mNotificationBuilder.build());
+        if (!upload.isInstantPicture() && !upload.isInstantVideo()) {
+            mNotificationManager.notify(R.string.uploader_upload_in_progress_ticker, mNotificationBuilder.build());
+        }   // else wait until the upload really start (onTransferProgress is called), so that if it's discarded
+        // due to lack of Wifi, no notification is shown
+        // TODO generalize for automated uploads
 
     }
 
@@ -1012,7 +1015,9 @@ public class FileUploader extends Service
         mNotificationManager.cancel(R.string.uploader_upload_in_progress_ticker);
 
         // Show the result: success or fail notification
-        if (!uploadResult.isCancelled()) {
+        if (!uploadResult.isCancelled() &&
+            !uploadResult.getCode().equals(ResultCode.DELAYED_FOR_WIFI)) {
+
             int tickerId = (uploadResult.isSuccess()) ? R.string.uploader_upload_succeeded_ticker :
                     R.string.uploader_upload_failed_ticker;
 
@@ -1075,7 +1080,7 @@ public class FileUploader extends Service
             if (uploadResult.isSuccess()) {
                 mPendingUploads.remove(upload.getAccount().name, upload.getFile().getRemotePath());
                 // remove success notification, with a delay of 2 seconds
-                NotificationDelayer.cancelWithDelay(
+                NotificationUtils.cancelWithDelay(
                         mNotificationManager,
                         R.string.uploader_upload_succeeded_ticker,
                         2000);

+ 0 - 134
src/com/owncloud/android/notifications/NotificationBuilderWithProgressBar.java

@@ -1,134 +0,0 @@
-/**
- *   ownCloud Android client application
- *
- *   @author David A. Velasco
- *   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.notifications;
-
-import com.owncloud.android.R;
-
-import android.app.Notification;
-import android.content.Context;
-import android.os.Build;
-import android.support.v4.app.NotificationCompat;
-import android.view.View;
-import android.widget.RemoteViews;
-
-/**
- * Extends the support class {@link NotificationCompat.Builder} to grant that
- * a progress bar is available in every Android version, because 
- * {@link NotificationCompat.Builder#setProgress(int, int, boolean)} has no
- * real effect for Android < 4.0
- */
-public class NotificationBuilderWithProgressBar extends NotificationCompat.Builder {
-
-    /**
-     * Custom view to replace the original layout of the notifications
-     */
-    private RemoteViews mContentView = null;
-    
-    /**
-     * Fatory method.
-     * 
-     * Instances of this class will be only returned in Android versions needing it.
-     * 
-     * @param context       Context that will use the builder to create notifications
-     * @return              An instance of this class, or of the regular 
-     *                      {@link NotificationCompat.Builder}, when it is good enough.
-     */
-    public static NotificationCompat.Builder newNotificationBuilderWithProgressBar(Context context) {
-        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
-            return new NotificationBuilderWithProgressBar(context); 
-        } else {
-            return new NotificationCompat.Builder(context).
-                    setColor(context.getResources().getColor(R.color.primary));
-        }
-    }
-    
-    /**
-     * Constructor.
-     * 
-     * @param context       Context that will use the builder to create notifications.
-     */
-    private NotificationBuilderWithProgressBar(Context context) {
-        super(context);
-        mContentView = new RemoteViews(context.getPackageName(), R.layout.notification_with_progress_bar);
-        setContent(mContentView);
-    }
-    
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public NotificationCompat.Builder setProgress(int max, int progress, boolean indeterminate) {
-        mContentView.setProgressBar(R.id.progress, max, progress, indeterminate);
-        if (max > 0) {
-            mContentView.setViewVisibility(R.id.progressHolder, View.VISIBLE);
-        } else {
-            mContentView.setViewVisibility(R.id.progressHolder, View.GONE);
-        }
-        return this;
-    }
-    
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public NotificationCompat.Builder setSmallIcon(int icon) {
-        super.setSmallIcon(icon);   // necessary
-        mContentView.setImageViewResource(R.id.icon, icon);
-        return this;
-    }
-    
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public NotificationCompat.Builder setContentTitle(CharSequence title) {
-        super.setContentTitle(title);
-        mContentView.setTextViewText(R.id.title, title);
-        return this;
-    }
-    
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public NotificationCompat.Builder setContentText(CharSequence text) {
-        super.setContentText(text);
-        mContentView.setTextViewText(R.id.text, text);
-        if (text != null && text.length() > 0) {
-            mContentView.setViewVisibility(R.id.text, View.VISIBLE);
-        } else {
-            mContentView.setViewVisibility(R.id.text, View.GONE);
-        }
-        return this;
-    }
-
-    @Override
-    public Notification build() {
-        Notification result = super.build();
-        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
-            // super.build() in Android 2.x totally ruins whatever was made #setContent 
-            result.contentView = mContentView;
-        }
-        return result;
-    }
-    
-    
-}

+ 2 - 2
src/com/owncloud/android/ui/activity/UploadListActivity.java

@@ -199,7 +199,7 @@ public class UploadListActivity extends FileActivity implements UploadListFragme
 
             case R.id.action_clear_failed_uploads:
                 storageManager = new UploadsStorageManager(getContentResolver());
-                storageManager.clearFailedUploads();
+                storageManager.clearFailedButNotDelayedForWifiUploads();
                 uploadListFragment.updateUploads();
                 break;
 
@@ -211,7 +211,7 @@ public class UploadListActivity extends FileActivity implements UploadListFragme
 
             case R.id.action_clear_finished_uploads:
                 storageManager = new UploadsStorageManager(getContentResolver());
-                storageManager.clearAllFinishedUploads();
+                storageManager.clearAllFinishedButNotDelayedForWifiUploads();
                 uploadListFragment.updateUploads();
                 break;
 

+ 6 - 1
src/com/owncloud/android/ui/adapter/ExpandableUploadListAdapter.java

@@ -92,6 +92,9 @@ public class ExpandableUploadListAdapter extends BaseExpandableListAdapter imple
             @Override
             public int compare(OCUpload upload1, OCUpload upload2) {
                 if (upload1.getUploadStatus().equals(UploadStatus.UPLOAD_IN_PROGRESS)) {
+                    if (!upload2.getUploadStatus().equals(UploadStatus.UPLOAD_IN_PROGRESS)) {
+                        return -1;
+                    }
                     FileUploader.FileUploaderBinder binder = mParentActivity.getFileUploaderBinder();
                     if (binder != null) {
                         if (binder.isUploadingNow(upload1)) {
@@ -100,6 +103,8 @@ public class ExpandableUploadListAdapter extends BaseExpandableListAdapter imple
                             return 1;
                         }
                     }
+                } else if (upload2.getUploadStatus().equals(UploadStatus.UPLOAD_IN_PROGRESS)) {
+                    return 1;
                 }
                 if (upload1.getUploadEndTimestamp() == 0) {
                     return compareUploadId(upload1, upload2);
@@ -142,7 +147,7 @@ public class ExpandableUploadListAdapter extends BaseExpandableListAdapter imple
         mUploadGroups[1] = new UploadGroup(mParentActivity.getString(R.string.uploads_view_group_failed_uploads)) {
             @Override
             public void refresh() {
-                items = mUploadsStorageManager.getFailedUploads();
+                items = mUploadsStorageManager.getFailedButNotDelayedForWifiUploads();
                 Arrays.sort(items, comparator);
             }
 

+ 28 - 3
src/com/owncloud/android/notifications/NotificationDelayer.java → src/com/owncloud/android/ui/notifications/NotificationUtils.java

@@ -17,17 +17,42 @@
  *
  */
 
-package com.owncloud.android.notifications;
+package com.owncloud.android.ui.notifications;
 
 import java.util.Random;
 
 import android.app.NotificationManager;
+import android.content.Context;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Process;
+import android.support.v4.app.NotificationCompat;
+
+import com.owncloud.android.R;
+
+public class NotificationUtils {
+
+    /**
+     * Factory method for {@link android.support.v4.app.NotificationCompat.Builder} instances.
+     *
+     * Not strictly needed from the moment when the minimum API level supported by the app
+     * was raised to 14 (Android 4.0).
+     *
+     * Formerly, returned a customized implementation of {@link android.support.v4.app.NotificationCompat.Builder}
+     * for Android API levels >= 8 and < 14.
+     *
+     * Kept in place for the extra abstraction level; notifications in the app need a review, and they
+     * change a lot in different Android versions.
+     *
+     * @param context       Context that will use the builder to create notifications
+     * @return              An instance of the regular {@link NotificationCompat.Builder}.
+     */
+    public static NotificationCompat.Builder newNotificationBuilder(Context context) {
+        return new NotificationCompat.Builder(context).
+            setColor(context.getResources().getColor(R.color.primary));
+    }
+
 
-public class NotificationDelayer {
-    
     public static void cancelWithDelay(
             final NotificationManager notificationManager,
             final int notificationId,