Refactor permissions requests to use ActivityResultContract (#4391)

The app currently uses a custom callback system for requesting
permissions, located in `BaseActivity`.
This code doesn't work when the activity gets re-created before the
permission is granted: the callback will be lost with the Activity and
no action will be performed after the permission is granted.

To avoid these issues while still simplifying the code, Google
recommends to use the ActivityResultContract APIs to request
permissions, which allow to register persistent callbacks. This pull
request removes the legacy API and replaces the calls with
`registerForActivityResult(ActivityResultContracts.RequestPermission())`.

- `ActivityResultContracts.RequestPermission` will check if the
permission is already granted and call the callback synchronously when
possible. So this check doesn't need to be performed anymore.
- In `SearchStatusesFragment` and `SFragment`, the download action to
launch after granting the permission requires an argument (a list of
media URLs). This argument is temporarily stored in a Fragment field and
saved and restored as part of the instance state, so the action can
properly resume after an Activity re-creation.
This commit is contained in:
Christophe Beyls 2024-05-03 21:42:35 +02:00 committed by GitHub
commit ad1afdd241
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 133 additions and 150 deletions

View file

@ -23,7 +23,6 @@ import android.content.ClipData
import android.content.ClipboardManager
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.graphics.Color
import android.net.Uri
@ -38,6 +37,7 @@ import android.view.View
import android.view.WindowManager
import android.webkit.MimeTypeMap
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.app.ShareCompat
import androidx.core.content.FileProvider
import androidx.core.content.IntentCompat
@ -92,6 +92,19 @@ class ViewMediaActivity :
private val toolbarVisibilityListeners = mutableListOf<ToolbarVisibilityListener>()
private var imageUrl: String? = null
private val requestDownloadMediaPermissionLauncher =
registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
if (isGranted) {
downloadMedia()
} else {
showErrorDialog(
binding.toolbar,
R.string.error_media_download_permission,
R.string.action_retry
) { requestDownloadMedia() }
}
}
fun addToolbarVisibilityListener(listener: ToolbarVisibilityListener): Function0<Boolean> {
this.toolbarVisibilityListeners.add(listener)
listener(isToolbarVisible)
@ -235,22 +248,7 @@ class ViewMediaActivity :
private fun requestDownloadMedia() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
requestPermissions(
arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE)
) { _, grantResults ->
if (
grantResults.isNotEmpty() &&
grantResults[0] == PackageManager.PERMISSION_GRANTED
) {
downloadMedia()
} else {
showErrorDialog(
binding.toolbar,
R.string.error_media_download_permission,
R.string.action_retry
) { requestDownloadMedia() }
}
}
requestDownloadMediaPermissionLauncher.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE)
} else {
downloadMedia()
}