Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -82,15 +82,13 @@ class MediaFoldersDetectionWork constructor(
contentResolver,
1,
null,
true,
viewThemeUtils
true
)
val videoMediaFolders = MediaProvider.getVideoFolders(
contentResolver,
1,
null,
true,
viewThemeUtils
true
)
val imageMediaFolderPaths: MutableList<String> = ArrayList()
val videoMediaFolderPaths: MutableList<String> = ArrayList()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,6 @@ public final class AppPreferencesImpl implements AppPreferences {

private static final String PREF__PDF_ZOOM_TIP_SHOWN = "pdf_zoom_tip_shown";
private static final String PREF__MEDIA_FOLDER_LAST_PATH = "media_folder_last_path";

private static final String PREF__STORAGE_PERMISSION_REQUESTED = "storage_permission_requested";
private static final String PREF__IN_APP_REVIEW_DATA = "in_app_review_data";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,15 @@ import android.content.Context
import android.content.ContextWrapper
import android.content.Intent
import android.content.IntentFilter
import android.net.Uri
import android.os.Build
import android.os.Handler
import android.os.Looper
import android.provider.Settings
import android.view.WindowInsets
import android.view.WindowManager
import android.widget.Toast
import androidx.core.net.toUri
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import com.owncloud.android.R
Expand Down Expand Up @@ -69,3 +72,22 @@ fun Context.getActivity(): Activity? = when (this) {
is ContextWrapper -> baseContext.getActivity()
else -> null
}

fun Activity.openMediaPermissions(requestCode: Int) {
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
data = Uri.fromParts("package", packageName, null)
}
startActivityForResult(intent, requestCode)
}

fun Activity.openAllFilesAccessSettings(requestCode: Int) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
return
}

val intent = Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION).apply {
data = "package:$packageName".toUri()
}

startActivityForResult(intent, requestCode)
}
8 changes: 3 additions & 5 deletions app/src/main/java/com/owncloud/android/MainApp.java
Original file line number Diff line number Diff line change
Expand Up @@ -628,7 +628,7 @@ public static void initSyncOperations(
updateAutoUploadEntries(clock);

if (getAppContext() != null) {
if (PermissionUtil.checkExternalStoragePermission(getAppContext())) {
if (PermissionUtil.checkStoragePermission(getAppContext())) {
splitOutAutoUploadEntries(clock, viewThemeUtils);
} else {
preferences.setAutoUploadSplitEntriesEnabled(true);
Expand Down Expand Up @@ -904,13 +904,11 @@ private static void splitOutAutoUploadEntries(Clock clock,
final List<MediaFolder> imageMediaFolders = MediaProvider.getImageFolders(contentResolver,
1,
null,
true,
viewThemeUtils);
true);
final List<MediaFolder> videoMediaFolders = MediaProvider.getVideoFolders(contentResolver,
1,
null,
true,
viewThemeUtils);
true);

ArrayList<Long> idsToDelete = new ArrayList<>();
List<SyncedFolder> syncedFolders = syncedFolderProvider.getSyncedFolders();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,13 @@ private MediaProvider() {
public static List<MediaFolder> getImageFolders(ContentResolver contentResolver,
int itemLimit,
@Nullable final AppCompatActivity activity,
boolean getWithoutActivity,
final ViewThemeUtils viewThemeUtils) {
boolean getWithoutActivity) {
// check permissions
checkPermissions(activity, viewThemeUtils);
checkPermissions(activity);

// query media/image folders
Cursor cursorFolders = null;
if (activity != null && PermissionUtil.checkExternalStoragePermission(activity.getApplicationContext())
if (activity != null && PermissionUtil.checkStoragePermission(activity.getApplicationContext())
|| getWithoutActivity) {
cursorFolders = ContentResolverHelper.queryResolver(contentResolver, IMAGES_MEDIA_URI,
IMAGES_FOLDER_PROJECTION, null, null,
Expand Down Expand Up @@ -159,25 +158,23 @@ private static boolean isValidAndExistingFilePath(String filePath) {
return filePath != null && filePath.lastIndexOf('/') > 0 && new File(filePath).exists();
}

private static void checkPermissions(@Nullable AppCompatActivity activity,
final ViewThemeUtils viewThemeUtils) {
private static void checkPermissions(@Nullable AppCompatActivity activity) {
if (activity != null &&
!PermissionUtil.checkExternalStoragePermission(activity.getApplicationContext())) {
PermissionUtil.requestExternalStoragePermission(activity, viewThemeUtils, true);
!PermissionUtil.checkStoragePermission(activity.getApplicationContext())) {
PermissionUtil.requestStoragePermissionIfNeeded(activity);
}
}

public static List<MediaFolder> getVideoFolders(ContentResolver contentResolver,
int itemLimit,
@Nullable final AppCompatActivity activity,
boolean getWithoutActivity,
final ViewThemeUtils viewThemeUtils) {
boolean getWithoutActivity) {
// check permissions
checkPermissions(activity, viewThemeUtils);
checkPermissions(activity);

// query media/image folders
Cursor cursorFolders = null;
if ((activity != null && PermissionUtil.checkExternalStoragePermission(activity.getApplicationContext()))
if ((activity != null && PermissionUtil.checkStoragePermission(activity.getApplicationContext()))
|| getWithoutActivity) {
cursorFolders = contentResolver.query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, VIDEOS_FOLDER_PROJECTION,
null, null, null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import android.accounts.AuthenticatorException;
import android.accounts.OperationCanceledException;
import android.app.Activity;
import android.app.ComponentCaller;
import android.content.Context;
import android.content.Intent;
import android.content.res.ColorStateList;
Expand Down Expand Up @@ -52,7 +53,6 @@
import com.nextcloud.client.account.User;
import com.nextcloud.client.di.Injectable;
import com.nextcloud.client.files.DeepLinkConstants;
import com.nextcloud.client.jobs.upload.FileUploadWorker;
import com.nextcloud.client.network.ClientFactory;
import com.nextcloud.client.onboarding.FirstRunActivity;
import com.nextcloud.client.preferences.AppPreferences;
Expand Down Expand Up @@ -145,6 +145,8 @@ public abstract class DrawerActivity extends ToolbarActivity
private static final int MENU_ITEM_EXTERNAL_LINK = 111;
private static final int MAX_LOGO_SIZE_PX = 1000;
private static final int RELATIVE_THRESHOLD_WARNING = 80;
public static final int REQ_ALL_FILES_ACCESS = 3001;
public static final int REQ_MEDIA_ACCESS = 3000;

/**
* Reference to the drawer layout.
Expand Down Expand Up @@ -1432,4 +1434,21 @@ public void showBottomNavigationBar(boolean show) {
public BottomNavigationView getBottomNavigationView() {
return bottomNavigationView;
}

@Override
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data, @NonNull ComponentCaller caller) {
super.onActivityResult(requestCode, resultCode, data, caller);

if (requestCode == REQ_ALL_FILES_ACCESS || requestCode == REQ_MEDIA_ACCESS) {
checkStoragePermissionWarningBannerVisibility();
}
}

private void checkStoragePermissionWarningBannerVisibility() {
if (this instanceof SyncedFoldersActivity syncedFoldersActivity) {
syncedFoldersActivity.setupStoragePermissionWarningBanner();
} else if (this instanceof UploadFilesActivity uploadFilesActivity) {
uploadFilesActivity.setupStoragePermissionWarningBanner();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ import com.owncloud.android.utils.ErrorMessageAdapter
import com.owncloud.android.utils.FileSortOrder
import com.owncloud.android.utils.MimeTypeUtil
import com.owncloud.android.utils.PermissionUtil
import com.owncloud.android.utils.PermissionUtil.requestExternalStoragePermission
import com.owncloud.android.utils.PermissionUtil.requestStoragePermissionIfNeeded
import com.owncloud.android.utils.PermissionUtil.requestNotificationPermission
import com.owncloud.android.utils.PushUtils
import com.owncloud.android.utils.StringUtils
Expand Down Expand Up @@ -364,7 +364,7 @@ class FileDisplayActivity :
if (dialog != null && dialog.isShowing) {
dialog.dismiss()
supportFragmentManager.beginTransaction().remove(fragment).commitNowAllowingStateLoss()
requestExternalStoragePermission(this, viewThemeUtils)
requestStoragePermissionIfNeeded(this)
}
}
}
Expand All @@ -379,7 +379,7 @@ class FileDisplayActivity :
// storage permissions handled in onRequestPermissionsResult
requestNotificationPermission(this)
} else {
requestExternalStoragePermission(this, viewThemeUtils)
requestStoragePermissionIfNeeded(this)
}

if (intent.getParcelableArgument(
Expand Down Expand Up @@ -462,7 +462,7 @@ class FileDisplayActivity :
// handle notification permission on API level >= 33
PermissionUtil.PERMISSIONS_POST_NOTIFICATIONS ->
// dialogue was dismissed -> prompt for storage permissions
requestExternalStoragePermission(this, viewThemeUtils)
requestStoragePermissionIfNeeded(this)

// If request is cancelled, result arrays are empty.
PermissionUtil.PERMISSIONS_EXTERNAL_STORAGE ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
import com.nextcloud.client.preferences.AppPreferences;
import com.nextcloud.client.preferences.AppPreferencesImpl;
import com.nextcloud.client.preferences.DarkMode;
import com.nextcloud.utils.extensions.ContextExtensionsKt;
import com.nextcloud.utils.extensions.ViewExtensionsKt;
import com.nextcloud.utils.mdm.MDMConfig;
import com.owncloud.android.MainApp;
Expand All @@ -76,6 +77,7 @@
import com.owncloud.android.utils.DisplayUtils;
import com.owncloud.android.utils.EncryptionUtils;
import com.owncloud.android.utils.MimeTypeUtil;
import com.owncloud.android.utils.PermissionUtil;
import com.owncloud.android.utils.theme.CapabilityUtils;
import com.owncloud.android.utils.theme.ViewThemeUtils;

Expand All @@ -93,6 +95,8 @@
import androidx.core.content.ContextCompat;
import androidx.core.content.res.ResourcesCompat;

import static com.owncloud.android.ui.activity.DrawerActivity.REQ_ALL_FILES_ACCESS;

/**
* An Activity that allows the user to change the application's settings.
* It proxies the necessary calls via {@link androidx.appcompat.app.AppCompatDelegate} to be used with AppCompat.
Expand Down Expand Up @@ -374,6 +378,7 @@ private void setupSyncCategory() {

setupAutoUploadPreference(preferenceCategorySync);
setupInternalTwoWaySyncPreference();
setupAllFilesAccessPreference(preferenceCategorySync);
}

private void setupMoreCategory() {
Expand Down Expand Up @@ -620,6 +625,23 @@ private void setupInternalTwoWaySyncPreference() {
});
}

private void setupAllFilesAccessPreference(PreferenceCategory category) {
Preference allFilesAccess = findPreference("allFilesAccess");

if (PermissionUtil.checkAllFilesAccess()) {
category.removePreference(allFilesAccess);
} else {
if (allFilesAccess.getParent() == null) {
category.addPreference(allFilesAccess);
}
}

allFilesAccess.setOnPreferenceClickListener(preference -> {
ContextExtensionsKt.openAllFilesAccessSettings(this, REQ_ALL_FILES_ACCESS);
return true;
});
}

private void setupBackupPreference() {
Preference pContactsBackup = findPreference("backup");
if (pContactsBackup != null) {
Expand Down Expand Up @@ -1067,6 +1089,9 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
storageMigration.setStorageMigrationProgressListener(this);
storageMigration.migrate();
}
} else if (requestCode == REQ_ALL_FILES_ACCESS) {
final PreferenceCategory preferenceCategorySync = (PreferenceCategory) findPreference("sync");
setupAllFilesAccessPreference(preferenceCategorySync);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,11 @@ import com.nextcloud.client.jobs.upload.FileUploadWorker
import com.nextcloud.client.preferences.SubFolderRule
import com.nextcloud.utils.extensions.getParcelableArgument
import com.nextcloud.utils.extensions.isDialogFragmentReady
import com.nextcloud.utils.extensions.setVisibleIf
import com.owncloud.android.BuildConfig
import com.owncloud.android.MainApp
import com.owncloud.android.R
import com.owncloud.android.databinding.StoragePermissionWarningBannerBinding
import com.owncloud.android.databinding.SyncedFoldersLayoutBinding
import com.owncloud.android.datamodel.ArbitraryDataProviderImpl
import com.owncloud.android.datamodel.MediaFolder
Expand All @@ -53,6 +55,7 @@ import com.owncloud.android.datamodel.SyncedFolderProvider
import com.owncloud.android.files.services.NameCollisionPolicy
import com.owncloud.android.lib.common.utils.Log_OC
import com.owncloud.android.ui.adapter.SyncedFolderAdapter
import com.owncloud.android.ui.adapter.storagePermissionBanner.setup
import com.owncloud.android.ui.decoration.MediaGridItemDecoration
import com.owncloud.android.ui.dialog.ConfirmationDialogFragment
import com.owncloud.android.ui.dialog.SyncedFolderPreferencesDialogFragment
Expand Down Expand Up @@ -197,7 +200,15 @@ class SyncedFoldersActivity :
setTheme(R.style.FallbackThemingTheme)
}
binding.emptyList.emptyListViewAction.setOnClickListener { showHiddenItems() }
PermissionUtil.requestExternalStoragePermission(this, viewThemeUtils, true)
setupStoragePermissionWarningBanner()
}

fun setupStoragePermissionWarningBanner() {
val storagePermissionWarningBanner = binding.storagePermissionWarningBanner.root
StoragePermissionWarningBannerBinding.bind(storagePermissionWarningBanner).apply {
setup(this@SyncedFoldersActivity, R.string.storage_permission_banner_auto_upload_text)
}
storagePermissionWarningBanner.setVisibleIf(!PermissionUtil.checkStoragePermission(this))
}

override fun onCreateOptionsMenu(menu: Menu): Boolean {
Expand Down Expand Up @@ -274,16 +285,14 @@ class SyncedFoldersActivity :
contentResolver,
perFolderMediaItemLimit,
this@SyncedFoldersActivity,
false,
viewThemeUtils
false
)
mediaFolders.addAll(
MediaProvider.getVideoFolders(
contentResolver,
perFolderMediaItemLimit,
this@SyncedFoldersActivity,
false,
viewThemeUtils
false
)
)

Expand Down Expand Up @@ -519,7 +528,7 @@ class SyncedFoldersActivity :
android.R.id.home -> finish()
R.id.action_create_custom_folder -> {
Log_OC.d(TAG, "Show custom folder dialog")
if (PermissionUtil.checkExternalStoragePermission(this)) {
if (PermissionUtil.checkStoragePermission(this)) {
val emptyCustomFolder = SyncedFolderDisplayItem(
SyncedFolder.UNPERSISTED_ID,
null,
Expand All @@ -542,7 +551,7 @@ class SyncedFoldersActivity :
)
onSyncFolderSettingsClick(0, emptyCustomFolder)
} else {
PermissionUtil.requestExternalStoragePermission(this, viewThemeUtils, true)
PermissionUtil.requestStoragePermissionIfNeeded(this)
}
result = super.onOptionsItemSelected(item)
}
Expand Down
Loading
Loading