From a7f034f50064741988f76e5b8ee8f4729d7373ec Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Wed, 7 Oct 2020 10:53:37 +0200 Subject: [PATCH] Stop using deprecated API to manage Permissions request from Fragment --- .../vector/app/core/utils/PermissionsTools.kt | 57 ++------ .../VerificationChooseMethodFragment.kt | 16 +-- .../home/room/detail/RoomDetailFragment.kt | 124 +++++++++--------- .../roomprofile/RoomProfileFragment.kt | 16 +-- .../settings/VectorSettingsGeneralFragment.kt | 16 +-- 5 files changed, 90 insertions(+), 139 deletions(-) diff --git a/vector/src/main/java/im/vector/app/core/utils/PermissionsTools.kt b/vector/src/main/java/im/vector/app/core/utils/PermissionsTools.kt index aff26ae494..3b83364f35 100644 --- a/vector/src/main/java/im/vector/app/core/utils/PermissionsTools.kt +++ b/vector/src/main/java/im/vector/app/core/utils/PermissionsTools.kt @@ -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.contract.ActivityResultContracts import androidx.annotation.StringRes import androidx.appcompat.app.AlertDialog import androidx.core.app.ActivityCompat @@ -105,7 +106,7 @@ fun checkPermissions(permissionsToBeGrantedBitMap: Int, activity: Activity, requestCode: Int, @StringRes rationaleMessage: Int = 0): Boolean { - return checkPermissions(permissionsToBeGrantedBitMap, activity, null, requestCode, rationaleMessage) + return checkPermissions(permissionsToBeGrantedBitMap, activity, null, null, requestCode, rationaleMessage) } /** @@ -117,9 +118,9 @@ fun checkPermissions(permissionsToBeGrantedBitMap: Int, */ fun checkPermissions(permissionsToBeGrantedBitMap: Int, fragment: Fragment, - requestCode: Int, - @StringRes rationaleMessage: Int = 0): Boolean { - return checkPermissions(permissionsToBeGrantedBitMap, fragment.activity, fragment, requestCode, rationaleMessage) + @StringRes rationaleMessage: Int = 0, + allGranted: (Boolean) -> Unit): Boolean { + return checkPermissions(permissionsToBeGrantedBitMap, fragment.activity, fragment, allGranted, 0, rationaleMessage) } /** @@ -143,6 +144,7 @@ fun checkPermissions(permissionsToBeGrantedBitMap: Int, private fun checkPermissions(permissionsToBeGrantedBitMap: Int, activity: Activity?, fragment: Fragment?, + allGranted: ((Boolean) -> Unit)?, requestCode: Int, @StringRes rationaleMessage: Int ): Boolean { @@ -222,7 +224,10 @@ 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?.requestPermissions(permissionsListToBeGranted.toTypedArray(), requestCode) + fragment?.registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { result -> + allGranted?.invoke(result.keys.all { result[it] == true }) + } + ?.launch(permissionsListToBeGranted.toTypedArray()) ?: run { ActivityCompat.requestPermissions(activity, permissionsListToBeGranted.toTypedArray(), requestCode) } @@ -262,7 +267,10 @@ private fun checkPermissions(permissionsToBeGrantedBitMap: Int, .show() */ } else { - fragment?.requestPermissions(permissionsArrayToBeGranted, requestCode) + fragment?.registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { result -> + allGranted?.invoke(result.keys.all { result[it] == true }) + } + ?.launch(permissionsArrayToBeGranted) ?: run { ActivityCompat.requestPermissions(activity, permissionsArrayToBeGranted, requestCode) } @@ -307,43 +315,6 @@ private fun updatePermissionsToBeGranted(activity: Activity, return isRequestPermissionRequested } -/** - * Helper method to process [.PERMISSIONS_FOR_AUDIO_IP_CALL] - * on onRequestPermissionsResult() methods. - * - * @param context App context - * @param grantResults permissions granted results - * @return true if audio IP call is permitted, false otherwise - */ -fun onPermissionResultAudioIpCall(context: Context, grantResults: IntArray): Boolean { - val arePermissionsGranted = allGranted(grantResults) - - if (!arePermissionsGranted) { - Toast.makeText(context, R.string.permissions_action_not_performed_missing_permissions, Toast.LENGTH_SHORT).show() - } - - return arePermissionsGranted -} - -/** - * Helper method to process [.PERMISSIONS_FOR_VIDEO_IP_CALL] - * on onRequestPermissionsResult() methods. - * For video IP calls, record audio and camera permissions are both mandatory. - * - * @param context App context - * @param grantResults permissions granted results - * @return true if video IP call is permitted, false otherwise - */ -fun onPermissionResultVideoIpCall(context: Context, grantResults: IntArray): Boolean { - val arePermissionsGranted = allGranted(grantResults) - - if (!arePermissionsGranted) { - Toast.makeText(context, R.string.permissions_action_not_performed_missing_permissions, Toast.LENGTH_SHORT).show() - } - - return arePermissionsGranted -} - /** * Return true if all permissions are granted, false if not or if permission request has been cancelled */ diff --git a/vector/src/main/java/im/vector/app/features/crypto/verification/choose/VerificationChooseMethodFragment.kt b/vector/src/main/java/im/vector/app/features/crypto/verification/choose/VerificationChooseMethodFragment.kt index fc715301f2..b176cc0815 100644 --- a/vector/src/main/java/im/vector/app/features/crypto/verification/choose/VerificationChooseMethodFragment.kt +++ b/vector/src/main/java/im/vector/app/features/crypto/verification/choose/VerificationChooseMethodFragment.kt @@ -27,8 +27,6 @@ import im.vector.app.core.extensions.cleanup 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.PERMISSION_REQUEST_CODE_LAUNCH_CAMERA -import im.vector.app.core.utils.allGranted import im.vector.app.core.utils.checkPermissions import im.vector.app.features.crypto.verification.VerificationAction import im.vector.app.features.crypto.verification.VerificationBottomSheetViewModel @@ -76,15 +74,11 @@ class VerificationChooseMethodFragment @Inject constructor( } override fun openCamera() { - if (checkPermissions(PERMISSIONS_FOR_TAKING_PHOTO, this, PERMISSION_REQUEST_CODE_LAUNCH_CAMERA)) { - doOpenQRCodeScanner() - } - } - - override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { - super.onRequestPermissionsResult(requestCode, permissions, grantResults) - - if (requestCode == PERMISSION_REQUEST_CODE_LAUNCH_CAMERA && allGranted(grantResults)) { + if (checkPermissions(PERMISSIONS_FOR_TAKING_PHOTO, this) { allGranted -> + if (allGranted) { + doOpenQRCodeScanner() + } + }) { doOpenQRCodeScanner() } } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt index 8694cf3978..6ee6212cf6 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/RoomDetailFragment.kt @@ -91,18 +91,13 @@ import im.vector.app.core.utils.KeyboardStateUtils import im.vector.app.core.utils.PERMISSIONS_FOR_AUDIO_IP_CALL import im.vector.app.core.utils.PERMISSIONS_FOR_VIDEO_IP_CALL import im.vector.app.core.utils.PERMISSIONS_FOR_WRITING_FILES -import im.vector.app.core.utils.PERMISSION_REQUEST_CODE_INCOMING_URI -import im.vector.app.core.utils.PERMISSION_REQUEST_CODE_PICK_ATTACHMENT import im.vector.app.core.utils.TextUtils -import im.vector.app.core.utils.allGranted import im.vector.app.core.utils.checkPermissions import im.vector.app.core.utils.colorizeMatchingText import im.vector.app.core.utils.copyToClipboard 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.onPermissionResultAudioIpCall -import im.vector.app.core.utils.onPermissionResultVideoIpCall import im.vector.app.core.utils.openUrlInExternalBrowser import im.vector.app.core.utils.saveMedia import im.vector.app.core.utils.shareMedia @@ -234,11 +229,6 @@ class RoomDetailFragment @Inject constructor( ActiveCallView.Callback { companion object { - - private const val AUDIO_CALL_PERMISSION_REQUEST_CODE = 1 - private const val VIDEO_CALL_PERMISSION_REQUEST_CODE = 2 - private const val SAVE_ATTACHEMENT_REQUEST_CODE = 3 - /** * Sanitize the display name. * @@ -797,15 +787,35 @@ class RoomDetailFragment @Inject constructor( roomDetailViewModel.pendingAction = startCallAction if (isVideoCall) { if (checkPermissions(PERMISSIONS_FOR_VIDEO_IP_CALL, - this, VIDEO_CALL_PERMISSION_REQUEST_CODE, - R.string.permissions_rationale_msg_camera_and_audio)) { + 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() + } + }) { roomDetailViewModel.pendingAction = null roomDetailViewModel.handle(startCallAction) } } else { if (checkPermissions(PERMISSIONS_FOR_AUDIO_IP_CALL, - this, AUDIO_CALL_PERMISSION_REQUEST_CODE, - R.string.permissions_rationale_msg_record_audio)) { + 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() + } + }) { roomDetailViewModel.pendingAction = null roomDetailViewModel.handle(startCallAction) } @@ -1027,7 +1037,17 @@ class RoomDetailFragment @Inject constructor( override fun onRichContentSelected(contentUri: Uri): Boolean { // We need WRITE_EXTERNAL permission - return if (checkPermissions(PERMISSIONS_FOR_WRITING_FILES, this@RoomDetailFragment, PERMISSION_REQUEST_CODE_INCOMING_URI)) { + 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() + } + }) { sendUri(contentUri) } else { roomDetailViewModel.pendingUri = contentUri @@ -1417,52 +1437,11 @@ class RoomDetailFragment @Inject constructor( // // } // } - override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { - if (allGranted(grantResults)) { - when (requestCode) { - SAVE_ATTACHEMENT_REQUEST_CODE -> { - sharedActionViewModel.pendingAction?.let { - handleActions(it) - sharedActionViewModel.pendingAction = null - } - } - PERMISSION_REQUEST_CODE_INCOMING_URI -> { - val pendingUri = roomDetailViewModel.pendingUri - if (pendingUri != null) { - roomDetailViewModel.pendingUri = null - sendUri(pendingUri) - } - } - PERMISSION_REQUEST_CODE_PICK_ATTACHMENT -> { - val pendingType = attachmentsHelper.pendingType - if (pendingType != null) { - attachmentsHelper.pendingType = null - launchAttachmentProcess(pendingType) - } - } - AUDIO_CALL_PERMISSION_REQUEST_CODE -> { - if (onPermissionResultAudioIpCall(requireContext(), grantResults)) { - (roomDetailViewModel.pendingAction as? RoomDetailAction.StartCall)?.let { - roomDetailViewModel.pendingAction = null - roomDetailViewModel.handle(it) - } - } - } - VIDEO_CALL_PERMISSION_REQUEST_CODE -> { - if (onPermissionResultVideoIpCall(requireContext(), grantResults)) { - (roomDetailViewModel.pendingAction as? RoomDetailAction.StartCall)?.let { - roomDetailViewModel.pendingAction = null - roomDetailViewModel.handle(it) - } - } - } - } - } else { - // Reset all pending data - roomDetailViewModel.pendingAction = null - roomDetailViewModel.pendingUri = null - attachmentsHelper.pendingType = null - } + private fun cleanUpAfterPermissionNotGranted() { + // Reset all pending data + roomDetailViewModel.pendingAction = null + roomDetailViewModel.pendingUri = null + attachmentsHelper.pendingType = null } // override fun onAudioMessageClicked(messageAudioContent: MessageAudioContent) { @@ -1579,7 +1558,16 @@ 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, SAVE_ATTACHEMENT_REQUEST_CODE)) { + && !checkPermissions(PERMISSIONS_FOR_WRITING_FILES, this) { allGranted -> + if (allGranted) { + sharedActionViewModel.pendingAction?.let { + handleActions(it) + sharedActionViewModel.pendingAction = null + } + } else { + cleanUpAfterPermissionNotGranted() + } + }) { sharedActionViewModel.pendingAction = action return } @@ -1818,7 +1806,17 @@ class RoomDetailFragment @Inject constructor( // AttachmentTypeSelectorView.Callback override fun onTypeSelected(type: AttachmentTypeSelectorView.Type) { - if (checkPermissions(type.permissionsBit, this, PERMISSION_REQUEST_CODE_PICK_ATTACHMENT)) { + if (checkPermissions(type.permissionsBit, this) { allGranted -> + if (allGranted) { + val pendingType = attachmentsHelper.pendingType + if (pendingType != null) { + attachmentsHelper.pendingType = null + launchAttachmentProcess(pendingType) + } + } else { + cleanUpAfterPermissionNotGranted() + } + }) { launchAttachmentProcess(type) } else { attachmentsHelper.pendingType = type diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileFragment.kt b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileFragment.kt index 477d557bea..f5c80b378f 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileFragment.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileFragment.kt @@ -46,8 +46,6 @@ import im.vector.app.core.extensions.setTextOrHide import im.vector.app.core.intent.getFilenameFromUri import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.core.utils.PERMISSIONS_FOR_TAKING_PHOTO -import im.vector.app.core.utils.PERMISSION_REQUEST_CODE_LAUNCH_CAMERA -import im.vector.app.core.utils.allGranted import im.vector.app.core.utils.checkPermissions import im.vector.app.core.utils.copyToClipboard import im.vector.app.core.utils.startSharePlainTextIntent @@ -288,7 +286,11 @@ class RoomProfileFragment @Inject constructor( private var avatarCameraUri: Uri? = null private fun onAvatarTypeSelected(isCamera: Boolean) { if (isCamera) { - if (checkPermissions(PERMISSIONS_FOR_TAKING_PHOTO, this, PERMISSION_REQUEST_CODE_LAUNCH_CAMERA)) { + if (checkPermissions(PERMISSIONS_FOR_TAKING_PHOTO, this) { allGranted -> + if (allGranted) { + onAvatarTypeSelected(true) + } + }) { avatarCameraUri = MultiPicker.get(MultiPicker.CAMERA).startWithExpectingFile(this) } } else { @@ -331,14 +333,6 @@ class RoomProfileFragment @Inject constructor( super.onActivityResult(requestCode, resultCode, data) } - override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { - if (allGranted(grantResults)) { - when (requestCode) { - PERMISSION_REQUEST_CODE_LAUNCH_CAMERA -> onAvatarTypeSelected(true) - } - } - } - private fun onAvatarCropped(uri: Uri?) { if (uri != null) { roomProfileViewModel.handle(RoomProfileAction.ChangeRoomAvatar(uri, getFilenameFromUri(context, uri))) diff --git a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsGeneralFragment.kt b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsGeneralFragment.kt index 6c0aefe9da..2f2c0d4c33 100644 --- a/vector/src/main/java/im/vector/app/features/settings/VectorSettingsGeneralFragment.kt +++ b/vector/src/main/java/im/vector/app/features/settings/VectorSettingsGeneralFragment.kt @@ -48,9 +48,7 @@ import im.vector.app.core.preference.UserAvatarPreference import im.vector.app.core.preference.VectorPreference import im.vector.app.core.preference.VectorSwitchPreference import im.vector.app.core.utils.PERMISSIONS_FOR_TAKING_PHOTO -import im.vector.app.core.utils.PERMISSION_REQUEST_CODE_LAUNCH_CAMERA import im.vector.app.core.utils.TextUtils -import im.vector.app.core.utils.allGranted import im.vector.app.core.utils.checkPermissions import im.vector.app.core.utils.getSizeOfFiles import im.vector.app.core.utils.toast @@ -279,14 +277,6 @@ class VectorSettingsGeneralFragment : VectorSettingsBaseFragment() { session.integrationManagerService().removeListener(integrationServiceListener) } - override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { - if (allGranted(grantResults)) { - if (requestCode == PERMISSION_REQUEST_CODE_LAUNCH_CAMERA) { - onAvatarTypeSelected(true) - } - } - } - override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) @@ -402,7 +392,11 @@ class VectorSettingsGeneralFragment : VectorSettingsBaseFragment() { private fun onAvatarTypeSelected(isCamera: Boolean) { if (isCamera) { - if (checkPermissions(PERMISSIONS_FOR_TAKING_PHOTO, this, PERMISSION_REQUEST_CODE_LAUNCH_CAMERA)) { + if (checkPermissions(PERMISSIONS_FOR_TAKING_PHOTO, this) { allGranted -> + if (allGranted) { + onAvatarTypeSelected(true) + } + }) { avatarCameraUri = MultiPicker.get(MultiPicker.CAMERA).startWithExpectingFile(this) } } else {