Skip to content

Instantly share code, notes, and snippets.

@eduardobape
Created August 9, 2022 18:17
Show Gist options
  • Save eduardobape/8130ebb06604ccdb127272af5f735622 to your computer and use it in GitHub Desktop.
Save eduardobape/8130ebb06604ccdb127272af5f735622 to your computer and use it in GitHub Desktop.
Permissions flow for all Android versions using Activity Result APIs
package com.edudev.livedataroomexample
import android.Manifest
import android.app.Activity
import android.app.AlertDialog
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Bundle
import android.provider.Settings
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import com.edudev.livedataroomexample.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private val permissionCamera =
registerForActivityResult(ActivityResultContracts.RequestPermission()) { granted ->
if (granted) {
// Access to the camera is allowed, open the camera
Toast.makeText(this, "Access to the camera is allowed", Toast.LENGTH_SHORT).show()
} else if (!shouldShowRequestPermissionRationale(Manifest.permission.CAMERA)) {
// This else-if branch is useful in two cases:
// 1) On Android 10 or below, if the user has chosen the option "Don't ask again" on
// the permission default dialog, this dialog won't be displayed anymore.
// This situation is detected is shouldShowRequestPermissionRationale returns false.
// 2) On Android 11 or higher, if the user has already denied a permission two or
// more times, the permission default dialog won't be displayed anymore.
// This situation is detected is shouldShowRequestPermissionRationale returns false.
// In both cases, the only possibility would be displayed a custom dialog where the user
// could choose an option to navigate to the app settings in order to grant a determined
// permission. This custom dialog should displayed the reason why the permission
// needs to be granted.
showDialogPermissionsSettings()
} else {
// This else branch is executed in different ways, depending on the Android version:
// 1) On Android 10 or below, this branch is executed if the user has denied a
// permission one or more times, but they have never chosen the option "Don't ask again".
// 2) On Android 11 or higher, this branch is executed only the user denies a permission
// for the first time.
// In both cases, it's recommended to show a custom dialog displaying the reason why
// the permission needs to be granted. If the user chooses the option to grant this
// permission on this custom dialog, the Android permission default dialog will be
// opened by Android.
showDialogRationaleCameraPermission()
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
handleEventNewWord()
handleEventOpenCamera()
}
private fun handleEventNewWord() {
binding.fabNewWord.setOnClickListener {
newWordResult.launch(Intent(this, NewWordActivity::class.java))
}
}
private fun handleEventOpenCamera() {
binding.fabCamera.setOnClickListener {
when {
ContextCompat.checkSelfPermission(this,
Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED -> {
// Check if the user granted the camera permission
Toast.makeText(this, "Ya me diste permiso", Toast.LENGTH_SHORT).show()
}
shouldShowRequestPermissionRationale(Manifest.permission.CAMERA) -> {
// On Android 10 or below, shouldShowRequestPermissionRationale is true if the
// user has already denied the permission at least once.
// On Android 11 or higher, shouldShowRequestPermissionRationale is true only
// when the user has denied the permission only once. When the user denies the
// permission two or more times, shouldShowRequestPermissionRationale is false
showDialogRationaleCameraPermission()
}
else -> {
// The Android permission default dialog is shown the first time the app is opened
permissionCamera.launch(Manifest.permission.CAMERA)
}
}
}
}
private fun showDialogRationaleCameraPermission() {
val alertDialogBuilder = AlertDialog.Builder(this)
with(alertDialogBuilder) {
setMessage("Necesito permiso para hacerte fotos please!")
setPositiveButton("Sí") { _, _ ->
permissionCamera.launch(Manifest.permission.CAMERA)
}
setNegativeButton("No") { _, _ ->
Toast.makeText(this@MainActivity,
"Has elegido No, por tanto, fotos no",
Toast.LENGTH_SHORT).show()
}
create().show()
}
}
private fun showDialogPermissionsSettings() {
val alertDialogBuilder = AlertDialog.Builder(this)
with(alertDialogBuilder) {
setMessage("¿Desea acceder a la configuración de la app para activar el permiso de la cámara")
setPositiveButton("Sí") { _, _ ->
val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
intent.data = Uri.parse("package:$packageName")
startActivity(intent)
}
setNegativeButton("No") { _, _ ->
}
alertDialogBuilder.create().show()
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment