浏览代码

Add notifications on sync failure

Signed-off-by: Mario Danic <mario@lovelyhq.com>
Mario Danic 7 年之前
父节点
当前提交
b64cfbde70

+ 56 - 15
src/main/java/com/owncloud/android/providers/DocumentsStorageProvider.java

@@ -21,6 +21,7 @@
 package com.owncloud.android.providers;
 
 import android.accounts.Account;
+import android.annotation.SuppressLint;
 import android.annotation.TargetApi;
 import android.content.ContentResolver;
 import android.content.Context;
@@ -32,6 +33,7 @@ import android.os.Build;
 import android.os.CancellationSignal;
 import android.os.ParcelFileDescriptor;
 import android.provider.DocumentsProvider;
+import android.util.Log;
 
 import com.owncloud.android.authentication.AccountUtils;
 import com.owncloud.android.datamodel.FileDataStorageManager;
@@ -40,6 +42,7 @@ import com.owncloud.android.files.services.FileDownloader;
 import com.owncloud.android.lib.common.operations.RemoteOperationResult;
 import com.owncloud.android.operations.SynchronizeFileOperation;
 import com.owncloud.android.ui.activity.ConflictsResolveActivity;
+import com.owncloud.android.ui.notifications.NotificationUtils;
 import com.owncloud.android.utils.FileStorageUtils;
 
 import org.nextcloud.providers.cursors.FileCursor;
@@ -54,6 +57,8 @@ import java.util.Vector;
 @TargetApi(Build.VERSION_CODES.KITKAT)
 public class DocumentsStorageProvider extends DocumentsProvider {
 
+    private static final String TAG = "DocumentsStorageProvider";
+
     private FileDataStorageManager mCurrentStorageManager = null;
     private static Map<Long, FileDataStorageManager> mRootIdToStorageManager;
 
@@ -76,6 +81,15 @@ public class DocumentsStorageProvider extends DocumentsProvider {
         updateCurrentStorageManagerIfNeeded(docId);
 
         final FileCursor result = new FileCursor(projection);
+        if (mCurrentStorageManager == null) {
+            for(long key : mRootIdToStorageManager.keySet()) {
+                if (mRootIdToStorageManager.get(key).getFileById(docId) != null) {
+                    mCurrentStorageManager = mRootIdToStorageManager.get(key);
+                    break;
+                }
+            }
+        }
+
         OCFile file = mCurrentStorageManager.getFileById(docId);
         if (file != null) {
             result.addFile(file);
@@ -101,6 +115,7 @@ public class DocumentsStorageProvider extends DocumentsProvider {
         return result;
     }
 
+    @SuppressLint("LongLogTag")
     @Override
     public ParcelFileDescriptor openDocument(String documentId, String mode, CancellationSignal cancellationSignal)
             throws FileNotFoundException {
@@ -127,21 +142,38 @@ public class DocumentsStorageProvider extends DocumentsProvider {
 
             } while (!file.isDown());
         } else {
-            FileDataStorageManager storageManager =
-                    new FileDataStorageManager(account, context.getContentResolver());
-            SynchronizeFileOperation sfo =
-                    new SynchronizeFileOperation(file, null, account, true, context);
-            RemoteOperationResult result = sfo.execute(storageManager, context);
-            if (result.getCode() == RemoteOperationResult.ResultCode.SYNC_CONFLICT) {
-                // ISSUE 5: if the user is not running the app (this is a service!),
-                // this can be very intrusive; a notification should be preferred
-                Intent i = new Intent(context, ConflictsResolveActivity.class);
-                i.setFlags(i.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
-                i.putExtra(ConflictsResolveActivity.EXTRA_FILE, file);
-                i.putExtra(ConflictsResolveActivity.EXTRA_ACCOUNT, account);
-                context.startActivity(i);
-            } else {
-                FileStorageUtils.checkIfFileFinishedSaving(file);
+            OCFile finalFile = file;
+            Thread syncThread = new Thread(() -> {
+                try {
+                    FileDataStorageManager storageManager =
+                            new FileDataStorageManager(account, context.getContentResolver());
+                    SynchronizeFileOperation sfo =
+                            new SynchronizeFileOperation(finalFile, null, account, true, context);
+                    RemoteOperationResult result = sfo.execute(storageManager, context);
+                    if (result.getCode() == RemoteOperationResult.ResultCode.SYNC_CONFLICT) {
+                        // ISSUE 5: if the user is not running the app (this is a service!),
+                        // this can be very intrusive; a notification should be preferred
+                        Intent i = new Intent(context, ConflictsResolveActivity.class);
+                        i.setFlags(i.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
+                        i.putExtra(ConflictsResolveActivity.EXTRA_FILE, finalFile);
+                        i.putExtra(ConflictsResolveActivity.EXTRA_ACCOUNT, account);
+                        context.startActivity(i);
+                    } else {
+                        FileStorageUtils.checkIfFileFinishedSaving(finalFile);
+                        if (!result.isSuccess()) {
+                            NotificationUtils.showSyncFailedNotification();
+                        }
+                    }
+                } catch (Exception exception) {
+                    NotificationUtils.showSyncFailedNotification();
+                }
+            });
+
+            syncThread.start();
+            try {
+                syncThread.join();
+            } catch (InterruptedException e) {
+                Log.e(TAG, "Failed to wait for thread to finish");
             }
         }
 
@@ -185,7 +217,16 @@ public class DocumentsStorageProvider extends DocumentsProvider {
         return result;
     }
 
+    @SuppressLint("LongLogTag")
     private void updateCurrentStorageManagerIfNeeded(long docId) {
+        if (mRootIdToStorageManager == null) {
+            try {
+                queryRoots(FileCursor.DEFAULT_DOCUMENT_PROJECTION);
+            } catch (FileNotFoundException e) {
+                Log.e(TAG, "Failed to query roots");
+            }
+        }
+
         if (mCurrentStorageManager == null ||
                 (mRootIdToStorageManager.containsKey(docId) &&
                         mCurrentStorageManager != mRootIdToStorageManager.get(docId))) {

+ 4 - 9
src/main/java/com/owncloud/android/providers/FileContentProvider.java

@@ -42,6 +42,7 @@ import android.os.Binder;
 import android.os.Build;
 import android.support.annotation.NonNull;
 import android.text.TextUtils;
+import android.util.Log;
 
 import com.owncloud.android.MainApp;
 import com.owncloud.android.R;
@@ -99,7 +100,7 @@ public class FileContentProvider extends ContentProvider {
         if (isCallerNotAllowed()) {
             return -1;
         }
-                
+
         SQLiteDatabase db = mDbHelper.getWritableDatabase();
         db.beginTransaction();
         try {
@@ -116,7 +117,7 @@ public class FileContentProvider extends ContentProvider {
         if (isCallerNotAllowed()) {
             return -1;
         }
-        
+
         int count = 0;
         switch (mUriMatcher.match(uri)) {
             case SINGLE_FILE:
@@ -1552,13 +1553,7 @@ public class FileContentProvider extends ContentProvider {
     }
 
     private boolean isCallerNotAllowed() {
-        String callingPackage;
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
-            callingPackage = getCallingPackage();
-        } else {
-            callingPackage = mContext.getPackageManager().getNameForUid(Binder.getCallingUid());
-        }
-
+        String callingPackage = mContext.getPackageManager().getNameForUid(Binder.getCallingUid());
         return callingPackage == null || !callingPackage.contains(mContext.getPackageName());
     }
 }

+ 8 - 1
src/main/java/com/owncloud/android/ui/helpers/FileOperationsHelper.java

@@ -176,6 +176,9 @@ public class FileOperationsHelper {
                 } else {
                     if (file.isDown()) {
                         FileStorageUtils.checkIfFileFinishedSaving(file);
+                        if (!result.isSuccess()) {
+                            DisplayUtils.showSnackMessage(mFileActivity, R.string.file_not_synced);
+                        }
                         EventBus.getDefault().post(new SyncEventFinished(intent));
                     }
                 }
@@ -245,13 +248,17 @@ public class FileOperationsHelper {
                     } else {
                         if (launchables != null && launchables.size() > 0) {
                             try {
+                                if (!result.isSuccess()) {
+                                    DisplayUtils.showSnackMessage(mFileActivity, R.string.file_not_synced);
+                                }
+
                                 mFileActivity.startActivity(
                                         Intent.createChooser(
                                                 finalOpenFileWithIntent,
                                                 mFileActivity.getString(R.string.actionbar_open_with)
                                         )
                                 );
-                            } catch (ActivityNotFoundException anfe) {
+                            } catch (ActivityNotFoundException exception) {
                                 DisplayUtils.showSnackMessage(mFileActivity, R.string.file_list_no_app_for_file_type);
                             }
                         } else {

+ 25 - 2
src/main/java/com/owncloud/android/ui/notifications/NotificationUtils.java

@@ -26,12 +26,16 @@ import android.os.HandlerThread;
 import android.os.Process;
 import android.support.v4.app.NotificationCompat;
 
+import com.owncloud.android.MainApp;
+import com.owncloud.android.R;
 import com.owncloud.android.utils.ThemeUtils;
 
 import java.util.Random;
 
 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 
+import static android.content.Context.NOTIFICATION_SERVICE;
+
 public class NotificationUtils {
 
     public static final String NOTIFICATION_CHANNEL_DOWNLOAD = "NOTIFICATION_CHANNEL_DOWNLOAD";
@@ -76,7 +80,26 @@ public class NotificationUtils {
                  notificationManager.cancel(notificationId);
                  ((HandlerThread)Thread.currentThread()).getLooper().quit();
              } 
-        }, delayInMillis); 
-    
+        }, delayInMillis);
+    }
+
+    public static void showSyncFailedNotification() {
+        Context context = MainApp.getAppContext();
+        NotificationCompat.Builder mNotificationBuilder = NotificationUtils.newNotificationBuilder(context);
+        mNotificationBuilder
+                .setTicker(context.getString(R.string.sync_fail_ticker))
+                .setSmallIcon(R.drawable.notification_icon)
+                .setContentTitle(context.getString(R.string.sync_fail_ticker))
+                .setContentText(context.getString(R.string.file_not_synced_short));
+
+
+        if ((android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O)) {
+            mNotificationBuilder.setChannelId(NotificationUtils.NOTIFICATION_CHANNEL_DOWNLOAD);
+        }
+
+        NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(NOTIFICATION_SERVICE);
+        if (mNotificationManager != null) {
+            mNotificationManager.notify(R.string.sync_fail_ticker, mNotificationBuilder.build());
+        }
     }
 }

+ 1 - 1
src/main/java/org/nextcloud/providers/cursors/FileCursor.java

@@ -31,7 +31,7 @@ import com.owncloud.android.utils.MimeTypeUtil;
 @TargetApi(Build.VERSION_CODES.KITKAT)
 public class FileCursor extends MatrixCursor {
 
-    private static final String[] DEFAULT_DOCUMENT_PROJECTION = new String[] {
+    public static final String[] DEFAULT_DOCUMENT_PROJECTION = new String[] {
             Document.COLUMN_DOCUMENT_ID, Document.COLUMN_DISPLAY_NAME,
             Document.COLUMN_MIME_TYPE, Document.COLUMN_SIZE,
             Document.COLUMN_FLAGS, Document.COLUMN_LAST_MODIFIED

+ 2 - 0
src/main/res/values/strings.xml

@@ -651,6 +651,8 @@
     <string name="picture_set_as_no_app">No app found to set a picture with!</string>
     <string name="privacy">Privacy</string>
     <string name="file_not_found">File not found!</string>
+    <string name="file_not_synced">Failed to sync the desired file. Last version available is shown.</string>
+    <string name="file_not_synced_short">Last version available is shown.</string>
 
     <!-- Auto upload -->
     <string name="autoupload_custom_folder">Set up a custom folder</string>