diff --git a/CHANGES.md b/CHANGES.md index 7067edbb1b..64d041a14c 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -7,6 +7,7 @@ Features ✨: Improvements 🙌: - Add "show password" in import Megolm keys dialog - Visually disable call buttons in menu and prohibit calling when permissions are insufficient (#2112) + - Better management of requested permissions (#2048) - Add a setting to show timestamp for all messages (#2123) - Use cache for user color - Allow using an outdated homeserver, at user's risk (#1972) 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 7bb060f075..aff26ae494 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 @@ -30,8 +30,6 @@ import androidx.fragment.app.Fragment import im.vector.app.R import timber.log.Timber -private const val LOG_TAG = "PermissionUtils" - // Android M permission request code management private const val PERMISSIONS_GRANTED = true private const val PERMISSIONS_DENIED = !PERMISSIONS_GRANTED @@ -42,16 +40,18 @@ 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 or PERMISSION_WRITE_EXTERNAL_STORAGE +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 const val PERMISSIONS_EMPTY = PERMISSION_BYPASSED @@ -67,7 +67,6 @@ 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_PREVIEW_FRAGMENT = 578 const val PERMISSION_REQUEST_CODE_READ_CONTACTS = 579 /** @@ -79,6 +78,7 @@ fun logPermissionStatuses(context: Context) { Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO, Manifest.permission.WRITE_EXTERNAL_STORAGE, + Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.READ_CONTACTS) Timber.v("## logPermissionStatuses() : log the permissions status used by the app") @@ -145,7 +145,7 @@ private fun checkPermissions(permissionsToBeGrantedBitMap: Int, fragment: Fragment?, requestCode: Int, @StringRes rationaleMessage: Int - ): Boolean { +): Boolean { var isPermissionGranted = false // sanity check @@ -161,7 +161,8 @@ private fun checkPermissions(permissionsToBeGrantedBitMap: Int, && PERMISSIONS_FOR_MEMBER_DETAILS != permissionsToBeGrantedBitMap && PERMISSIONS_FOR_ROOM_AVATAR != permissionsToBeGrantedBitMap && PERMISSIONS_FOR_VIDEO_RECORDING != permissionsToBeGrantedBitMap - && PERMISSIONS_FOR_WRITING_FILES != permissionsToBeGrantedBitMap) { + && PERMISSIONS_FOR_WRITING_FILES != permissionsToBeGrantedBitMap + && PERMISSIONS_FOR_READING_FILES != permissionsToBeGrantedBitMap) { Timber.w("## checkPermissions(): permissions to be granted are not supported") isPermissionGranted = false } else { @@ -188,6 +189,12 @@ private fun checkPermissions(permissionsToBeGrantedBitMap: Int, 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 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 1d6ea7339d..b9ccad9455 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 @@ -42,7 +42,6 @@ import im.vector.app.core.extensions.getMeasurements import im.vector.app.core.utils.PERMISSIONS_EMPTY import im.vector.app.core.utils.PERMISSIONS_FOR_PICKING_CONTACT import im.vector.app.core.utils.PERMISSIONS_FOR_TAKING_PHOTO -import im.vector.app.core.utils.PERMISSIONS_FOR_WRITING_FILES import im.vector.app.features.attachments.AttachmentTypeSelectorView.Callback import kotlin.math.max @@ -215,10 +214,10 @@ class AttachmentTypeSelectorView(context: Context, */ enum class Type(val permissionsBit: Int) { CAMERA(PERMISSIONS_FOR_TAKING_PHOTO), - GALLERY(PERMISSIONS_FOR_WRITING_FILES), - FILE(PERMISSIONS_FOR_WRITING_FILES), + GALLERY(PERMISSIONS_EMPTY), + FILE(PERMISSIONS_EMPTY), STICKER(PERMISSIONS_EMPTY), - AUDIO(PERMISSIONS_FOR_WRITING_FILES), + AUDIO(PERMISSIONS_EMPTY), CONTACT(PERMISSIONS_FOR_PICKING_CONTACT) } } diff --git a/vector/src/main/java/im/vector/app/features/attachments/preview/AttachmentsPreviewFragment.kt b/vector/src/main/java/im/vector/app/features/attachments/preview/AttachmentsPreviewFragment.kt index a822c49e9b..387cfb2261 100644 --- a/vector/src/main/java/im/vector/app/features/attachments/preview/AttachmentsPreviewFragment.kt +++ b/vector/src/main/java/im/vector/app/features/attachments/preview/AttachmentsPreviewFragment.kt @@ -42,17 +42,13 @@ import im.vector.app.core.extensions.cleanup import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.core.resources.ColorProvider import im.vector.app.core.utils.OnSnapPositionChangeListener -import im.vector.app.core.utils.PERMISSIONS_FOR_WRITING_FILES -import im.vector.app.core.utils.PERMISSION_REQUEST_CODE_PREVIEW_FRAGMENT import im.vector.app.core.utils.SnapOnScrollListener -import im.vector.app.core.utils.allGranted import im.vector.app.core.utils.attachSnapHelperWithListener -import im.vector.app.core.utils.checkPermissions import im.vector.app.features.media.createUCropWithDefaultSettings -import org.matrix.android.sdk.api.extensions.orFalse -import org.matrix.android.sdk.api.session.content.ContentAttachmentData import kotlinx.android.parcel.Parcelize import kotlinx.android.synthetic.main.fragment_attachments_preview.* +import org.matrix.android.sdk.api.extensions.orFalse +import org.matrix.android.sdk.api.session.content.ContentAttachmentData import timber.log.Timber import java.io.File import javax.inject.Inject @@ -102,7 +98,7 @@ class AttachmentsPreviewFragment @Inject constructor( handleRemoveAction() true } - R.id.attachmentsPreviewEditAction -> { + R.id.attachmentsPreviewEditAction -> { handleEditAction() true } @@ -183,22 +179,7 @@ class AttachmentsPreviewFragment @Inject constructor( viewModel.handle(AttachmentsPreviewAction.RemoveCurrentAttachment) } - private fun handleEditAction() { - // check permissions - if (checkPermissions(PERMISSIONS_FOR_WRITING_FILES, this, PERMISSION_REQUEST_CODE_PREVIEW_FRAGMENT)) { - doHandleEditAction() - } - } - - override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { - super.onRequestPermissionsResult(requestCode, permissions, grantResults) - - if (requestCode == PERMISSION_REQUEST_CODE_PREVIEW_FRAGMENT && allGranted(grantResults)) { - doHandleEditAction() - } - } - - private fun doHandleEditAction() = withState(viewModel) { + private fun handleEditAction() = withState(viewModel) { val currentAttachment = it.attachments.getOrNull(it.currentAttachmentIndex) ?: return@withState val destinationFile = File(requireContext().cacheDir, "${currentAttachment.name}_edited_image_${System.currentTimeMillis()}") val uri = currentAttachment.queryUri diff --git a/vector/src/main/java/im/vector/app/features/share/IncomingShareFragment.kt b/vector/src/main/java/im/vector/app/features/share/IncomingShareFragment.kt index b1fc96605e..a75cfa4304 100644 --- a/vector/src/main/java/im/vector/app/features/share/IncomingShareFragment.kt +++ b/vector/src/main/java/im/vector/app/features/share/IncomingShareFragment.kt @@ -28,23 +28,19 @@ import androidx.appcompat.widget.SearchView import androidx.core.view.isVisible import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState -import org.matrix.android.sdk.api.session.content.ContentAttachmentData -import org.matrix.android.sdk.api.session.room.model.RoomSummary import im.vector.app.R import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.configureWith import im.vector.app.core.extensions.exhaustive import im.vector.app.core.platform.VectorBaseFragment -import im.vector.app.core.utils.PERMISSIONS_FOR_WRITING_FILES -import im.vector.app.core.utils.PERMISSION_REQUEST_CODE_PICK_ATTACHMENT -import im.vector.app.core.utils.allGranted -import im.vector.app.core.utils.checkPermissions import im.vector.app.features.attachments.AttachmentsHelper import im.vector.app.features.attachments.preview.AttachmentsPreviewActivity import im.vector.app.features.attachments.preview.AttachmentsPreviewArgs import im.vector.app.features.login.LoginActivity import kotlinx.android.synthetic.main.fragment_incoming_share.* +import org.matrix.android.sdk.api.session.content.ContentAttachmentData +import org.matrix.android.sdk.api.session.room.model.RoomSummary import javax.inject.Inject /** @@ -76,7 +72,7 @@ class IncomingShareFragment @Inject constructor( val intent = vectorBaseActivity.intent val isShareManaged = when (intent?.action) { - Intent.ACTION_SEND -> { + Intent.ACTION_SEND -> { var isShareManaged = attachmentsHelper.handleShareIntent(requireContext(), intent) if (!isShareManaged) { isShareManaged = handleTextShare(intent) @@ -106,7 +102,7 @@ class IncomingShareFragment @Inject constructor( } viewModel.observeViewEvents { when (it) { - is IncomingShareViewEvents.ShareToRoom -> handleShareToRoom(it) + is IncomingShareViewEvents.ShareToRoom -> handleShareToRoom(it) is IncomingShareViewEvents.EditMediaBeforeSending -> handleEditMediaBeforeSending(it) is IncomingShareViewEvents.MultipleRoomsShareDone -> handleMultipleRoomsShareDone(it) }.exhaustive @@ -139,22 +135,6 @@ class IncomingShareFragment @Inject constructor( } } - override fun onResume() { - super.onResume() - - // We need the read file permission - checkPermissions(PERMISSIONS_FOR_WRITING_FILES, this, PERMISSION_REQUEST_CODE_PICK_ATTACHMENT) - } - - override fun onRequestPermissionsResult(requestCode: Int, permissions: Array, grantResults: IntArray) { - super.onRequestPermissionsResult(requestCode, permissions, grantResults) - - if (requestCode == PERMISSION_REQUEST_CODE_PICK_ATTACHMENT && !allGranted(grantResults)) { - // Permission is mandatory - cannotManageShare(R.string.missing_permissions_error) - } - } - private fun handleShareToRoom(event: IncomingShareViewEvents.ShareToRoom) { if (event.showAlert) { showConfirmationDialog(event.roomSummary, event.sharedData) diff --git a/vector/src/main/res/layout/item_verification_wait.xml b/vector/src/main/res/layout/item_verification_wait.xml index 639a3e112c..6cfc497b16 100644 --- a/vector/src/main/res/layout/item_verification_wait.xml +++ b/vector/src/main/res/layout/item_verification_wait.xml @@ -47,7 +47,7 @@ + app:constraint_referenced_ids="app_ios_android,app_desktop_web" />