Permissions: allow to provide the rationale message as it requires "context" and cannot be generic

This commit is contained in:
ganfra 2019-10-22 17:13:38 +02:00
parent c7a4d34192
commit 7388a408b8
6 changed files with 24 additions and 60 deletions

View File

@ -21,8 +21,8 @@ import android.app.Activity
import android.content.Context import android.content.Context
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.os.Build import android.os.Build
import android.text.TextUtils
import android.widget.Toast import android.widget.Toast
import androidx.annotation.StringRes
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.core.app.ActivityCompat import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
@ -102,8 +102,9 @@ fun logPermissionStatuses(context: Context) {
*/ */
fun checkPermissions(permissionsToBeGrantedBitMap: Int, fun checkPermissions(permissionsToBeGrantedBitMap: Int,
activity: Activity, activity: Activity,
requestCode: Int = PERMISSION_REQUEST_CODE): Boolean { requestCode: Int,
return checkPermissions(permissionsToBeGrantedBitMap, activity, null, requestCode) @StringRes rationaleMessage: Int = 0): Boolean {
return checkPermissions(permissionsToBeGrantedBitMap, activity, null, requestCode, rationaleMessage)
} }
/** /**
@ -115,8 +116,9 @@ fun checkPermissions(permissionsToBeGrantedBitMap: Int,
*/ */
fun checkPermissions(permissionsToBeGrantedBitMap: Int, fun checkPermissions(permissionsToBeGrantedBitMap: Int,
fragment: Fragment, fragment: Fragment,
requestCode: Int = PERMISSION_REQUEST_CODE): Boolean { requestCode: Int,
return checkPermissions(permissionsToBeGrantedBitMap, fragment.activity, fragment, requestCode) @StringRes rationaleMessage: Int = 0): Boolean {
return checkPermissions(permissionsToBeGrantedBitMap, fragment.activity, fragment, requestCode, rationaleMessage)
} }
/** /**
@ -140,7 +142,9 @@ fun checkPermissions(permissionsToBeGrantedBitMap: Int,
private fun checkPermissions(permissionsToBeGrantedBitMap: Int, private fun checkPermissions(permissionsToBeGrantedBitMap: Int,
activity: Activity?, activity: Activity?,
fragment: Fragment?, fragment: Fragment?,
requestCode: Int): Boolean { requestCode: Int,
@StringRes rationaleMessage: Int
): Boolean {
var isPermissionGranted = false var isPermissionGranted = false
// sanity check // sanity check
@ -163,7 +167,6 @@ private fun checkPermissions(permissionsToBeGrantedBitMap: Int,
val permissionListAlreadyDenied = ArrayList<String>() val permissionListAlreadyDenied = ArrayList<String>()
val permissionsListToBeGranted = ArrayList<String>() val permissionsListToBeGranted = ArrayList<String>()
var isRequestPermissionRequired = false var isRequestPermissionRequired = false
var explanationMessage = ""
// retrieve the permissions to be granted according to the request code bit map // retrieve the permissions to be granted according to the request code bit map
if (PERMISSION_CAMERA == permissionsToBeGrantedBitMap and PERMISSION_CAMERA) { if (PERMISSION_CAMERA == permissionsToBeGrantedBitMap and PERMISSION_CAMERA) {
@ -203,58 +206,11 @@ private fun checkPermissions(permissionsToBeGrantedBitMap: Int,
} }
// if some permissions were already denied: display a dialog to the user before asking again. // if some permissions were already denied: display a dialog to the user before asking again.
if (!permissionListAlreadyDenied.isEmpty()) { if (permissionListAlreadyDenied.isNotEmpty() && rationaleMessage != 0) {
if (permissionsToBeGrantedBitMap == PERMISSIONS_FOR_VIDEO_IP_CALL || permissionsToBeGrantedBitMap == PERMISSIONS_FOR_AUDIO_IP_CALL) {
// Permission request for VOIP call
if (permissionListAlreadyDenied.contains(Manifest.permission.CAMERA)
&& permissionListAlreadyDenied.contains(Manifest.permission.RECORD_AUDIO)) {
// Both missing
explanationMessage += activity.getString(R.string.permissions_rationale_msg_camera_and_audio)
} else if (permissionListAlreadyDenied.contains(Manifest.permission.RECORD_AUDIO)) {
// Audio missing
explanationMessage += activity.getString(R.string.permissions_rationale_msg_record_audio)
explanationMessage += activity.getString(R.string.permissions_rationale_msg_record_audio_explanation)
} else if (permissionListAlreadyDenied.contains(Manifest.permission.CAMERA)) {
// Camera missing
explanationMessage += activity.getString(R.string.permissions_rationale_msg_camera)
explanationMessage += activity.getString(R.string.permissions_rationale_msg_camera_explanation)
}
} else {
permissionListAlreadyDenied.forEach {
when (it) {
Manifest.permission.CAMERA -> {
if (!TextUtils.isEmpty(explanationMessage)) {
explanationMessage += "\n\n"
}
explanationMessage += activity.getString(R.string.permissions_rationale_msg_camera)
}
Manifest.permission.RECORD_AUDIO -> {
if (!TextUtils.isEmpty(explanationMessage)) {
explanationMessage += "\n\n"
}
explanationMessage += activity.getString(R.string.permissions_rationale_msg_record_audio)
}
Manifest.permission.WRITE_EXTERNAL_STORAGE -> {
if (!TextUtils.isEmpty(explanationMessage)) {
explanationMessage += "\n\n"
}
explanationMessage += activity.getString(R.string.permissions_rationale_msg_storage)
}
Manifest.permission.READ_CONTACTS -> {
if (!TextUtils.isEmpty(explanationMessage)) {
explanationMessage += "\n\n"
}
explanationMessage += activity.getString(R.string.permissions_rationale_msg_contacts)
}
else -> Timber.v("## checkPermissions(): already denied permission not supported")
}
}
}
// display the dialog with the info text // display the dialog with the info text
AlertDialog.Builder(activity) AlertDialog.Builder(activity)
.setTitle(R.string.permissions_rationale_popup_title) .setTitle(R.string.permissions_rationale_popup_title)
.setMessage(explanationMessage) .setMessage(rationaleMessage)
.setOnCancelListener { Toast.makeText(activity, R.string.missing_permissions_warning, Toast.LENGTH_SHORT).show() } .setOnCancelListener { Toast.makeText(activity, R.string.missing_permissions_warning, Toast.LENGTH_SHORT).show() }
.setPositiveButton(R.string.ok) { _, _ -> .setPositiveButton(R.string.ok) { _, _ ->
if (!permissionsListToBeGranted.isEmpty()) { if (!permissionsListToBeGranted.isEmpty()) {

View File

@ -130,7 +130,7 @@ class KeysBackupSetupActivity : SimpleFragmentActivity() {
} }
private fun exportKeysManually() { private fun exportKeysManually() {
if (checkPermissions(PERMISSIONS_FOR_WRITING_FILES, this, PERMISSION_REQUEST_CODE_EXPORT_KEYS)) { if (checkPermissions(PERMISSIONS_FOR_WRITING_FILES, this, PERMISSION_REQUEST_CODE_EXPORT_KEYS, R.string.permissions_rationale_msg_keys_backup_export)) {
ExportKeysDialog().show(this, object : ExportKeysDialog.ExportKeyDialogListener { ExportKeysDialog().show(this, object : ExportKeysDialog.ExportKeyDialogListener {
override fun onPassphrase(passphrase: String) { override fun onPassphrase(passphrase: String) {
showWaitingView() showWaitingView()

View File

@ -135,7 +135,13 @@ class KeysBackupSetupStep3Fragment : VectorBaseFragment() {
} }
dialog.findViewById<View>(R.id.keys_backup_setup_save)?.setOnClickListener { dialog.findViewById<View>(R.id.keys_backup_setup_save)?.setOnClickListener {
if (checkPermissions(PERMISSIONS_FOR_WRITING_FILES, this, PERMISSION_REQUEST_CODE_EXPORT_KEYS)) { val permissionsChecked = checkPermissions(
PERMISSIONS_FOR_WRITING_FILES,
this,
PERMISSION_REQUEST_CODE_EXPORT_KEYS,
R.string.permissions_rationale_msg_keys_backup_export
)
if (permissionsChecked) {
exportRecoveryKeyToFile(recoveryKey) exportRecoveryKeyToFile(recoveryKey)
} }
dialog.dismiss() dialog.dismiss()

View File

@ -52,7 +52,6 @@ class ComposerEditText @JvmOverloads constructor(context: Context, attrs: Attrib
} }
} }
callback?.onRichContentSelected(inputContentInfo.contentUri) ?: false callback?.onRichContentSelected(inputContentInfo.contentUri) ?: false
} }
return InputConnectionCompat.createWrapper(ic, editorInfo, callback) return InputConnectionCompat.createWrapper(ic, editorInfo, callback)
} }

View File

@ -212,7 +212,7 @@ class VectorSettingsSecurityPrivacyFragment : VectorSettingsBaseFragment() {
*/ */
private fun exportKeys() { private fun exportKeys() {
// We need WRITE_EXTERNAL permission // We need WRITE_EXTERNAL permission
if (checkPermissions(PERMISSIONS_FOR_WRITING_FILES, this, PERMISSION_REQUEST_CODE_EXPORT_KEYS)) { if (checkPermissions(PERMISSIONS_FOR_WRITING_FILES, this, PERMISSION_REQUEST_CODE_EXPORT_KEYS, R.string.permissions_rationale_msg_keys_backup_export)) {
activity?.let { activity -> activity?.let { activity ->
ExportKeysDialog().show(activity, object : ExportKeysDialog.ExportKeyDialogListener { ExportKeysDialog().show(activity, object : ExportKeysDialog.ExportKeyDialogListener {
override fun onPassphrase(passphrase: String) { override fun onPassphrase(passphrase: String) {

View File

@ -368,6 +368,9 @@
<string name="permissions_rationale_msg_camera_and_audio">Riot needs permission to access your camera and your microphone to perform video calls.\n\nPlease allow access on the next pop-ups to be able to make the call.</string> <string name="permissions_rationale_msg_camera_and_audio">Riot needs permission to access your camera and your microphone to perform video calls.\n\nPlease allow access on the next pop-ups to be able to make the call.</string>
<string name="permissions_rationale_msg_contacts">Riot can check your address book to find other Matrix users based on their email and phone numbers. If you agree to share your address book for this purpose, please allow access on the next pop-up.</string> <string name="permissions_rationale_msg_contacts">Riot can check your address book to find other Matrix users based on their email and phone numbers. If you agree to share your address book for this purpose, please allow access on the next pop-up.</string>
<string name="permissions_msg_contacts_warning_other_androids">Riot can check your address book to find other Matrix users based on their email and phone numbers.\n\nDo you agree to share your address book for this purpose?</string> <string name="permissions_msg_contacts_warning_other_androids">Riot can check your address book to find other Matrix users based on their email and phone numbers.\n\nDo you agree to share your address book for this purpose?</string>
<string name="permissions_rationale_msg_keys_backup_export">Riot needs permission to save your E2E keys on disk.\n\nPlease allow access on the next pop-up to be able to export your keys manually.</string>
<string name="permissions_action_not_performed_missing_permissions">Sorry. Action not performed, due to missing permissions</string> <string name="permissions_action_not_performed_missing_permissions">Sorry. Action not performed, due to missing permissions</string>