Browse Source

Merge pull request #13084 from nextcloud/bugfix/general-crash-fixes

Bugfix General Crash Fixes
Alper Öztürk 11 months ago
parent
commit
ac5cd4e0b8

+ 5 - 0
app/src/main/java/com/owncloud/android/operations/RefreshFolderOperation.java

@@ -453,6 +453,11 @@ public class RefreshFolderOperation extends RemoteOperation {
         // get 'fresh data' from the database
         // get 'fresh data' from the database
         mLocalFolder = mStorageManager.getFileByPath(mLocalFolder.getRemotePath());
         mLocalFolder = mStorageManager.getFileByPath(mLocalFolder.getRemotePath());
 
 
+        if (mLocalFolder == null) {
+            Log_OC.d(TAG,"mLocalFolder cannot be null");
+            return;
+        }
+
         // parse data from remote folder
         // parse data from remote folder
         OCFile remoteFolder = FileStorageUtils.fillOCFile((RemoteFile) folderAndFiles.get(0));
         OCFile remoteFolder = FileStorageUtils.fillOCFile((RemoteFile) folderAndFiles.get(0));
         remoteFolder.setParentId(mLocalFolder.getParentId());
         remoteFolder.setParentId(mLocalFolder.getParentId());

+ 22 - 4
app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java

@@ -13,6 +13,7 @@
  */
  */
 package com.owncloud.android.ui.activity;
 package com.owncloud.android.ui.activity;
 
 
+import android.accounts.Account;
 import android.accounts.AuthenticatorException;
 import android.accounts.AuthenticatorException;
 import android.annotation.SuppressLint;
 import android.annotation.SuppressLint;
 import android.app.Activity;
 import android.app.Activity;
@@ -31,7 +32,9 @@ import android.net.Uri;
 import android.os.Build;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Bundle;
 import android.os.Environment;
 import android.os.Environment;
+import android.os.Handler;
 import android.os.IBinder;
 import android.os.IBinder;
+import android.os.Looper;
 import android.os.Parcelable;
 import android.os.Parcelable;
 import android.text.TextUtils;
 import android.text.TextUtils;
 import android.view.Menu;
 import android.view.Menu;
@@ -609,7 +612,8 @@ public class FileDisplayActivity extends FileActivity
 
 
     private OCFileListFragment getOCFileListFragmentFromFile() {
     private OCFileListFragment getOCFileListFragmentFromFile() {
         final Fragment leftFragment = getLeftFragment();
         final Fragment leftFragment = getLeftFragment();
-        OCFileListFragment listOfFiles = null;
+        OCFileListFragment listOfFiles;
+
         if (leftFragment instanceof OCFileListFragment) {
         if (leftFragment instanceof OCFileListFragment) {
             listOfFiles = (OCFileListFragment) leftFragment;
             listOfFiles = (OCFileListFragment) leftFragment;
         } else {
         } else {
@@ -617,12 +621,25 @@ public class FileDisplayActivity extends FileActivity
             Bundle args = new Bundle();
             Bundle args = new Bundle();
             args.putBoolean(OCFileListFragment.ARG_ALLOW_CONTEXTUAL_ACTIONS, true);
             args.putBoolean(OCFileListFragment.ARG_ALLOW_CONTEXTUAL_ACTIONS, true);
             listOfFiles.setArguments(args);
             listOfFiles.setArguments(args);
-            setLeftFragment(listOfFiles);
-            getSupportFragmentManager().executePendingTransactions();
+
+            FragmentManager fm = getSupportFragmentManager();
+            boolean isExecutingTransactions = !fm.isStateSaved() && !fm.executePendingTransactions();
+
+            if (isExecutingTransactions) {
+                setLeftFragment(listOfFiles);
+                fm.executePendingTransactions();
+            } else {
+                new Handler(Looper.getMainLooper()).post(() -> {
+                    setLeftFragment(listOfFiles);
+                    fm.executePendingTransactions();
+                });
+            }
         }
         }
+
         return listOfFiles;
         return listOfFiles;
     }
     }
 
 
+
     public void showFileActions(OCFile file) {
     public void showFileActions(OCFile file) {
         dismissLoadingDialog();
         dismissLoadingDialog();
         OCFileListFragment listOfFiles = getOCFileListFragmentFromFile();
         OCFileListFragment listOfFiles = getOCFileListFragmentFromFile();
@@ -1354,7 +1371,8 @@ public class FileDisplayActivity extends FileActivity
         public void onReceive(Context context, Intent intent) {
         public void onReceive(Context context, Intent intent) {
             String uploadedRemotePath = intent.getStringExtra(FileUploadWorker.EXTRA_REMOTE_PATH);
             String uploadedRemotePath = intent.getStringExtra(FileUploadWorker.EXTRA_REMOTE_PATH);
             String accountName = intent.getStringExtra(FileUploadWorker.ACCOUNT_NAME);
             String accountName = intent.getStringExtra(FileUploadWorker.ACCOUNT_NAME);
-            boolean sameAccount = getAccount() != null && accountName.equals(getAccount().name);
+            Account account = getAccount();
+            boolean sameAccount = accountName != null && account != null && accountName.equals(account.name);
             OCFile currentDir = getCurrentDir();
             OCFile currentDir = getCurrentDir();
             boolean isDescendant = currentDir != null && uploadedRemotePath != null && uploadedRemotePath.startsWith(currentDir.getRemotePath());
             boolean isDescendant = currentDir != null && uploadedRemotePath != null && uploadedRemotePath.startsWith(currentDir.getRemotePath());
 
 

+ 12 - 9
app/src/main/java/com/owncloud/android/ui/fragment/ExtendedListFragment.java

@@ -454,18 +454,21 @@ public class ExtendedListFragment extends Fragment implements
      * Restore index and position
      * Restore index and position
      */
      */
     protected void restoreIndexAndTopPosition() {
     protected void restoreIndexAndTopPosition() {
-        if (mIndexes.size() > 0) {
-            // needs to be checked; not every browse-up had a browse-down before
+        if (mIndexes == null || mIndexes.isEmpty()) {
+            Log_OC.d(TAG,"Indexes is null or empty");
+            return;
+        }
 
 
-            int index = mIndexes.remove(mIndexes.size() - 1);
-            final int firstPosition = mFirstPositions.remove(mFirstPositions.size() - 1);
-            int top = mTops.remove(mTops.size() - 1);
+        // needs to be checked; not every browse-up had a browse-down before
 
 
-            Log_OC.v(TAG, "Setting selection to position: " + firstPosition + "; top: "
-                + top + "; index: " + index);
+        int index = mIndexes.remove(mIndexes.size() - 1);
+        final int firstPosition = mFirstPositions.remove(mFirstPositions.size() - 1);
+        int top = mTops.remove(mTops.size() - 1);
 
 
-            scrollToPosition(firstPosition);
-        }
+        Log_OC.v(TAG, "Setting selection to position: " + firstPosition + "; top: "
+            + top + "; index: " + index);
+
+        scrollToPosition(firstPosition);
     }
     }
 
 
     private void scrollToPosition(int position) {
     private void scrollToPosition(int position) {

+ 52 - 39
app/src/main/java/com/owncloud/android/ui/fragment/OCFileListFragment.java

@@ -1292,6 +1292,24 @@ public class OCFileListFragment extends ExtendedListFragment implements
         listDirectory(directory, null, onlyOnDevice, fromSearch);
         listDirectory(directory, null, onlyOnDevice, fromSearch);
     }
     }
 
 
+    private OCFile getDirectoryForListDirectory(OCFile directory, FileDataStorageManager storageManager) {
+        if (directory == null) {
+            if (mFile != null) {
+                directory = mFile;
+            } else {
+                directory = storageManager.getFileByPath(ROOT_PATH);
+            }
+        }
+
+        // If that's not a directory -> List its parent
+        if (!directory.isFolder()) {
+            Log_OC.w(TAG, "You see, that is not a directory -> " + directory);
+            directory = storageManager.getFileById(directory.getParentId());
+        }
+
+        return directory;
+    }
+
     /**
     /**
      * Lists the given directory on the view. When the input parameter is null, it will either refresh the last known
      * Lists the given directory on the view. When the input parameter is null, it will either refresh the last known
      * directory. list the root if there never was a directory.
      * directory. list the root if there never was a directory.
@@ -1301,52 +1319,47 @@ public class OCFileListFragment extends ExtendedListFragment implements
     public void listDirectory(OCFile directory, OCFile file, boolean onlyOnDevice, boolean fromSearch) {
     public void listDirectory(OCFile directory, OCFile file, boolean onlyOnDevice, boolean fromSearch) {
         if (!searchFragment) {
         if (!searchFragment) {
             FileDataStorageManager storageManager = mContainerActivity.getStorageManager();
             FileDataStorageManager storageManager = mContainerActivity.getStorageManager();
-            if (storageManager != null) {
-                // Check input parameters for null
-                if (directory == null) {
-                    if (mFile != null) {
-                        directory = mFile;
-                    } else {
-                        directory = storageManager.getFileByPath(ROOT_PATH);
-                        if (directory == null) {
-                            return; // no files, wait for sync
-                        }
-                    }
-                }
+            if (storageManager == null) {
+                Log_OC.d(TAG, "fileDataStorageManager is null");
+                return;
+            }
 
 
-                // If that's not a directory -> List its parent
-                if (!directory.isFolder()) {
-                    Log_OC.w(TAG, "You see, that is not a directory -> " + directory);
-                    directory = storageManager.getFileById(directory.getParentId());
+            directory = getDirectoryForListDirectory(directory, storageManager);
+            if (directory == null) {
+                Log_OC.d(TAG, "directory is null, no files, wait for sync");
+                return;
+            }
 
 
-                    if (directory == null) {
-                        return; // no files, wait for sync
-                    }
-                }
+            if (mLimitToMimeType == null) {
+                Log_OC.d(TAG, "mLimitToMimeType is null");
+                return;
+            }
 
 
-                mAdapter.swapDirectory(
-                    accountManager.getUser(),
-                    directory,
-                    storageManager,
-                    onlyOnDevice,
-                    mLimitToMimeType
-                                      );
+            if (mAdapter == null) {
+                Log_OC.d(TAG, "mAdapter is null");
+                return;
+            }
 
 
-                OCFile previousDirectory = mFile;
-                mFile = directory;
+            mAdapter.swapDirectory(
+                accountManager.getUser(),
+                directory,
+                storageManager,
+                onlyOnDevice,
+                mLimitToMimeType);
 
 
-                updateLayout();
+            OCFile previousDirectory = mFile;
+            mFile = directory;
 
 
-                if (file != null) {
-                    mAdapter.setHighlightedItem(file);
-                    int position = mAdapter.getItemPosition(file);
-                    if (position != -1) {
-                        getRecyclerView().scrollToPosition(position);
-                    }
-                } else if (previousDirectory == null || !previousDirectory.equals(directory)) {
-                    getRecyclerView().scrollToPosition(0);
-                }
+            updateLayout();
 
 
+            if (file != null) {
+                mAdapter.setHighlightedItem(file);
+                int position = mAdapter.getItemPosition(file);
+                if (position != -1) {
+                    getRecyclerView().scrollToPosition(position);
+                }
+            } else if (previousDirectory == null || !previousDirectory.equals(directory)) {
+                getRecyclerView().scrollToPosition(0);
             }
             }
         } else if (isSearchEventSet(searchEvent)) {
         } else if (isSearchEventSet(searchEvent)) {
             handleSearchEvent(searchEvent);
             handleSearchEvent(searchEvent);

+ 31 - 15
app/src/main/java/com/owncloud/android/ui/preview/PreviewImageFragment.java

@@ -230,26 +230,42 @@ public class PreviewImageFragment extends FileFragment implements Injectable {
     @Override
     @Override
     public void onActivityCreated(Bundle savedInstanceState) {
     public void onActivityCreated(Bundle savedInstanceState) {
         super.onActivityCreated(savedInstanceState);
         super.onActivityCreated(savedInstanceState);
-        if (savedInstanceState != null) {
-            if (!ignoreFirstSavedState) {
-                OCFile file = BundleExtensionsKt.getParcelableArgument(savedInstanceState, EXTRA_FILE, OCFile.class);
-                if (file == null) {
-                    return;
-                }
+        if (savedInstanceState == null) {
+            Log_OC.d(TAG, "savedInstanceState is null");
+            return;
+        }
 
 
-                setFile(file);
+        if (ignoreFirstSavedState) {
+            Log_OC.d(TAG, "Saved state ignored");
+            ignoreFirstSavedState = false;
+            return;
+        }
 
 
-                try {
-                    binding.image.setScale(Math.min(binding.image.getMaximumScale(), savedInstanceState.getFloat(EXTRA_ZOOM)));
-                } catch (IllegalArgumentException e) {
-                    Log_OC.d(TAG, "Error caught at setScale: " + e);
-                }
-            } else {
-                ignoreFirstSavedState = false;
-            }
+        OCFile file = BundleExtensionsKt.getParcelableArgument(savedInstanceState, EXTRA_FILE, OCFile.class);
+        if (file == null) {
+            Log_OC.d(TAG, "file cannot be found inside the savedInstanceState");
+            return;
+        }
+
+        setFile(file);
+
+        float maxScale = binding.image.getMaximumScale();
+        float minScale = binding.image.getMinimumScale();
+        float savedScale = savedInstanceState.getFloat(EXTRA_ZOOM);
+
+        if (savedScale < minScale || savedScale > maxScale) {
+            Log_OC.d(TAG, "Saved scale " + savedScale + " is out of bounds, setting to default scale.");
+            savedScale = Math.min(maxScale, Math.max(minScale, savedScale));
+        }
+
+        try {
+            binding.image.setScale(savedScale);
+        } catch (IllegalArgumentException e) {
+            Log_OC.d(TAG, "Error caught at setScale: " + e);
         }
         }
     }
     }
 
 
+
     @Override
     @Override
     public void onSaveInstanceState(@NonNull Bundle outState) {
     public void onSaveInstanceState(@NonNull Bundle outState) {
         super.onSaveInstanceState(outState);
         super.onSaveInstanceState(outState);

+ 9 - 2
app/src/main/java/com/owncloud/android/ui/unifiedsearch/UnifiedSearchRemoteRepository.kt

@@ -13,6 +13,7 @@ import com.nextcloud.client.network.ClientFactory
 import com.nextcloud.common.NextcloudClient
 import com.nextcloud.common.NextcloudClient
 import com.owncloud.android.lib.common.SearchProviders
 import com.owncloud.android.lib.common.SearchProviders
 import com.owncloud.android.lib.common.utils.Log_OC
 import com.owncloud.android.lib.common.utils.Log_OC
+import kotlinx.coroutines.CoroutineExceptionHandler
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.launch
@@ -24,12 +25,18 @@ class UnifiedSearchRemoteRepository(
 ) : IUnifiedSearchRepository {
 ) : IUnifiedSearchRepository {
 
 
     private var providers: SearchProviders? = null
     private var providers: SearchProviders? = null
+    private val tag = "UnifiedSearchRemoteRepository"
 
 
-    private fun runAsyncWithNcClient(callback: (client: NextcloudClient) -> Unit) =
-        CoroutineScope(Dispatchers.IO).launch {
+    private fun runAsyncWithNcClient(callback: (client: NextcloudClient) -> Unit) {
+        val coroutineExceptionHandler = CoroutineExceptionHandler { _, exception ->
+            Log_OC.d(tag, "CoroutineExceptionHandler got at runAsyncWithNcClient $exception")
+        }
+
+        CoroutineScope(Dispatchers.IO).launch(coroutineExceptionHandler) {
             val client = clientFactory.createNextcloudClient(currentAccountProvider.user)
             val client = clientFactory.createNextcloudClient(currentAccountProvider.user)
             callback(client)
             callback(client)
         }
         }
+    }
 
 
     override fun queryAll(
     override fun queryAll(
         query: String,
         query: String,