refactor(app): improve permissions management
This commit is contained in:
@@ -16,6 +16,7 @@ import io.github.thibaultbee.streampack.data.VideoConfig
|
|||||||
import io.github.thibaultbee.streampack.error.StreamPackError
|
import io.github.thibaultbee.streampack.error.StreamPackError
|
||||||
import io.github.thibaultbee.streampack.example.databinding.ActivityMainBinding
|
import io.github.thibaultbee.streampack.example.databinding.ActivityMainBinding
|
||||||
import io.github.thibaultbee.streampack.example.utils.PermissionsManager
|
import io.github.thibaultbee.streampack.example.utils.PermissionsManager
|
||||||
|
import io.github.thibaultbee.streampack.example.utils.showDialog
|
||||||
import io.github.thibaultbee.streampack.example.utils.toast
|
import io.github.thibaultbee.streampack.example.utils.toast
|
||||||
import io.github.thibaultbee.streampack.ext.rtmp.streamers.CameraRtmpLiveStreamer
|
import io.github.thibaultbee.streampack.ext.rtmp.streamers.CameraRtmpLiveStreamer
|
||||||
import io.github.thibaultbee.streampack.ext.srt.streamers.CameraSrtLiveStreamer
|
import io.github.thibaultbee.streampack.ext.srt.streamers.CameraSrtLiveStreamer
|
||||||
@@ -36,13 +37,30 @@ class MainActivity : AppCompatActivity() {
|
|||||||
private val permissionsManager = PermissionsManager(this,
|
private val permissionsManager = PermissionsManager(this,
|
||||||
streamerRequiredPermissions,
|
streamerRequiredPermissions,
|
||||||
onAllGranted = { inflateStreamer() },
|
onAllGranted = { inflateStreamer() },
|
||||||
onShowPermissionRationale = { true },
|
onShowPermissionRationale = { permissions, onRequiredPermissionLastTime ->
|
||||||
onDenied = {})
|
// Explain why we need permissions
|
||||||
|
showDialog(
|
||||||
|
title = "Permissions denied",
|
||||||
|
message = "Explain why you need to grant $permissions permissions to stream",
|
||||||
|
positiveButtonText = R.string.accept,
|
||||||
|
onPositiveButtonClick = { onRequiredPermissionLastTime() },
|
||||||
|
negativeButtonText = R.string.denied
|
||||||
|
)
|
||||||
|
},
|
||||||
|
onDenied = {
|
||||||
|
showDialog(
|
||||||
|
"Permissions denied",
|
||||||
|
"You need to grant all permissions to stream",
|
||||||
|
positiveButtonText = 0,
|
||||||
|
negativeButtonText = 0
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
// Reports and manages error with [OnErrorListener]
|
// Reports and manages error with [OnErrorListener]
|
||||||
private val errorListener = object : OnErrorListener {
|
private val errorListener = object : OnErrorListener {
|
||||||
override fun onError(error: StreamPackError) {
|
override fun onError(error: StreamPackError) {
|
||||||
toast("An error occured: $error")
|
toast("An error occurred: $error")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,8 +132,8 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onStart() {
|
||||||
super.onResume()
|
super.onStart()
|
||||||
permissionsManager.requestPermissions()
|
permissionsManager.requestPermissions()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,40 @@
|
|||||||
package io.github.thibaultbee.streampack.example.utils
|
package io.github.thibaultbee.streampack.example.utils
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.DialogInterface
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
import androidx.annotation.StringRes
|
||||||
|
import androidx.appcompat.app.AlertDialog
|
||||||
|
|
||||||
fun Context.toast(message: String) =
|
fun Context.toast(message: String) =
|
||||||
Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
|
Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
|
||||||
|
|
||||||
|
fun Context.showDialog(
|
||||||
|
title: String,
|
||||||
|
message: String = "",
|
||||||
|
@StringRes
|
||||||
|
positiveButtonText: Int = android.R.string.ok,
|
||||||
|
@StringRes
|
||||||
|
negativeButtonText: Int = android.R.string.cancel,
|
||||||
|
onPositiveButtonClick: () -> Unit = {},
|
||||||
|
onNegativeButtonClick: () -> Unit = {}
|
||||||
|
) {
|
||||||
|
AlertDialog.Builder(this)
|
||||||
|
.setTitle(title)
|
||||||
|
.setMessage(message)
|
||||||
|
.apply {
|
||||||
|
if (positiveButtonText != 0) {
|
||||||
|
setPositiveButton(positiveButtonText) { dialogInterface: DialogInterface, _: Int ->
|
||||||
|
dialogInterface.dismiss()
|
||||||
|
onPositiveButtonClick()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (negativeButtonText != 0) {
|
||||||
|
setNegativeButton(negativeButtonText) { dialogInterface: DialogInterface, _: Int ->
|
||||||
|
dialogInterface.dismiss()
|
||||||
|
onNegativeButtonClick()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.show()
|
||||||
|
}
|
||||||
@@ -8,43 +8,60 @@ class PermissionsManager(
|
|||||||
private val activity: ComponentActivity,
|
private val activity: ComponentActivity,
|
||||||
private val requiredPermissions: List<String>,
|
private val requiredPermissions: List<String>,
|
||||||
private val onAllGranted: () -> Unit,
|
private val onAllGranted: () -> Unit,
|
||||||
private val onShowPermissionRationale: (List<String>) -> Boolean,
|
private val onShowPermissionRationale: (List<String>, () -> Unit) -> Unit,
|
||||||
private val onDenied: (List<String>) -> Unit
|
private val onDenied: (List<String>) -> Unit
|
||||||
) {
|
) {
|
||||||
private fun hasPermissions(): Boolean {
|
private fun hasAllPermissions(): Boolean {
|
||||||
return requiredPermissions.all {
|
return requiredPermissions.all {
|
||||||
activity.checkSelfPermission(it) == PackageManager.PERMISSION_GRANTED
|
activity.checkSelfPermission(it) == PackageManager.PERMISSION_GRANTED
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun hasShownAllRationales(): Boolean {
|
||||||
|
return requiredPermissions.all {
|
||||||
|
!activity.shouldShowRequestPermissionRationale(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun requestPermissions() {
|
fun requestPermissions() {
|
||||||
if (hasPermissions()) {
|
if (hasAllPermissions()) {
|
||||||
onAllGranted()
|
onAllGranted()
|
||||||
} else {
|
} else {
|
||||||
var hasShownRationale = false
|
// Either we ask for rationale or we ask for all permissions
|
||||||
requiredPermissions.forEach {
|
if (requestRationales()) {
|
||||||
if (activity.shouldShowRequestPermissionRationale(it)) {
|
|
||||||
hasShownRationale = true
|
|
||||||
// Last chance to show rationale
|
|
||||||
if (onShowPermissionRationale(requiredPermissions)) {
|
|
||||||
requestMultiplePermissions.launch(arrayOf(it))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!hasShownRationale) {
|
|
||||||
requestMultiplePermissions.launch(requiredPermissions.toTypedArray())
|
requestMultiplePermissions.launch(requiredPermissions.toTypedArray())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun requestRationales(): Boolean {
|
||||||
|
// List of permissions that have been denied once. In this case, we should explain why we need them.
|
||||||
|
val rationalesPermission = mutableListOf<String>()
|
||||||
|
requiredPermissions.filter {
|
||||||
|
activity.shouldShowRequestPermissionRationale(it)
|
||||||
|
}.forEach {
|
||||||
|
rationalesPermission.add(it)
|
||||||
|
}
|
||||||
|
if (rationalesPermission.isNotEmpty()) {
|
||||||
|
onShowPermissionRationale(rationalesPermission) {
|
||||||
|
requestMultiplePermissions.launch(rationalesPermission.toTypedArray())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rationalesPermission.isEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
private val requestMultiplePermissions =
|
private val requestMultiplePermissions =
|
||||||
activity.registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
|
activity.registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
|
||||||
permissions.filter { !it.value }.keys.toList().let {
|
val deniedPermissions = permissions.filter { !it.value }.keys.toList()
|
||||||
if (it.isNotEmpty()) {
|
if (deniedPermissions.isNotEmpty()) {
|
||||||
onDenied(it)
|
if (!hasShownAllRationales()) {
|
||||||
|
requestRationales()
|
||||||
|
} else {
|
||||||
|
onDenied(deniedPermissions)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
onAllGranted()
|
onAllGranted()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">My Streaming App</string>
|
<string name="app_name">My Streaming App</string>
|
||||||
|
<string name="denied">Denied</string>
|
||||||
|
<string name="accept">Accept</string>
|
||||||
</resources>
|
</resources>
|
||||||
Reference in New Issue
Block a user