From cca9a8007c26a2a8893fb1bf91e93a945c608423 Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 12 Jul 2021 21:18:01 +0200 Subject: [PATCH 1/9] Use new permission request management I do not know why all has not been migrated in the previous rework --- .../app/features/debug/DebugMenuActivity.kt | 12 +- .../vector/app/core/utils/PermissionsTools.kt | 215 +++--------------- .../attachments/AttachmentTypeSelectorView.kt | 2 +- .../app/features/call/VectorCallActivity.kt | 13 +- .../createdirect/CreateDirectRoomActivity.kt | 37 ++- .../home/room/detail/RoomDetailFragment.kt | 2 +- .../invite/InviteUsersToRoomActivity.kt | 17 +- 7 files changed, 61 insertions(+), 237 deletions(-) diff --git a/vector/src/debug/java/im/vector/app/features/debug/DebugMenuActivity.kt b/vector/src/debug/java/im/vector/app/features/debug/DebugMenuActivity.kt index 539091c7ce..aa871c5fb5 100644 --- a/vector/src/debug/java/im/vector/app/features/debug/DebugMenuActivity.kt +++ b/vector/src/debug/java/im/vector/app/features/debug/DebugMenuActivity.kt @@ -30,9 +30,8 @@ import im.vector.app.core.di.ScreenComponent import im.vector.app.core.extensions.registerStartForActivityResult import im.vector.app.core.platform.VectorBaseActivity 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.registerForPermissionsResult import im.vector.app.core.utils.toast import im.vector.app.databinding.ActivityDebugMenuBinding import im.vector.app.features.debug.sas.DebugSasEmojiActivity @@ -48,7 +47,6 @@ import im.vector.lib.ui.styles.debug.DebugVectorButtonStylesLightActivity import im.vector.lib.ui.styles.debug.DebugVectorTextViewDarkActivity import im.vector.lib.ui.styles.debug.DebugVectorTextViewLightActivity import org.matrix.android.sdk.internal.crypto.verification.qrcode.toQrCodeData - import timber.log.Timber import javax.inject.Inject @@ -217,15 +215,13 @@ class DebugMenuActivity : VectorBaseActivity() { } private fun scanQRCode() { - if (checkPermissions(PERMISSIONS_FOR_TAKING_PHOTO, this, PERMISSION_REQUEST_CODE_LAUNCH_CAMERA)) { + if (checkPermissions(PERMISSIONS_FOR_TAKING_PHOTO, this, permissionCamera)) { doScanQRCode() } } - override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { - super.onRequestPermissionsResult(requestCode, permissions, grantResults) - - if (requestCode == PERMISSION_REQUEST_CODE_LAUNCH_CAMERA && allGranted(grantResults)) { + private val permissionCamera = registerForPermissionsResult { allGranted -> + if (allGranted) { doScanQRCode() } } 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 b6566b4ce9..879a53f0ae 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.ComponentActivity import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.contract.ActivityResultContracts import androidx.annotation.StringRes @@ -33,44 +34,16 @@ import im.vector.app.R import im.vector.app.core.platform.VectorBaseActivity import timber.log.Timber -// Android M permission request code management -private const val PERMISSIONS_GRANTED = true -private const val PERMISSIONS_DENIED = !PERMISSIONS_GRANTED - -// Permission bit -private const val PERMISSION_BYPASSED = 0x0 -const val PERMISSION_CAMERA = 0x1 -private const val PERMISSION_WRITE_EXTERNAL_STORAGE = 0x1 shl 1 -private const val PERMISSION_RECORD_AUDIO = 0x1 shl 2 -private const val PERMISSION_READ_CONTACTS = 0x1 shl 3 -private const val PERMISSION_READ_EXTERNAL_STORAGE = 0x1 shl 4 - // Permissions sets -const val PERMISSIONS_FOR_AUDIO_IP_CALL = PERMISSION_RECORD_AUDIO -const val PERMISSIONS_FOR_VIDEO_IP_CALL = PERMISSION_CAMERA or PERMISSION_RECORD_AUDIO -const val PERMISSIONS_FOR_TAKING_PHOTO = PERMISSION_CAMERA -const val PERMISSIONS_FOR_MEMBERS_SEARCH = PERMISSION_READ_CONTACTS -const val PERMISSIONS_FOR_MEMBER_DETAILS = PERMISSION_READ_CONTACTS -const val PERMISSIONS_FOR_ROOM_AVATAR = PERMISSION_CAMERA -const val PERMISSIONS_FOR_VIDEO_RECORDING = PERMISSION_CAMERA or PERMISSION_RECORD_AUDIO -const val PERMISSIONS_FOR_WRITING_FILES = PERMISSION_WRITE_EXTERNAL_STORAGE -const val PERMISSIONS_FOR_READING_FILES = PERMISSION_READ_EXTERNAL_STORAGE -const val PERMISSIONS_FOR_PICKING_CONTACT = PERMISSION_READ_CONTACTS +val PERMISSIONS_FOR_AUDIO_IP_CALL = listOf(Manifest.permission.RECORD_AUDIO) +val PERMISSIONS_FOR_VIDEO_IP_CALL = listOf(Manifest.permission.RECORD_AUDIO, Manifest.permission.CAMERA) +val PERMISSIONS_FOR_TAKING_PHOTO = listOf(Manifest.permission.CAMERA) +val PERMISSIONS_FOR_MEMBERS_SEARCH = listOf(Manifest.permission.READ_CONTACTS) +val PERMISSIONS_FOR_ROOM_AVATAR = listOf(Manifest.permission.CAMERA) +val PERMISSIONS_FOR_WRITING_FILES = listOf(Manifest.permission.WRITE_EXTERNAL_STORAGE) +val PERMISSIONS_FOR_PICKING_CONTACT = listOf(Manifest.permission.READ_CONTACTS) -const val PERMISSIONS_EMPTY = PERMISSION_BYPASSED - -// Request code to ask permission to the system (arbitrary values) -const val PERMISSION_REQUEST_CODE = 567 -const val PERMISSION_REQUEST_CODE_LAUNCH_CAMERA = 568 -const val PERMISSION_REQUEST_CODE_LAUNCH_NATIVE_CAMERA = 569 -const val PERMISSION_REQUEST_CODE_LAUNCH_NATIVE_VIDEO_CAMERA = 570 -const val PERMISSION_REQUEST_CODE_AUDIO_CALL = 571 -const val PERMISSION_REQUEST_CODE_VIDEO_CALL = 572 -const val PERMISSION_REQUEST_CODE_CHANGE_AVATAR = 574 -const val PERMISSION_REQUEST_CODE_DOWNLOAD_FILE = 575 -const val PERMISSION_REQUEST_CODE_PICK_ATTACHMENT = 576 -const val PERMISSION_REQUEST_CODE_INCOMING_URI = 577 -const val PERMISSION_REQUEST_CODE_READ_CONTACTS = 579 +val PERMISSIONS_EMPTY = emptyList() /** * Log the used permissions statuses. @@ -97,38 +70,16 @@ fun logPermissionStatuses(context: Context) { } } -fun Fragment.registerForPermissionsResult(allGranted: (Boolean) -> Unit): ActivityResultLauncher> { +fun ComponentActivity.registerForPermissionsResult(allGranted: (Boolean) -> Unit): ActivityResultLauncher> { return registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { result -> allGranted.invoke(result.keys.all { result[it] == true }) } } -/** - * See [.checkPermissions] - * - * @param permissionsToBeGrantedBitMap - * @param activity - * @return true if the permissions are granted (synchronous flow), false otherwise (asynchronous flow) - */ -fun checkPermissions(permissionsToBeGrantedBitMap: Int, - activity: Activity, - requestCode: Int, - @StringRes rationaleMessage: Int = 0): Boolean { - return checkPermissions(permissionsToBeGrantedBitMap, activity, null, requestCode, rationaleMessage) -} - -/** - * See [.checkPermissions] - * - * @param permissionsToBeGrantedBitMap - * @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, - activity: Activity, - activityResultLauncher: ActivityResultLauncher>, - @StringRes rationaleMessage: Int = 0): Boolean { - return checkPermissions(permissionsToBeGrantedBitMap, activity, activityResultLauncher, 0, rationaleMessage) +fun Fragment.registerForPermissionsResult(allGranted: (Boolean) -> Unit): ActivityResultLauncher> { + return registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { result -> + allGranted.invoke(result.keys.all { result[it] == true }) + } } /** @@ -144,78 +95,29 @@ fun checkPermissions(permissionsToBeGrantedBitMap: Int, * If a permission was already denied by the user, a popup is displayed to * explain why vector needs the corresponding permission. * - * @param permissionsToBeGrantedBitMap the permissions bit map to be granted - * @param activity the calling Activity that is requesting the permissions (or fragment parent) - * @param activityResultLauncher from the calling fragment that is requesting the permissions + * @param permissionsToBeGranted the permissions to be granted + * @param activity the calling Activity that is requesting the permissions (or fragment parent) + * @param activityResultLauncher from the calling fragment/Activity 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, - activityResultLauncher: ActivityResultLauncher>?, - requestCode: Int, - @StringRes rationaleMessage: Int -): Boolean { +fun checkPermissions(permissionsToBeGranted: List, + activity: Activity, + activityResultLauncher: ActivityResultLauncher>, + @StringRes rationaleMessage: Int = 0): Boolean { var isPermissionGranted = false // sanity check - if (PERMISSIONS_EMPTY == permissionsToBeGrantedBitMap) { + if (permissionsToBeGranted.isEmpty()) { isPermissionGranted = true - } else if (PERMISSIONS_FOR_AUDIO_IP_CALL != permissionsToBeGrantedBitMap - && PERMISSIONS_FOR_VIDEO_IP_CALL != permissionsToBeGrantedBitMap - && PERMISSIONS_FOR_TAKING_PHOTO != permissionsToBeGrantedBitMap - && PERMISSIONS_FOR_MEMBERS_SEARCH != permissionsToBeGrantedBitMap - && PERMISSIONS_FOR_MEMBER_DETAILS != permissionsToBeGrantedBitMap - && PERMISSIONS_FOR_ROOM_AVATAR != permissionsToBeGrantedBitMap - && PERMISSIONS_FOR_VIDEO_RECORDING != permissionsToBeGrantedBitMap - && PERMISSIONS_FOR_WRITING_FILES != permissionsToBeGrantedBitMap - && PERMISSIONS_FOR_READING_FILES != permissionsToBeGrantedBitMap) { - Timber.w("## checkPermissions(): permissions to be granted are not supported") - isPermissionGranted = false } else { - val permissionListAlreadyDenied = ArrayList() - val permissionsListToBeGranted = ArrayList() + val permissionListAlreadyDenied = mutableListOf() + val permissionsListToBeGranted = mutableListOf() var isRequestPermissionRequired = false - // retrieve the permissions to be granted according to the request code bit map - if (PERMISSION_CAMERA == permissionsToBeGrantedBitMap and PERMISSION_CAMERA) { - val permissionType = Manifest.permission.CAMERA - isRequestPermissionRequired = isRequestPermissionRequired or - updatePermissionsToBeGranted(activity, permissionListAlreadyDenied, permissionsListToBeGranted, permissionType) - } - - if (PERMISSION_RECORD_AUDIO == permissionsToBeGrantedBitMap and PERMISSION_RECORD_AUDIO) { - val permissionType = Manifest.permission.RECORD_AUDIO - isRequestPermissionRequired = isRequestPermissionRequired or - updatePermissionsToBeGranted(activity, permissionListAlreadyDenied, permissionsListToBeGranted, permissionType) - } - - if (PERMISSION_WRITE_EXTERNAL_STORAGE == permissionsToBeGrantedBitMap and PERMISSION_WRITE_EXTERNAL_STORAGE) { - val permissionType = Manifest.permission.WRITE_EXTERNAL_STORAGE - isRequestPermissionRequired = isRequestPermissionRequired or - updatePermissionsToBeGranted(activity, permissionListAlreadyDenied, permissionsListToBeGranted, permissionType) - } - - if (PERMISSION_READ_EXTERNAL_STORAGE == permissionsToBeGrantedBitMap and PERMISSION_READ_EXTERNAL_STORAGE) { - val permissionType = Manifest.permission.READ_EXTERNAL_STORAGE - isRequestPermissionRequired = isRequestPermissionRequired or - updatePermissionsToBeGranted(activity, permissionListAlreadyDenied, permissionsListToBeGranted, permissionType) - } - - // the contact book access is requested for any android platforms - // for android M, we use the system preferences - // for android < M, we use a dedicated settings - if (PERMISSION_READ_CONTACTS == permissionsToBeGrantedBitMap and PERMISSION_READ_CONTACTS) { - val permissionType = Manifest.permission.READ_CONTACTS - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - isRequestPermissionRequired = isRequestPermissionRequired or - updatePermissionsToBeGranted(activity, permissionListAlreadyDenied, permissionsListToBeGranted, permissionType) - } else { - // TODO uncomment - /*if (!ContactsManager.getInstance().isContactBookAccessRequested) { - isRequestPermissionRequired = true - permissionsListToBeGranted.add(permissionType) - }*/ + // retrieve the permissions to be granted according to the permission list + permissionsToBeGranted.forEach { permission -> + if (updatePermissionsToBeGranted(activity, permissionListAlreadyDenied, permissionsListToBeGranted, permission)) { + isRequestPermissionRequired = true } } @@ -228,53 +130,14 @@ 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()) { - activityResultLauncher - ?.launch(permissionsListToBeGranted.toTypedArray()) - ?: run { - ActivityCompat.requestPermissions(activity, permissionsListToBeGranted.toTypedArray(), requestCode) - } + activityResultLauncher.launch(permissionsListToBeGranted.toTypedArray()) } } .show() } else { // some permissions are not granted, ask permissions if (isRequestPermissionRequired) { - val permissionsArrayToBeGranted = permissionsListToBeGranted.toTypedArray() - - // for android < M, we use a custom dialog to request the contacts book access. - if (permissionsListToBeGranted.contains(Manifest.permission.READ_CONTACTS) - && Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { - TODO() - /* - MaterialAlertDialogBuilder(activity) - .setIcon(android.R.drawable.ic_dialog_info) - .setTitle(R.string.permissions_rationale_popup_title) - .setMessage(R.string.permissions_msg_contacts_warning_other_androids) - // gives the contacts book access - .setPositiveButton(R.string.yes) { _, _ -> - ContactsManager.getInstance().setIsContactBookAccessAllowed(true) - fragment?.requestPermissions(permissionsArrayToBeGranted, requestCode) - ?: run { - ActivityCompat.requestPermissions(activity, permissionsArrayToBeGranted, requestCode) - } - } - // or reject it - .setNegativeButton(R.string.no) { _, _ -> - ContactsManager.getInstance().setIsContactBookAccessAllowed(false) - fragment?.requestPermissions(permissionsArrayToBeGranted, requestCode) - ?: run { - ActivityCompat.requestPermissions(activity, permissionsArrayToBeGranted, requestCode) - } - } - .show() - */ - } else { - activityResultLauncher - ?.launch(permissionsArrayToBeGranted) - ?: run { - ActivityCompat.requestPermissions(activity, permissionsArrayToBeGranted, requestCode) - } - } + activityResultLauncher.launch(permissionsListToBeGranted.toTypedArray()) } else { // permissions were granted, start now. isPermissionGranted = true @@ -320,21 +183,3 @@ private fun updatePermissionsToBeGranted(activity: Activity, } return isRequestPermissionRequested } - -/** - * Return true if all permissions are granted, false if not or if permission request has been cancelled - */ -fun allGranted(grantResults: IntArray): Boolean { - if (grantResults.isEmpty()) { - // A cancellation occurred - return false - } - - var granted = true - - grantResults.forEach { - granted = granted && PackageManager.PERMISSION_GRANTED == it - } - - return granted -} diff --git a/vector/src/main/java/im/vector/app/features/attachments/AttachmentTypeSelectorView.kt b/vector/src/main/java/im/vector/app/features/attachments/AttachmentTypeSelectorView.kt index cf7270225d..c0d4669108 100644 --- a/vector/src/main/java/im/vector/app/features/attachments/AttachmentTypeSelectorView.kt +++ b/vector/src/main/java/im/vector/app/features/attachments/AttachmentTypeSelectorView.kt @@ -206,7 +206,7 @@ class AttachmentTypeSelectorView(context: Context, /** * The all possible types to pick with their required permissions. */ - enum class Type(val permissionsBit: Int) { + enum class Type(val permissions: List) { CAMERA(PERMISSIONS_FOR_TAKING_PHOTO), GALLERY(PERMISSIONS_EMPTY), FILE(PERMISSIONS_EMPTY), diff --git a/vector/src/main/java/im/vector/app/features/call/VectorCallActivity.kt b/vector/src/main/java/im/vector/app/features/call/VectorCallActivity.kt index 21939bd42b..cbe2733134 100644 --- a/vector/src/main/java/im/vector/app/features/call/VectorCallActivity.kt +++ b/vector/src/main/java/im/vector/app/features/call/VectorCallActivity.kt @@ -40,8 +40,8 @@ import im.vector.app.core.di.ScreenComponent import im.vector.app.core.platform.VectorBaseActivity 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.allGranted import im.vector.app.core.utils.checkPermissions +import im.vector.app.core.utils.registerForPermissionsResult import im.vector.app.databinding.ActivityCallBinding import im.vector.app.features.call.dialpad.CallDialPadBottomSheet import im.vector.app.features.call.dialpad.DialPadFragment @@ -139,11 +139,11 @@ class VectorCallActivity : VectorBaseActivity(), CallContro .disposeOnDestroy() if (callArgs.isVideoCall) { - if (checkPermissions(PERMISSIONS_FOR_VIDEO_IP_CALL, this, CAPTURE_PERMISSION_REQUEST_CODE, R.string.permissions_rationale_msg_camera_and_audio)) { + if (checkPermissions(PERMISSIONS_FOR_VIDEO_IP_CALL, this, permissionCameraLauncher, R.string.permissions_rationale_msg_camera_and_audio)) { start() } } else { - if (checkPermissions(PERMISSIONS_FOR_AUDIO_IP_CALL, this, CAPTURE_PERMISSION_REQUEST_CODE, R.string.permissions_rationale_msg_record_audio)) { + if (checkPermissions(PERMISSIONS_FOR_AUDIO_IP_CALL, this, permissionCameraLauncher, R.string.permissions_rationale_msg_record_audio)) { start() } } @@ -298,9 +298,8 @@ class VectorCallActivity : VectorBaseActivity(), CallContro } } - override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { - super.onRequestPermissionsResult(requestCode, permissions, grantResults) - if (requestCode == CAPTURE_PERMISSION_REQUEST_CODE && allGranted(grantResults)) { + private val permissionCameraLauncher = registerForPermissionsResult { allGranted -> + if (allGranted) { start() } else { // TODO display something @@ -370,8 +369,6 @@ class VectorCallActivity : VectorBaseActivity(), CallContro } companion object { - - private const val CAPTURE_PERMISSION_REQUEST_CODE = 1 private const val EXTRA_MODE = "EXTRA_MODE" private const val FRAGMENT_DIAL_PAD_TAG = "FRAGMENT_DIAL_PAD_TAG" diff --git a/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomActivity.kt b/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomActivity.kt index 4aa5f023c4..c2d323ff64 100644 --- a/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomActivity.kt +++ b/vector/src/main/java/im/vector/app/features/createdirect/CreateDirectRoomActivity.kt @@ -38,11 +38,9 @@ import im.vector.app.core.platform.SimpleFragmentActivity import im.vector.app.core.platform.WaitingViewData import im.vector.app.core.utils.PERMISSIONS_FOR_MEMBERS_SEARCH 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.PERMISSION_REQUEST_CODE_READ_CONTACTS -import im.vector.app.core.utils.allGranted import im.vector.app.core.utils.checkPermissions import im.vector.app.core.utils.onPermissionDeniedSnackbar +import im.vector.app.core.utils.registerForPermissionsResult import im.vector.app.features.contactsbook.ContactsBookFragment import im.vector.app.features.contactsbook.ContactsBookViewModel import im.vector.app.features.contactsbook.ContactsBookViewState @@ -52,7 +50,6 @@ import im.vector.app.features.userdirectory.UserListSharedAction import im.vector.app.features.userdirectory.UserListSharedActionViewModel import im.vector.app.features.userdirectory.UserListViewModel import im.vector.app.features.userdirectory.UserListViewState - import org.matrix.android.sdk.api.failure.Failure import org.matrix.android.sdk.api.session.room.failure.CreateRoomFailure import java.net.HttpURLConnection @@ -111,35 +108,31 @@ class CreateDirectRoomActivity : SimpleFragmentActivity(), UserListViewModel.Fac } private fun openAddByQrCode() { - if (checkPermissions(PERMISSIONS_FOR_TAKING_PHOTO, this, PERMISSION_REQUEST_CODE_LAUNCH_CAMERA, 0)) { + if (checkPermissions(PERMISSIONS_FOR_TAKING_PHOTO, this, permissionCameraLauncher, 0)) { addFragment(R.id.container, CreateDirectRoomByQrCodeFragment::class.java) } } private fun openPhoneBook() { // Check permission first - if (checkPermissions(PERMISSIONS_FOR_MEMBERS_SEARCH, - this, - PERMISSION_REQUEST_CODE_READ_CONTACTS, - 0)) { + if (checkPermissions(PERMISSIONS_FOR_MEMBERS_SEARCH, this, permissionReadContactLauncher, 0)) { addFragmentToBackstack(R.id.container, ContactsBookFragment::class.java) } } - override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { - super.onRequestPermissionsResult(requestCode, permissions, grantResults) - if (allGranted(grantResults)) { - if (requestCode == PERMISSION_REQUEST_CODE_READ_CONTACTS) { - doOnPostResume { addFragmentToBackstack(R.id.container, ContactsBookFragment::class.java) } - } else if (requestCode == PERMISSION_REQUEST_CODE_LAUNCH_CAMERA) { - addFragment(R.id.container, CreateDirectRoomByQrCodeFragment::class.java) - } + private val permissionReadContactLauncher = registerForPermissionsResult { allGranted -> + if (allGranted) { + doOnPostResume { addFragmentToBackstack(R.id.container, ContactsBookFragment::class.java) } } else { - if (requestCode == PERMISSION_REQUEST_CODE_LAUNCH_CAMERA) { - onPermissionDeniedSnackbar(R.string.permissions_denied_qr_code) - } else if (requestCode == PERMISSION_REQUEST_CODE_READ_CONTACTS) { - onPermissionDeniedSnackbar(R.string.permissions_denied_add_contact) - } + onPermissionDeniedSnackbar(R.string.permissions_denied_add_contact) + } + } + + private val permissionCameraLauncher = registerForPermissionsResult { allGranted -> + if (allGranted) { + addFragment(R.id.container, CreateDirectRoomByQrCodeFragment::class.java) + } else { + onPermissionDeniedSnackbar(R.string.permissions_denied_qr_code) } } 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 c4caff025b..f7fd4026b0 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 @@ -1990,7 +1990,7 @@ class RoomDetailFragment @Inject constructor( } override fun onTypeSelected(type: AttachmentTypeSelectorView.Type) { - if (checkPermissions(type.permissionsBit, requireActivity(), typeSelectedActivityResultLauncher)) { + if (checkPermissions(type.permissions, requireActivity(), typeSelectedActivityResultLauncher)) { launchAttachmentProcess(type) } else { attachmentsHelper.pendingType = type diff --git a/vector/src/main/java/im/vector/app/features/invite/InviteUsersToRoomActivity.kt b/vector/src/main/java/im/vector/app/features/invite/InviteUsersToRoomActivity.kt index 142498e031..0f3e3c57d2 100644 --- a/vector/src/main/java/im/vector/app/features/invite/InviteUsersToRoomActivity.kt +++ b/vector/src/main/java/im/vector/app/features/invite/InviteUsersToRoomActivity.kt @@ -33,9 +33,8 @@ import im.vector.app.core.extensions.addFragmentToBackstack import im.vector.app.core.platform.SimpleFragmentActivity import im.vector.app.core.platform.WaitingViewData import im.vector.app.core.utils.PERMISSIONS_FOR_MEMBERS_SEARCH -import im.vector.app.core.utils.PERMISSION_REQUEST_CODE_READ_CONTACTS -import im.vector.app.core.utils.allGranted import im.vector.app.core.utils.checkPermissions +import im.vector.app.core.utils.registerForPermissionsResult import im.vector.app.core.utils.toast import im.vector.app.features.contactsbook.ContactsBookFragment import im.vector.app.features.contactsbook.ContactsBookViewModel @@ -118,20 +117,14 @@ class InviteUsersToRoomActivity : SimpleFragmentActivity(), UserListViewModel.Fa private fun openPhoneBook() { // Check permission first - if (checkPermissions(PERMISSIONS_FOR_MEMBERS_SEARCH, - this, - PERMISSION_REQUEST_CODE_READ_CONTACTS, - 0)) { + if (checkPermissions(PERMISSIONS_FOR_MEMBERS_SEARCH, this, permissionContactLauncher)) { addFragmentToBackstack(R.id.container, ContactsBookFragment::class.java) } } - override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { - super.onRequestPermissionsResult(requestCode, permissions, grantResults) - if (allGranted(grantResults)) { - if (requestCode == PERMISSION_REQUEST_CODE_READ_CONTACTS) { - doOnPostResume { addFragmentToBackstack(R.id.container, ContactsBookFragment::class.java) } - } + private val permissionContactLauncher = registerForPermissionsResult { allGranted -> + if (allGranted) { + doOnPostResume { addFragmentToBackstack(R.id.container, ContactsBookFragment::class.java) } } else { Toast.makeText(baseContext, R.string.missing_permissions_error, Toast.LENGTH_SHORT).show() } From fabbd6da9e4597acdd80b1d4bb94bb84e42afcdf Mon Sep 17 00:00:00 2001 From: Benoit Marty Date: Mon, 12 Jul 2021 21:33:15 +0200 Subject: [PATCH 2/9] Add action to see permission status in the DebugActivity --- vector/src/debug/AndroidManifest.xml | 1 + .../app/features/debug/DebugMenuActivity.kt | 8 ++ .../features/debug/DebugPermissionActivity.kt | 91 +++++++++++++++++++ .../debug/res/layout/activity_debug_menu.xml | 6 ++ .../res/layout/activity_debug_permission.xml | 68 ++++++++++++++ vector/src/debug/res/values/strings.xml | 4 + .../vector/app/core/utils/PermissionsTools.kt | 32 ++----- 7 files changed, 185 insertions(+), 25 deletions(-) create mode 100644 vector/src/debug/java/im/vector/app/features/debug/DebugPermissionActivity.kt create mode 100644 vector/src/debug/res/layout/activity_debug_permission.xml create mode 100644 vector/src/debug/res/values/strings.xml diff --git a/vector/src/debug/AndroidManifest.xml b/vector/src/debug/AndroidManifest.xml index b97384099f..8ffcec6bc1 100644 --- a/vector/src/debug/AndroidManifest.xml +++ b/vector/src/debug/AndroidManifest.xml @@ -4,6 +4,7 @@ + diff --git a/vector/src/debug/java/im/vector/app/features/debug/DebugMenuActivity.kt b/vector/src/debug/java/im/vector/app/features/debug/DebugMenuActivity.kt index aa871c5fb5..5d94f312b2 100644 --- a/vector/src/debug/java/im/vector/app/features/debug/DebugMenuActivity.kt +++ b/vector/src/debug/java/im/vector/app/features/debug/DebugMenuActivity.kt @@ -20,15 +20,20 @@ import android.app.Activity import android.app.NotificationChannel import android.app.NotificationManager import android.content.Intent +import android.content.pm.PackageManager import android.os.Build +import androidx.core.app.ActivityCompat import androidx.core.app.NotificationCompat import androidx.core.app.Person +import androidx.core.content.ContextCompat import androidx.core.content.getSystemService +import com.google.android.material.dialog.MaterialAlertDialogBuilder import im.vector.app.R import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.di.ScreenComponent import im.vector.app.core.extensions.registerStartForActivityResult import im.vector.app.core.platform.VectorBaseActivity +import im.vector.app.core.utils.PERMISSIONS_ALL import im.vector.app.core.utils.PERMISSIONS_FOR_TAKING_PHOTO import im.vector.app.core.utils.checkPermissions import im.vector.app.core.utils.registerForPermissionsResult @@ -113,6 +118,9 @@ class DebugMenuActivity : VectorBaseActivity() { } views.debugTestCrash.setOnClickListener { testCrash() } views.debugScanQrCode.setOnClickListener { scanQRCode() } + views.debugPermission.setOnClickListener { + startActivity(Intent(this, DebugPermissionActivity::class.java)) + } } private fun renderQrCode(text: String) { diff --git a/vector/src/debug/java/im/vector/app/features/debug/DebugPermissionActivity.kt b/vector/src/debug/java/im/vector/app/features/debug/DebugPermissionActivity.kt new file mode 100644 index 0000000000..660e6c4312 --- /dev/null +++ b/vector/src/debug/java/im/vector/app/features/debug/DebugPermissionActivity.kt @@ -0,0 +1,91 @@ +/* + * Copyright 2019 New Vector Ltd + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package im.vector.app.features.debug + +import android.content.pm.PackageManager +import android.os.Build +import android.widget.Toast +import androidx.core.app.ActivityCompat +import androidx.core.content.ContextCompat +import im.vector.app.R +import im.vector.app.core.platform.VectorBaseActivity +import im.vector.app.core.utils.PERMISSIONS_ALL +import im.vector.app.core.utils.checkPermissions +import im.vector.app.core.utils.registerForPermissionsResult +import im.vector.app.databinding.ActivityDebugPermissionBinding +import timber.log.Timber + +class DebugPermissionActivity : VectorBaseActivity() { + + override fun getBinding() = ActivityDebugPermissionBinding.inflate(layoutInflater) + + override fun initUiAndData() { + views.status.setOnClickListener { refresh() } + + listOf( + views.audio, + views.camera, + views.write, + views.read, + views.contact + ).forEach { button -> + button.setOnClickListener { + checkPermissions(listOf(button.text.toString()), this, launcher, R.string.debug_rationale) + } + } + } + + private val launcher = registerForPermissionsResult { allGranted -> + if (allGranted) { + Toast.makeText(this, "All granted", Toast.LENGTH_SHORT).show() + } else { + Toast.makeText(this, "Denied", Toast.LENGTH_SHORT).show() + } + } + + override fun onResume() { + super.onResume() + refresh() + } + + private fun refresh() { + views.status.text = getStatus() + } + + private fun getStatus(): String { + return buildString { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + Timber.v("## debugPermission() : log the permissions status used by the app") + PERMISSIONS_ALL.forEach { permission -> + append("[$permission] : ") + if (PackageManager.PERMISSION_GRANTED == ContextCompat.checkSelfPermission(this@DebugPermissionActivity, permission)) { + append("PERMISSION_GRANTED") + } else { + append("PERMISSION_DENIED") + } + append(" show rational: ") + append(ActivityCompat.shouldShowRequestPermissionRationale(this@DebugPermissionActivity, permission)) + append("\n") + } + } else { + append("Before M!") + } + append("\n") + append("(Click to refresh)") + } + } +} diff --git a/vector/src/debug/res/layout/activity_debug_menu.xml b/vector/src/debug/res/layout/activity_debug_menu.xml index a83f61266a..976fe625e5 100644 --- a/vector/src/debug/res/layout/activity_debug_menu.xml +++ b/vector/src/debug/res/layout/activity_debug_menu.xml @@ -152,6 +152,12 @@ android:layout_height="200dp" tools:src="@drawable/ic_qr_code_add" /> +