Browse Source

Merge pull request #1140 from nextcloud/autoUploadWithoutStoragePermission

Prevent NPE when disabling "storage permission" and then access auto upload
Andy Scherzinger 7 years ago
parent
commit
72e8888bd2

+ 43 - 6
src/main/java/com/owncloud/android/datamodel/MediaProvider.java

@@ -1,33 +1,40 @@
-/**
+/*
  * Nextcloud Android client application
  *
  * @author Andy Scherzinger
  * Copyright (C) 2016 Andy Scherzinger
  * Copyright (C) 2016 Nextcloud
- * <p>
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
  * License as published by the Free Software Foundation; either
  * version 3 of the License, or any later version.
- * <p>
+ *
  * 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 AFFERO GENERAL PUBLIC LICENSE for more details.
- * <p>
+ *
  * You should have received a copy of the GNU Affero General Public
  * License along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
 package com.owncloud.android.datamodel;
 
+import android.Manifest;
+import android.app.Activity;
 import android.content.ContentResolver;
 import android.database.Cursor;
 import android.net.Uri;
 import android.provider.MediaStore;
+import android.support.design.widget.Snackbar;
 import android.util.Log;
+import android.view.View;
 
 import com.owncloud.android.MainApp;
+import com.owncloud.android.R;
+import com.owncloud.android.utils.DisplayUtils;
+import com.owncloud.android.utils.PermissionUtil;
 
 import java.io.File;
 import java.util.ArrayList;
@@ -54,9 +61,39 @@ public class MediaProvider {
      * @param itemLimit       the number of media items (usually images) to be returned per media folder.
      * @return list with media folders
      */
-    public static List<MediaFolder> getMediaFolders(ContentResolver contentResolver, int itemLimit) {
+    public static List<MediaFolder> getMediaFolders(ContentResolver contentResolver, int itemLimit,
+                                                    final Activity activity) {
+        // check permissions
+        if (!PermissionUtil.checkSelfPermission(activity.getApplicationContext(),
+                Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
+            // Check if we should show an explanation
+            if (PermissionUtil.shouldShowRequestPermissionRationale(activity,
+                    Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
+                // Show explanation to the user and then request permission
+                Snackbar snackbar = Snackbar.make(activity.findViewById(R.id.ListLayout),
+                        R.string.permission_storage_access, Snackbar.LENGTH_INDEFINITE)
+                        .setAction(R.string.common_ok, new View.OnClickListener() {
+                            @Override
+                            public void onClick(View v) {
+                                PermissionUtil.requestWriteExternalStoreagePermission(activity);
+                            }
+                        });
+
+                DisplayUtils.colorSnackbar(activity.getApplicationContext(), snackbar);
+
+                snackbar.show();
+            } else {
+                // No explanation needed, request the permission.
+                PermissionUtil.requestWriteExternalStoreagePermission(activity);
+            }
+        }
+
         // query media/image folders
-        Cursor cursorFolders = contentResolver.query(MEDIA_URI, FOLDER_PROJECTION, null, null, FOLDER_SORT_ORDER);
+        Cursor cursorFolders = null;
+        if (PermissionUtil.checkSelfPermission(activity.getApplicationContext(),
+                Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
+            cursorFolders = contentResolver.query(MEDIA_URI, FOLDER_PROJECTION, null, null, FOLDER_SORT_ORDER);
+        }
         List<MediaFolder> mediaFolders = new ArrayList<>();
         String dataPath = MainApp.getStoragePath() + File.separator + MainApp.getDataFolder();
 

+ 38 - 11
src/main/java/com/owncloud/android/ui/activity/FolderSyncActivity.java

@@ -1,20 +1,20 @@
-/**
+/*
  * Nextcloud Android client application
  *
  * @author Andy Scherzinger
  * Copyright (C) 2016 Andy Scherzinger
  * Copyright (C) 2016 Nextcloud
- * <p>
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
  * License as published by the Free Software Foundation; either
  * version 3 of the License, or any later version.
- * <p>
+ *
  * 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 AFFERO GENERAL PUBLIC LICENSE for more details.
- * <p>
+ *
  * You should have received a copy of the GNU Affero General Public
  * License along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
@@ -23,6 +23,7 @@ package com.owncloud.android.ui.activity;
 
 import android.accounts.Account;
 import android.content.Intent;
+import android.content.pm.PackageManager;
 import android.os.Bundle;
 import android.os.Handler;
 import android.support.annotation.NonNull;
@@ -30,6 +31,7 @@ import android.support.design.widget.BottomNavigationView;
 import android.support.v4.app.FragmentManager;
 import android.support.v4.app.FragmentTransaction;
 import android.support.v4.widget.DrawerLayout;
+import android.support.v7.app.ActionBar;
 import android.support.v7.widget.GridLayoutManager;
 import android.support.v7.widget.RecyclerView;
 import android.view.MenuItem;
@@ -53,6 +55,7 @@ import com.owncloud.android.ui.dialog.SyncedFolderPreferencesDialogFragment;
 import com.owncloud.android.ui.dialog.parcel.SyncedFolderParcelable;
 import com.owncloud.android.utils.AnalyticsUtils;
 import com.owncloud.android.utils.DisplayUtils;
+import com.owncloud.android.utils.PermissionUtil;
 
 import java.io.File;
 import java.util.ArrayList;
@@ -111,8 +114,11 @@ public class FolderSyncActivity extends FileActivity implements FolderSyncAdapte
 
         setupContent();
 
-        getSupportActionBar().setTitle(getString(R.string.drawer_folder_sync));
-        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
+        ActionBar actionBar = getSupportActionBar();
+        if (actionBar != null) {
+            actionBar.setTitle(getString(R.string.drawer_folder_sync));
+            actionBar.setDisplayHomeAsUpEnabled(true);
+        }
     }
 
     @Override
@@ -149,7 +155,7 @@ public class FolderSyncActivity extends FileActivity implements FolderSyncAdapte
             DisplayUtils.setupBottomBar(bottomNavigationView, getResources(), this, -1);
         }
 
-        load(gridWidth * 2);
+        load(gridWidth * 2, false);
     }
 
     /**
@@ -157,8 +163,8 @@ public class FolderSyncActivity extends FileActivity implements FolderSyncAdapte
      *
      * @param perFolderMediaItemLimit the amount of media items to be loaded/shown per media folder
      */
-    private void load(final int perFolderMediaItemLimit) {
-        if (mAdapter.getItemCount() > 0) {
+    private void load(final int perFolderMediaItemLimit, boolean force) {
+        if (mAdapter.getItemCount() > 0 && !force) {
             return;
         }
         setListShown(false);
@@ -167,9 +173,9 @@ public class FolderSyncActivity extends FileActivity implements FolderSyncAdapte
             @Override
             public void run() {
                 final List<MediaFolder> mediaFolders = MediaProvider.getMediaFolders(getContentResolver(),
-                        perFolderMediaItemLimit);
+                        perFolderMediaItemLimit, FolderSyncActivity.this);
                 List<SyncedFolder> syncedFolderArrayList = mSyncedFolderProvider.getSyncedFolders();
-                List<SyncedFolder> currentAccountSyncedFoldersList = new ArrayList<SyncedFolder>();
+                List<SyncedFolder> currentAccountSyncedFoldersList = new ArrayList<>();
                 Account currentAccount = AccountUtils.getCurrentOwnCloudAccount(FolderSyncActivity.this);
                 for (SyncedFolder syncedFolder : syncedFolderArrayList) {
                     if (syncedFolder.getAccount().equals(currentAccount.name)) {
@@ -493,4 +499,25 @@ public class FolderSyncActivity extends FileActivity implements FolderSyncAdapte
         item.setEnabled(enabled);
         return item;
     }
+
+    @Override
+    public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[],
+                                           @NonNull int[] grantResults) {
+        switch (requestCode) {
+            case PermissionUtil.PERMISSIONS_WRITE_EXTERNAL_STORAGE: {
+                // If request is cancelled, result arrays are empty.
+                if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
+                    // permission was granted
+                    int gridWidth = getResources().getInteger(R.integer.media_grid_width);
+                    load(gridWidth * 2, true);
+                } else {
+                    // permission denied --> do nothing
+                    return;
+                }
+                return;
+            }
+            default:
+                super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+        }
+    }
 }

+ 1 - 0
src/main/res/layout/folder_sync_layout.xml

@@ -40,6 +40,7 @@
             android:layout_height="match_parent"
             android:layout_above="@+id/bottom_navigation_view"
             android:layout_below="@+id/appbar"
+            android:id="@+id/ListLayout"
             android:orientation="vertical">
 
             <android.support.v7.widget.RecyclerView