registerForActivityResult has to be called at Fragment creation
This commit is contained in:
parent
a7f034f500
commit
05950ec1c8
|
@ -22,6 +22,7 @@ import android.content.Context
|
|||
import android.content.pm.PackageManager
|
||||
import android.os.Build
|
||||
import android.widget.Toast
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
|
@ -95,6 +96,12 @@ fun logPermissionStatuses(context: Context) {
|
|||
}
|
||||
}
|
||||
|
||||
fun Fragment.registerForPermissionsResult(allGranted: (Boolean) -> Unit): ActivityResultLauncher<Array<String>> {
|
||||
return registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { result ->
|
||||
allGranted.invoke(result.keys.all { result[it] == true })
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* See [.checkPermissions]
|
||||
*
|
||||
|
@ -106,21 +113,21 @@ fun checkPermissions(permissionsToBeGrantedBitMap: Int,
|
|||
activity: Activity,
|
||||
requestCode: Int,
|
||||
@StringRes rationaleMessage: Int = 0): Boolean {
|
||||
return checkPermissions(permissionsToBeGrantedBitMap, activity, null, null, requestCode, rationaleMessage)
|
||||
return checkPermissions(permissionsToBeGrantedBitMap, activity, null, requestCode, rationaleMessage)
|
||||
}
|
||||
|
||||
/**
|
||||
* See [.checkPermissions]
|
||||
*
|
||||
* @param permissionsToBeGrantedBitMap
|
||||
* @param fragment
|
||||
* @param activityResultLauncher from the calling fragment that is requesting the permissions
|
||||
* @return true if the permissions are granted (synchronous flow), false otherwise (asynchronous flow)
|
||||
*/
|
||||
fun checkPermissions(permissionsToBeGrantedBitMap: Int,
|
||||
fragment: Fragment,
|
||||
@StringRes rationaleMessage: Int = 0,
|
||||
allGranted: (Boolean) -> Unit): Boolean {
|
||||
return checkPermissions(permissionsToBeGrantedBitMap, fragment.activity, fragment, allGranted, 0, rationaleMessage)
|
||||
activity: Activity,
|
||||
activityResultLauncher: ActivityResultLauncher<Array<String>>,
|
||||
@StringRes rationaleMessage: Int = 0): Boolean {
|
||||
return checkPermissions(permissionsToBeGrantedBitMap, activity, activityResultLauncher, 0, rationaleMessage)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -138,23 +145,19 @@ fun checkPermissions(permissionsToBeGrantedBitMap: Int,
|
|||
*
|
||||
* @param permissionsToBeGrantedBitMap the permissions bit map to be granted
|
||||
* @param activity the calling Activity that is requesting the permissions (or fragment parent)
|
||||
* @param fragment the calling fragment that is requesting the permissions
|
||||
* @param activityResultLauncher from the calling fragment that is requesting the permissions
|
||||
* @return true if the permissions are granted (synchronous flow), false otherwise (asynchronous flow)
|
||||
*/
|
||||
private fun checkPermissions(permissionsToBeGrantedBitMap: Int,
|
||||
activity: Activity?,
|
||||
fragment: Fragment?,
|
||||
allGranted: ((Boolean) -> Unit)?,
|
||||
activity: Activity,
|
||||
activityResultLauncher: ActivityResultLauncher<Array<String>>?,
|
||||
requestCode: Int,
|
||||
@StringRes rationaleMessage: Int
|
||||
): Boolean {
|
||||
var isPermissionGranted = false
|
||||
|
||||
// sanity check
|
||||
if (null == activity) {
|
||||
Timber.w("## checkPermissions(): invalid input data")
|
||||
isPermissionGranted = false
|
||||
} else if (PERMISSIONS_EMPTY == permissionsToBeGrantedBitMap) {
|
||||
if (PERMISSIONS_EMPTY == permissionsToBeGrantedBitMap) {
|
||||
isPermissionGranted = true
|
||||
} else if (PERMISSIONS_FOR_AUDIO_IP_CALL != permissionsToBeGrantedBitMap
|
||||
&& PERMISSIONS_FOR_VIDEO_IP_CALL != permissionsToBeGrantedBitMap
|
||||
|
@ -224,9 +227,7 @@ private fun checkPermissions(permissionsToBeGrantedBitMap: Int,
|
|||
.setOnCancelListener { Toast.makeText(activity, R.string.missing_permissions_warning, Toast.LENGTH_SHORT).show() }
|
||||
.setPositiveButton(R.string.ok) { _, _ ->
|
||||
if (permissionsListToBeGranted.isNotEmpty()) {
|
||||
fragment?.registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { result ->
|
||||
allGranted?.invoke(result.keys.all { result[it] == true })
|
||||
}
|
||||
activityResultLauncher
|
||||
?.launch(permissionsListToBeGranted.toTypedArray())
|
||||
?: run {
|
||||
ActivityCompat.requestPermissions(activity, permissionsListToBeGranted.toTypedArray(), requestCode)
|
||||
|
@ -267,9 +268,7 @@ private fun checkPermissions(permissionsToBeGrantedBitMap: Int,
|
|||
.show()
|
||||
*/
|
||||
} else {
|
||||
fragment?.registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { result ->
|
||||
allGranted?.invoke(result.keys.all { result[it] == true })
|
||||
}
|
||||
activityResultLauncher
|
||||
?.launch(permissionsArrayToBeGranted)
|
||||
?: run {
|
||||
ActivityCompat.requestPermissions(activity, permissionsArrayToBeGranted, requestCode)
|
||||
|
|
|
@ -28,6 +28,7 @@ import im.vector.app.core.extensions.configureWith
|
|||
import im.vector.app.core.platform.VectorBaseFragment
|
||||
import im.vector.app.core.utils.PERMISSIONS_FOR_TAKING_PHOTO
|
||||
import im.vector.app.core.utils.checkPermissions
|
||||
import im.vector.app.core.utils.registerForPermissionsResult
|
||||
import im.vector.app.features.crypto.verification.VerificationAction
|
||||
import im.vector.app.features.crypto.verification.VerificationBottomSheetViewModel
|
||||
import im.vector.app.features.qrcode.QrCodeScannerActivity
|
||||
|
@ -73,12 +74,14 @@ class VerificationChooseMethodFragment @Inject constructor(
|
|||
state.pendingRequest.invoke()?.transactionId ?: ""))
|
||||
}
|
||||
|
||||
override fun openCamera() {
|
||||
if (checkPermissions(PERMISSIONS_FOR_TAKING_PHOTO, this) { allGranted ->
|
||||
private val openCameraActivityResultLauncher = registerForPermissionsResult { allGranted ->
|
||||
if (allGranted) {
|
||||
doOpenQRCodeScanner()
|
||||
}
|
||||
}) {
|
||||
}
|
||||
|
||||
override fun openCamera() {
|
||||
if (checkPermissions(PERMISSIONS_FOR_TAKING_PHOTO, requireActivity(), openCameraActivityResultLauncher)) {
|
||||
doOpenQRCodeScanner()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -99,6 +99,7 @@ import im.vector.app.core.utils.createJSonViewerStyleProvider
|
|||
import im.vector.app.core.utils.createUIHandler
|
||||
import im.vector.app.core.utils.isValidUrl
|
||||
import im.vector.app.core.utils.openUrlInExternalBrowser
|
||||
import im.vector.app.core.utils.registerForPermissionsResult
|
||||
import im.vector.app.core.utils.saveMedia
|
||||
import im.vector.app.core.utils.shareMedia
|
||||
import im.vector.app.core.utils.toast
|
||||
|
@ -782,40 +783,35 @@ class RoomDetailFragment @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private val startCallActivityResultLauncher = registerForPermissionsResult { allGranted ->
|
||||
if (allGranted) {
|
||||
(roomDetailViewModel.pendingAction as? RoomDetailAction.StartCall)?.let {
|
||||
roomDetailViewModel.pendingAction = null
|
||||
roomDetailViewModel.handle(it)
|
||||
}
|
||||
} else {
|
||||
context?.toast(R.string.permissions_action_not_performed_missing_permissions)
|
||||
cleanUpAfterPermissionNotGranted()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun safeStartCall2(isVideoCall: Boolean) {
|
||||
val startCallAction = RoomDetailAction.StartCall(isVideoCall)
|
||||
roomDetailViewModel.pendingAction = startCallAction
|
||||
if (isVideoCall) {
|
||||
if (checkPermissions(PERMISSIONS_FOR_VIDEO_IP_CALL,
|
||||
this,
|
||||
R.string.permissions_rationale_msg_camera_and_audio) { allGranted ->
|
||||
if (allGranted) {
|
||||
(roomDetailViewModel.pendingAction as? RoomDetailAction.StartCall)?.let {
|
||||
roomDetailViewModel.pendingAction = null
|
||||
roomDetailViewModel.handle(it)
|
||||
}
|
||||
} else {
|
||||
context?.toast(R.string.permissions_action_not_performed_missing_permissions)
|
||||
cleanUpAfterPermissionNotGranted()
|
||||
}
|
||||
}) {
|
||||
requireActivity(),
|
||||
startCallActivityResultLauncher,
|
||||
R.string.permissions_rationale_msg_camera_and_audio)) {
|
||||
roomDetailViewModel.pendingAction = null
|
||||
roomDetailViewModel.handle(startCallAction)
|
||||
}
|
||||
} else {
|
||||
if (checkPermissions(PERMISSIONS_FOR_AUDIO_IP_CALL,
|
||||
this,
|
||||
R.string.permissions_rationale_msg_record_audio) { allGranted ->
|
||||
if (allGranted) {
|
||||
(roomDetailViewModel.pendingAction as? RoomDetailAction.StartCall)?.let {
|
||||
roomDetailViewModel.pendingAction = null
|
||||
roomDetailViewModel.handle(it)
|
||||
}
|
||||
} else {
|
||||
context?.toast(R.string.permissions_action_not_performed_missing_permissions)
|
||||
cleanUpAfterPermissionNotGranted()
|
||||
}
|
||||
}) {
|
||||
requireActivity(),
|
||||
startCallActivityResultLauncher,
|
||||
R.string.permissions_rationale_msg_record_audio)) {
|
||||
roomDetailViewModel.pendingAction = null
|
||||
roomDetailViewModel.handle(startCallAction)
|
||||
}
|
||||
|
@ -1005,6 +1001,18 @@ class RoomDetailFragment @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private val writingFileActivityResultLauncher = registerForPermissionsResult { allGranted ->
|
||||
if (allGranted) {
|
||||
val pendingUri = roomDetailViewModel.pendingUri
|
||||
if (pendingUri != null) {
|
||||
roomDetailViewModel.pendingUri = null
|
||||
sendUri(pendingUri)
|
||||
}
|
||||
} else {
|
||||
cleanUpAfterPermissionNotGranted()
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupComposer() {
|
||||
autoCompleter.setup(composerLayout.composerEditText)
|
||||
|
||||
|
@ -1037,17 +1045,7 @@ class RoomDetailFragment @Inject constructor(
|
|||
|
||||
override fun onRichContentSelected(contentUri: Uri): Boolean {
|
||||
// We need WRITE_EXTERNAL permission
|
||||
return if (checkPermissions(PERMISSIONS_FOR_WRITING_FILES, this@RoomDetailFragment) { allGranted ->
|
||||
if (allGranted) {
|
||||
val pendingUri = roomDetailViewModel.pendingUri
|
||||
if (pendingUri != null) {
|
||||
roomDetailViewModel.pendingUri = null
|
||||
sendUri(pendingUri)
|
||||
}
|
||||
} else {
|
||||
cleanUpAfterPermissionNotGranted()
|
||||
}
|
||||
}) {
|
||||
return if (checkPermissions(PERMISSIONS_FOR_WRITING_FILES, requireActivity(), writingFileActivityResultLauncher)) {
|
||||
sendUri(contentUri)
|
||||
} else {
|
||||
roomDetailViewModel.pendingUri = contentUri
|
||||
|
@ -1556,9 +1554,7 @@ class RoomDetailFragment @Inject constructor(
|
|||
)
|
||||
}
|
||||
|
||||
private fun onSaveActionClicked(action: EventSharedAction.Save) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q
|
||||
&& !checkPermissions(PERMISSIONS_FOR_WRITING_FILES, this) { allGranted ->
|
||||
private val saveActionActivityResultLauncher = registerForPermissionsResult { allGranted ->
|
||||
if (allGranted) {
|
||||
sharedActionViewModel.pendingAction?.let {
|
||||
handleActions(it)
|
||||
|
@ -1567,7 +1563,11 @@ class RoomDetailFragment @Inject constructor(
|
|||
} else {
|
||||
cleanUpAfterPermissionNotGranted()
|
||||
}
|
||||
}) {
|
||||
}
|
||||
|
||||
private fun onSaveActionClicked(action: EventSharedAction.Save) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q
|
||||
&& !checkPermissions(PERMISSIONS_FOR_WRITING_FILES, requireActivity(), saveActionActivityResultLauncher)) {
|
||||
sharedActionViewModel.pendingAction = action
|
||||
return
|
||||
}
|
||||
|
@ -1805,8 +1805,7 @@ class RoomDetailFragment @Inject constructor(
|
|||
|
||||
// AttachmentTypeSelectorView.Callback
|
||||
|
||||
override fun onTypeSelected(type: AttachmentTypeSelectorView.Type) {
|
||||
if (checkPermissions(type.permissionsBit, this) { allGranted ->
|
||||
private val typeSelectedActivityResultLauncher = registerForPermissionsResult { allGranted ->
|
||||
if (allGranted) {
|
||||
val pendingType = attachmentsHelper.pendingType
|
||||
if (pendingType != null) {
|
||||
|
@ -1816,7 +1815,10 @@ class RoomDetailFragment @Inject constructor(
|
|||
} else {
|
||||
cleanUpAfterPermissionNotGranted()
|
||||
}
|
||||
}) {
|
||||
}
|
||||
|
||||
override fun onTypeSelected(type: AttachmentTypeSelectorView.Type) {
|
||||
if (checkPermissions(type.permissionsBit, requireActivity(), typeSelectedActivityResultLauncher)) {
|
||||
launchAttachmentProcess(type)
|
||||
} else {
|
||||
attachmentsHelper.pendingType = type
|
||||
|
|
|
@ -48,6 +48,7 @@ import im.vector.app.core.platform.VectorBaseFragment
|
|||
import im.vector.app.core.utils.PERMISSIONS_FOR_TAKING_PHOTO
|
||||
import im.vector.app.core.utils.checkPermissions
|
||||
import im.vector.app.core.utils.copyToClipboard
|
||||
import im.vector.app.core.utils.registerForPermissionsResult
|
||||
import im.vector.app.core.utils.startSharePlainTextIntent
|
||||
import im.vector.app.features.crypto.util.toImageRes
|
||||
import im.vector.app.features.home.AvatarRenderer
|
||||
|
@ -283,14 +284,16 @@ class RoomProfileFragment @Inject constructor(
|
|||
.show()
|
||||
}
|
||||
|
||||
private var avatarCameraUri: Uri? = null
|
||||
private fun onAvatarTypeSelected(isCamera: Boolean) {
|
||||
if (isCamera) {
|
||||
if (checkPermissions(PERMISSIONS_FOR_TAKING_PHOTO, this) { allGranted ->
|
||||
private val takePhotoActivityResultLauncher = registerForPermissionsResult { allGranted ->
|
||||
if (allGranted) {
|
||||
onAvatarTypeSelected(true)
|
||||
}
|
||||
}) {
|
||||
}
|
||||
|
||||
private var avatarCameraUri: Uri? = null
|
||||
private fun onAvatarTypeSelected(isCamera: Boolean) {
|
||||
if (isCamera) {
|
||||
if (checkPermissions(PERMISSIONS_FOR_TAKING_PHOTO, requireActivity(), takePhotoActivityResultLauncher)) {
|
||||
avatarCameraUri = MultiPicker.get(MultiPicker.CAMERA).startWithExpectingFile(this)
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -51,6 +51,7 @@ import im.vector.app.core.utils.PERMISSIONS_FOR_TAKING_PHOTO
|
|||
import im.vector.app.core.utils.TextUtils
|
||||
import im.vector.app.core.utils.checkPermissions
|
||||
import im.vector.app.core.utils.getSizeOfFiles
|
||||
import im.vector.app.core.utils.registerForPermissionsResult
|
||||
import im.vector.app.core.utils.toast
|
||||
import im.vector.app.features.MainActivity
|
||||
import im.vector.app.features.MainActivityArgs
|
||||
|
@ -390,13 +391,15 @@ class VectorSettingsGeneralFragment : VectorSettingsBaseFragment() {
|
|||
}.show()
|
||||
}
|
||||
|
||||
private fun onAvatarTypeSelected(isCamera: Boolean) {
|
||||
if (isCamera) {
|
||||
if (checkPermissions(PERMISSIONS_FOR_TAKING_PHOTO, this) { allGranted ->
|
||||
private val takePhotoActivityResultLauncher = registerForPermissionsResult { allGranted ->
|
||||
if (allGranted) {
|
||||
onAvatarTypeSelected(true)
|
||||
}
|
||||
}) {
|
||||
}
|
||||
|
||||
private fun onAvatarTypeSelected(isCamera: Boolean) {
|
||||
if (isCamera) {
|
||||
if (checkPermissions(PERMISSIONS_FOR_TAKING_PHOTO, requireActivity(), takePhotoActivityResultLauncher)) {
|
||||
avatarCameraUri = MultiPicker.get(MultiPicker.CAMERA).startWithExpectingFile(this)
|
||||
}
|
||||
} else {
|
||||
|
|
Loading…
Reference in New Issue