Disable partial media permissions

Partial media permissions don't make much sense for a Gallery app.
This commit is contained in:
Naveen Singh 2024-09-06 23:51:15 +05:30
parent f89f81d7e6
commit 267fdaf69f
No known key found for this signature in database
GPG key ID: 35F7D64346B28ED7
11 changed files with 167 additions and 95 deletions

View file

@ -14,6 +14,7 @@
<uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" /> <uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" /> <uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" /> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission <uses-permission
android:name="android.permission.MANAGE_EXTERNAL_STORAGE" android:name="android.permission.MANAGE_EXTERNAL_STORAGE"

View file

@ -158,30 +158,18 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
} }
// just request the permission, tryLoadGallery will then trigger in onResume // just request the permission, tryLoadGallery will then trigger in onResume
handleMediaPermissions { success -> handleMediaPermissions()
if (!success) {
toast(org.fossify.commons.R.string.no_storage_permissions)
finish()
}
}
} }
private fun handleMediaPermissions(callback: (granted: Boolean) -> Unit) { private fun handleMediaPermissions(callback: (() -> Unit)? = null) {
handlePermission(getPermissionToRequest()) { granted -> requestMediaPermissions(enableRationale = true) {
callback(granted) callback?.invoke()
if (granted && isRPlus()) { if (isRPlus() && !mWasMediaManagementPromptShown) {
handlePermission(PERMISSION_MEDIA_LOCATION) {}
if (isTiramisuPlus()) {
handlePermission(PERMISSION_READ_MEDIA_VIDEO) {}
}
if (!mWasMediaManagementPromptShown) {
mWasMediaManagementPromptShown = true mWasMediaManagementPromptShown = true
handleMediaManagementPrompt { } handleMediaManagementPrompt { }
} }
} }
} }
}
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
@ -497,9 +485,8 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
private fun tryLoadGallery() { private fun tryLoadGallery() {
// avoid calling anything right after granting the permission, it will be called from onResume() // avoid calling anything right after granting the permission, it will be called from onResume()
val wasMissingPermission = config.appRunCount == 1 && !hasPermission(getPermissionToRequest()) val wasMissingPermission = config.appRunCount == 1 && !hasAllPermissions(getPermissionsToRequest())
handleMediaPermissions { success -> handleMediaPermissions {
if (success) {
if (wasMissingPermission) { if (wasMissingPermission) {
return@handleMediaPermissions return@handleMediaPermissions
} }
@ -519,10 +506,6 @@ class MainActivity : SimpleActivity(), DirectoryOperationsListener {
} }
setupLayoutManager() setupLayoutManager()
} else {
toast(org.fossify.commons.R.string.no_storage_permissions)
finish()
}
} }
} }

View file

@ -15,7 +15,6 @@ import com.bumptech.glide.Glide
import com.bumptech.glide.request.RequestOptions import com.bumptech.glide.request.RequestOptions
import com.bumptech.glide.request.target.SimpleTarget import com.bumptech.glide.request.target.SimpleTarget
import com.bumptech.glide.request.transition.Transition import com.bumptech.glide.request.transition.Transition
import org.fossify.commons.dialogs.ConfirmationDialog
import org.fossify.commons.dialogs.CreateNewFolderDialog import org.fossify.commons.dialogs.CreateNewFolderDialog
import org.fossify.commons.dialogs.RadioGroupDialog import org.fossify.commons.dialogs.RadioGroupDialog
import org.fossify.commons.extensions.* import org.fossify.commons.extensions.*
@ -370,12 +369,11 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
} }
private fun tryLoadGallery() { private fun tryLoadGallery() {
handlePermission(getPermissionToRequest()) { requestMediaPermissions {
if (it) { val dirName = when (mPath) {
val dirName = when { FAVORITES -> getString(org.fossify.commons.R.string.favorites)
mPath == FAVORITES -> getString(org.fossify.commons.R.string.favorites) RECYCLE_BIN -> getString(org.fossify.commons.R.string.recycle_bin)
mPath == RECYCLE_BIN -> getString(org.fossify.commons.R.string.recycle_bin) config.OTGPath -> getString(org.fossify.commons.R.string.usb)
mPath == config.OTGPath -> getString(org.fossify.commons.R.string.usb)
else -> getHumanizedFilename(mPath) else -> getHumanizedFilename(mPath)
} }
@ -395,10 +393,6 @@ class MediaActivity : SimpleActivity(), MediaOperationsListener {
getMedia() getMedia()
setupLayoutManager() setupLayoutManager()
} else {
toast(org.fossify.commons.R.string.no_storage_permissions)
finish()
}
} }
} }

View file

@ -46,13 +46,8 @@ open class PhotoVideoActivity : SimpleActivity(), ViewPagerFragment.FragmentList
setupOptionsMenu() setupOptionsMenu()
refreshMenuItems() refreshMenuItems()
handlePermission(getPermissionToRequest()) { requestMediaPermissions {
if (it) {
checkIntent(savedInstanceState) checkIntent(savedInstanceState)
} else {
toast(org.fossify.commons.R.string.no_storage_permissions)
finish()
}
} }
} }

View file

@ -5,20 +5,24 @@ import android.net.Uri
import android.provider.MediaStore.Images import android.provider.MediaStore.Images
import android.provider.MediaStore.Video import android.provider.MediaStore.Video
import android.view.WindowManager import android.view.WindowManager
import androidx.appcompat.app.AlertDialog
import org.fossify.commons.activities.BaseSimpleActivity import org.fossify.commons.activities.BaseSimpleActivity
import org.fossify.commons.dialogs.FilePickerDialog import org.fossify.commons.dialogs.FilePickerDialog
import org.fossify.commons.extensions.getParentPath import org.fossify.commons.extensions.*
import org.fossify.commons.extensions.getRealPathFromURI
import org.fossify.commons.extensions.scanPathRecursively
import org.fossify.commons.helpers.ensureBackgroundThread import org.fossify.commons.helpers.ensureBackgroundThread
import org.fossify.commons.helpers.isPiePlus import org.fossify.commons.helpers.isPiePlus
import org.fossify.gallery.R import org.fossify.gallery.R
import org.fossify.gallery.dialogs.StoragePermissionRequiredDialog
import org.fossify.gallery.extensions.addPathToDB import org.fossify.gallery.extensions.addPathToDB
import org.fossify.gallery.extensions.config import org.fossify.gallery.extensions.config
import org.fossify.gallery.extensions.updateDirectoryPath import org.fossify.gallery.extensions.updateDirectoryPath
import org.fossify.gallery.helpers.getPermissionsToRequest
open class SimpleActivity : BaseSimpleActivity() { open class SimpleActivity : BaseSimpleActivity() {
val observer = object : ContentObserver(null) {
private var dialog: AlertDialog? = null
private val observer = object : ContentObserver(null) {
override fun onChange(selfChange: Boolean, uri: Uri?) { override fun onChange(selfChange: Boolean, uri: Uri?) {
super.onChange(selfChange, uri) super.onChange(selfChange, uri)
if (uri != null) { if (uri != null) {
@ -94,4 +98,44 @@ open class SimpleActivity : BaseSimpleActivity() {
} }
} }
} }
protected fun requestMediaPermissions(enableRationale: Boolean = false, onGranted: () -> Unit) {
when {
hasAllPermissions(getPermissionsToRequest()) -> onGranted()
config.showPermissionRationale -> {
if (enableRationale) {
showPermissionRationale()
} else {
onPermissionDenied()
}
}
else -> {
handlePartialMediaPermissions(getPermissionsToRequest(), force = true) { granted ->
if (granted) {
onGranted()
} else {
config.showPermissionRationale = true
showPermissionRationale()
}
}
}
}
}
private fun showPermissionRationale() {
dialog?.dismiss()
StoragePermissionRequiredDialog(
activity = this,
onOkay = ::openDeviceSettings,
onCancel = ::onPermissionDenied
) { dialog ->
this.dialog = dialog
}
}
private fun onPermissionDenied() {
toast(org.fossify.commons.R.string.no_storage_permissions)
finish()
}
} }

View file

@ -97,15 +97,10 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
checkNotchSupport() checkNotchSupport()
(MediaActivity.mMedia.clone() as ArrayList<ThumbnailItem>).filterIsInstanceTo(mMediaFiles, Medium::class.java) (MediaActivity.mMedia.clone() as ArrayList<ThumbnailItem>).filterIsInstanceTo(mMediaFiles, Medium::class.java)
handlePermission(getPermissionToRequest()) { requestMediaPermissions {
if (it) {
initViewPager( initViewPager(
savedPath = savedInstanceState?.getString(SAVED_PATH).orEmpty() savedPath = savedInstanceState?.getString(SAVED_PATH).orEmpty()
) )
} else {
toast(org.fossify.commons.R.string.no_storage_permissions)
finish()
}
} }
initFavorites() initFavorites()

View file

@ -0,0 +1,36 @@
package org.fossify.gallery.dialogs
import androidx.appcompat.app.AlertDialog
import org.fossify.commons.extensions.getAlertDialogBuilder
import org.fossify.commons.extensions.setupDialogStuff
import org.fossify.gallery.activities.SimpleActivity
import org.fossify.gallery.databinding.DialogStoragePermissionRequiredBinding
class StoragePermissionRequiredDialog(
val activity: SimpleActivity,
val onOkay: () -> Unit,
val onCancel: () -> Unit,
val callback: (dialog: AlertDialog) -> Unit
) {
init {
val binding = DialogStoragePermissionRequiredBinding.inflate(activity.layoutInflater)
activity.getAlertDialogBuilder()
.setPositiveButton(org.fossify.commons.R.string.go_to_settings) { dialog, _ ->
dialog.dismiss()
onOkay()
}
.setNegativeButton(org.fossify.commons.R.string.cancel) { dialog, _ ->
dialog.dismiss()
onCancel()
}
.apply {
activity.setupDialogStuff(
view = binding.root,
dialog = this,
cancelOnTouchOutside = false,
callback = callback
)
}
}
}

View file

@ -567,4 +567,8 @@ class Config(context: Context) : BaseConfig(context) {
var lastExportedFavoritesFolder: String var lastExportedFavoritesFolder: String
get() = prefs.getString(LAST_EXPORTED_FAVORITES_FOLDER, "")!! get() = prefs.getString(LAST_EXPORTED_FAVORITES_FOLDER, "")!!
set(lastExportedFavoritesFolder) = prefs.edit().putString(LAST_EXPORTED_FAVORITES_FOLDER, lastExportedFavoritesFolder).apply() set(lastExportedFavoritesFolder) = prefs.edit().putString(LAST_EXPORTED_FAVORITES_FOLDER, lastExportedFavoritesFolder).apply()
var showPermissionRationale: Boolean
get() = prefs.getBoolean(SHOW_PERMISSION_RATIONALE, false)
set(showPermissionRationale) = prefs.edit().putBoolean(SHOW_PERMISSION_RATIONALE, showPermissionRationale).apply()
} }

View file

@ -98,6 +98,7 @@ const val CUSTOM_FOLDERS_ORDER = "custom_folders_order"
const val AVOID_SHOWING_ALL_FILES_PROMPT = "avoid_showing_all_files_prompt" const val AVOID_SHOWING_ALL_FILES_PROMPT = "avoid_showing_all_files_prompt"
const val SEARCH_ALL_FILES_BY_DEFAULT = "search_all_files_by_default" const val SEARCH_ALL_FILES_BY_DEFAULT = "search_all_files_by_default"
const val LAST_EXPORTED_FAVORITES_FOLDER = "last_exported_favorites_folder" const val LAST_EXPORTED_FAVORITES_FOLDER = "last_exported_favorites_folder"
const val SHOW_PERMISSION_RATIONALE = "show_permission_rationale"
// slideshow // slideshow
const val SLIDESHOW_INTERVAL = "slideshow_interval" const val SLIDESHOW_INTERVAL = "slideshow_interval"
@ -250,8 +251,6 @@ const val THUMBNAIL_FADE_DURATION_MS = 150
fun getPermissionToRequest() = if (isTiramisuPlus()) PERMISSION_READ_MEDIA_IMAGES else PERMISSION_WRITE_STORAGE fun getPermissionToRequest() = if (isTiramisuPlus()) PERMISSION_READ_MEDIA_IMAGES else PERMISSION_WRITE_STORAGE
fun getRequiredPermission() = if (isUpsideDownCakePlus()) PERMISSION_READ_MEDIA_VISUAL_USER_SELECTED else getPermissionToRequest()
fun getPermissionsToRequest(): Collection<Int> { fun getPermissionsToRequest(): Collection<Int> {
val permissions = mutableListOf(getPermissionToRequest()) val permissions = mutableListOf(getPermissionToRequest())
if (isRPlus()) { if (isRPlus()) {

View file

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/message_scrollview"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<org.fossify.commons.views.MyTextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:lineSpacingExtra="@dimen/small_margin"
android:paddingLeft="@dimen/big_margin"
android:paddingTop="@dimen/big_margin"
android:paddingRight="@dimen/big_margin"
android:paddingBottom="@dimen/activity_margin"
android:text="@string/full_storage_permission_required"
android:textAlignment="center"
android:textSize="@dimen/bigger_text_size" />
</ScrollView>

View file

@ -33,6 +33,7 @@
<string name="reorder_by_dragging">Reorder folders by dragging</string> <string name="reorder_by_dragging">Reorder folders by dragging</string>
<string name="reorder_by_dragging_pro">Reorder folders by dragging (Pro)</string> <string name="reorder_by_dragging_pro">Reorder folders by dragging (Pro)</string>
<string name="restore_to_path">Restoring to \'%s\'</string> <string name="restore_to_path">Restoring to \'%s\'</string>
<string name="full_storage_permission_required">Fossify Gallery needs full access to display all your photos and videos. Go to Settings > Permissions > Photos and videos > Allow all.</string>
<!-- Filter --> <!-- Filter -->
<string name="filter_media">Filter media</string> <string name="filter_media">Filter media</string>