Skip to content

Commit

Permalink
feat: Remove nearby devices permission for calling (WPB-4583) (#2508)
Browse files Browse the repository at this point in the history
  • Loading branch information
ohassine authored Dec 11, 2023
1 parent d75f286 commit 43d336e
Show file tree
Hide file tree
Showing 48 changed files with 136 additions and 149 deletions.
2 changes: 0 additions & 2 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,7 @@

<!-- needed to switch between speaker/earpiece -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_PHONE_CALL" />
<uses-permission android:name="android.permission.MANAGE_OWN_CALLS" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,14 @@ import com.wire.android.ui.common.button.WireButtonState
import com.wire.android.util.ui.PreviewMultipleThemes

@Composable
fun MicrophoneBTPermissionsDeniedDialog(
fun MicrophonePermissionDeniedDialog(
shouldShow: Boolean,
onDismiss: () -> Unit,
onOpenSettings: () -> Unit
) {
if (shouldShow) {
WireDialog(
title = stringResource(id = R.string.permission_dialog_title),
title = stringResource(id = R.string.call_permission_dialog_title),
text = stringResource(id = R.string.call_permission_dialog_description),
onDismiss = onDismiss,
dismissButtonProperties = WireDialogButtonProperties(
Expand All @@ -53,8 +53,8 @@ fun MicrophoneBTPermissionsDeniedDialog(
}
@PreviewMultipleThemes
@Composable
fun PreviewMicrophoneBTPermissionsDeniedDialog() {
MicrophoneBTPermissionsDeniedDialog(
fun PreviewMicrophonePermissionDeniedDialog() {
MicrophonePermissionDeniedDialog(
shouldShow = true,
onDismiss = {},
onOpenSettings = {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import com.wire.android.ui.common.button.WirePrimaryButton
import com.wire.android.ui.common.dimensions
import com.wire.android.ui.theme.wireDimensions
import com.wire.android.ui.theme.wireTypography
import com.wire.android.util.permission.rememberCallingRecordAudioBluetoothRequestFlow
import com.wire.android.util.permission.rememberCallingRecordAudioRequestFlow

@Composable
fun JoinButton(
Expand All @@ -47,13 +47,13 @@ fun JoinButton(
minClickableSize: DpSize = MaterialTheme.wireDimensions.buttonMinClickableSize,
horizontalPadding: Dp = MaterialTheme.wireDimensions.spacing8x,
) {
val audioBTPermissionCheck = AudioBluetoothPermissionCheckFlow(
val audioPermissionCheck = AudioPermissionCheckFlow(
onJoinCall = buttonClick,
onPermanentPermissionDecline = onPermanentPermissionDecline
)

WirePrimaryButton(
onClick = audioBTPermissionCheck::launch,
onClick = audioPermissionCheck::launch,
fillMaxWidth = false,
shape = RoundedCornerShape(size = MaterialTheme.wireDimensions.corner12x),
text = stringResource(R.string.calling_button_label_join_call),
Expand All @@ -72,16 +72,16 @@ fun JoinButton(
}

@Composable
private fun AudioBluetoothPermissionCheckFlow(
private fun AudioPermissionCheckFlow(
onJoinCall: () -> Unit,
onPermanentPermissionDecline: () -> Unit
) = rememberCallingRecordAudioBluetoothRequestFlow(
onAudioBluetoothPermissionGranted = {
appLogger.d("IncomingCall - Permissions granted")
) = rememberCallingRecordAudioRequestFlow(
onAudioPermissionGranted = {
appLogger.d("IncomingCall - Audio permission granted")
onJoinCall()
},
onAudioBluetoothPermissionDenied = { },
onAudioBluetoothPermissionPermanentlyDenied = onPermanentPermissionDecline
onAudioPermissionDenied = { },
onAudioPermissionPermanentlyDenied = onPermanentPermissionDecline
)

@Preview
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import com.wire.android.ui.common.button.WireButtonState
import com.wire.android.ui.common.button.WireSecondaryButton
import com.wire.android.ui.common.dimensions
import com.wire.android.ui.theme.wireDimensions
import com.wire.android.util.permission.rememberCallingRecordAudioBluetoothRequestFlow
import com.wire.android.util.permission.rememberCallingRecordAudioRequestFlow
import com.wire.android.util.ui.PreviewMultipleThemes

@Composable
Expand All @@ -42,13 +42,13 @@ fun StartCallButton(
onPermanentPermissionDecline: () -> Unit,
isCallingEnabled: Boolean
) {
val audioBTPermissionCheck = AudioBluetoothPermissionCheckFlow(
val audioPermissionCheck = AudioPermissionCheckFlow(
startCall = onPhoneButtonClick,
onPermanentPermissionDecline = onPermanentPermissionDecline
)

WireSecondaryButton(
onClick = audioBTPermissionCheck::launch,
onClick = audioPermissionCheck::launch,
leadingIcon = {
Icon(
painter = painterResource(id = R.drawable.ic_phone),
Expand All @@ -58,24 +58,27 @@ fun StartCallButton(
state = if (isCallingEnabled) WireButtonState.Default else WireButtonState.Disabled,
fillMaxWidth = false,
minSize = dimensions().buttonSmallMinSize,
minClickableSize = DpSize(dimensions().buttonSmallMinSize.width, dimensions().buttonMinClickableSize.height),
minClickableSize = DpSize(
dimensions().buttonSmallMinSize.width,
dimensions().buttonMinClickableSize.height
),
clickBlockParams = ClickBlockParams(blockWhenSyncing = true, blockWhenConnecting = true),
shape = RoundedCornerShape(size = MaterialTheme.wireDimensions.corner12x),
contentPadding = PaddingValues(0.dp)
)
}

@Composable
private fun AudioBluetoothPermissionCheckFlow(
private fun AudioPermissionCheckFlow(
startCall: () -> Unit,
onPermanentPermissionDecline: () -> Unit
) = rememberCallingRecordAudioBluetoothRequestFlow(
onAudioBluetoothPermissionGranted = {
appLogger.d("startCall - Permissions granted")
) = rememberCallingRecordAudioRequestFlow(
onAudioPermissionGranted = {
appLogger.d("startCall - Audio permission granted")
startCall()
},
onAudioBluetoothPermissionDenied = { },
onAudioBluetoothPermissionPermanentlyDenied = onPermanentPermissionDecline
onAudioPermissionDenied = { },
onAudioPermissionPermanentlyDenied = onPermanentPermissionDecline
)

@PreviewMultipleThemes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ import com.wire.android.ui.calling.CallingNavArgs
import com.wire.android.ui.calling.SharedCallingViewModel
import com.wire.android.ui.calling.common.CallVideoPreview
import com.wire.android.ui.calling.common.CallerDetails
import com.wire.android.ui.calling.common.MicrophoneBTPermissionsDeniedDialog
import com.wire.android.ui.calling.common.MicrophonePermissionDeniedDialog
import com.wire.android.ui.calling.controlbuttons.AcceptButton
import com.wire.android.ui.calling.controlbuttons.CallOptionsControls
import com.wire.android.ui.calling.controlbuttons.HangUpButton
Expand All @@ -63,7 +63,7 @@ import com.wire.android.ui.common.dimensions
import com.wire.android.ui.destinations.OngoingCallScreenDestination
import com.wire.android.ui.theme.wireTypography
import com.wire.android.util.extension.openAppInfoScreen
import com.wire.android.util.permission.rememberCallingRecordAudioBluetoothRequestFlow
import com.wire.android.util.permission.rememberCallingRecordAudioRequestFlow
import com.wire.kalium.logic.data.call.ConversationType
import com.wire.kalium.logic.data.id.ConversationId

Expand All @@ -80,12 +80,12 @@ fun IncomingCallScreen(
) {
val context = LocalContext.current

val audioPermissionCheck = AudioBluetoothPermissionCheckFlow(
val audioPermissionCheck = AudioPermissionCheckFlow(
incomingCallViewModel::acceptCall,
incomingCallViewModel::showPermissionDialog
)

MicrophoneBTPermissionsDeniedDialog(
MicrophonePermissionDeniedDialog(
shouldShow = incomingCallViewModel.incomingCallState.shouldShowPermissionDialog,
onDismiss = incomingCallViewModel::dismissPermissionDialog,
onOpenSettings = {
Expand Down Expand Up @@ -233,16 +233,16 @@ private fun IncomingCallContent(
}

@Composable
fun AudioBluetoothPermissionCheckFlow(
fun AudioPermissionCheckFlow(
onAcceptCall: () -> Unit,
onPermanentPermissionDecline: () -> Unit,
) = rememberCallingRecordAudioBluetoothRequestFlow(
onAudioBluetoothPermissionGranted = {
appLogger.d("IncomingCall - Permissions granted")
) = rememberCallingRecordAudioRequestFlow(
onAudioPermissionGranted = {
appLogger.d("IncomingCall - Audio permission granted")
onAcceptCall()
},
onAudioBluetoothPermissionDenied = { },
onAudioBluetoothPermissionPermanentlyDenied = onPermanentPermissionDecline
onAudioPermissionDenied = { },
onAudioPermissionPermanentlyDenied = onPermanentPermissionDecline
)

@Preview
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ import com.wire.android.model.SnackBarMessage
import com.wire.android.navigation.BackStackMode
import com.wire.android.navigation.NavigationCommand
import com.wire.android.navigation.Navigator
import com.wire.android.ui.calling.common.MicrophoneBTPermissionsDeniedDialog
import com.wire.android.ui.calling.common.MicrophonePermissionDeniedDialog
import com.wire.android.ui.common.bottomsheet.MenuModalSheetHeader
import com.wire.android.ui.common.bottomsheet.MenuModalSheetLayout
import com.wire.android.ui.common.colorsScheme
Expand Down Expand Up @@ -225,7 +225,7 @@ fun ConversationScreen(
)
}

MicrophoneBTPermissionsDeniedDialog(
MicrophonePermissionDeniedDialog(
shouldShow = conversationCallViewState.shouldShowCallingPermissionDialog,
onDismiss = ::dismissCallingPermissionDialog,
onOpenSettings = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import androidx.compose.ui.platform.LocalContext
import androidx.hilt.navigation.compose.hiltViewModel
import com.wire.android.navigation.NavigationCommand
import com.wire.android.navigation.Navigator
import com.wire.android.ui.calling.common.MicrophoneBTPermissionsDeniedDialog
import com.wire.android.ui.calling.common.MicrophonePermissionDeniedDialog
import com.wire.android.ui.common.bottomsheet.conversation.ConversationOptionNavigation
import com.wire.android.ui.common.bottomsheet.conversation.ConversationSheetContent
import com.wire.android.ui.common.bottomsheet.conversation.rememberConversationSheetState
Expand Down Expand Up @@ -89,7 +89,7 @@ fun ConversationRouterHomeBridge(
viewModel.updateConversationsSource(conversationsSource)
}

MicrophoneBTPermissionsDeniedDialog(
MicrophonePermissionDeniedDialog(
shouldShow = viewModel.conversationListCallState.shouldShowCallingPermissionDialog,
onDismiss = viewModel::dismissCallingPermissionDialog,
onOpenSettings = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
package com.wire.android.util.permission

import android.content.Context
import android.os.Build
import androidx.activity.compose.ManagedActivityResultLauncher
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
Expand All @@ -32,63 +31,50 @@ import com.wire.android.util.extension.checkPermission
import com.wire.android.util.extension.getActivity

@Composable
fun rememberCallingRecordAudioBluetoothRequestFlow(
onAudioBluetoothPermissionGranted: () -> Unit,
onAudioBluetoothPermissionDenied: () -> Unit,
onAudioBluetoothPermissionPermanentlyDenied: () -> Unit,
fun rememberCallingRecordAudioRequestFlow(
onAudioPermissionGranted: () -> Unit,
onAudioPermissionDenied: () -> Unit,
onAudioPermissionPermanentlyDenied: () -> Unit,
): CallingAudioRequestFlow {
val context = LocalContext.current

val requestPermissionLauncher: ManagedActivityResultLauncher<Array<String>, Map<String, @JvmSuppressWildcards Boolean>> =
rememberLauncherForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
var permissionsGranted = true
permissions.values.forEach { if (!it) permissionsGranted = false }

if (permissionsGranted) {
onAudioBluetoothPermissionGranted()
val requestPermissionLauncher: ManagedActivityResultLauncher<String, Boolean> =
rememberLauncherForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted ->
if (isGranted) {
onAudioPermissionGranted()
} else {
context.getActivity()?.let {
if (it.shouldShowRequestPermissionRationale(android.Manifest.permission.RECORD_AUDIO) ||
it.shouldShowRequestPermissionRationale(android.Manifest.permission.BLUETOOTH_CONNECT)
) {
onAudioBluetoothPermissionDenied()
if (it.shouldShowRequestPermissionRationale(android.Manifest.permission.RECORD_AUDIO)) {
onAudioPermissionDenied()
} else {
onAudioBluetoothPermissionPermanentlyDenied()
onAudioPermissionPermanentlyDenied()
}
}
}
}

return remember {
CallingAudioRequestFlow(context, onAudioBluetoothPermissionGranted, requestPermissionLauncher)
CallingAudioRequestFlow(context, onAudioPermissionGranted, requestPermissionLauncher)
}
}

class CallingAudioRequestFlow(
private val context: Context,
private val permissionGranted: () -> Unit,
private val audioRecordPermissionLauncher: ManagedActivityResultLauncher<Array<String>, Map<String, @JvmSuppressWildcards Boolean>>
private val audioRecordPermissionLauncher: ManagedActivityResultLauncher<String, Boolean>
) {
fun launch() {
val audioPermissionEnabled = context.checkPermission(android.Manifest.permission.RECORD_AUDIO)
val bluetoothPermissionEnabled = context.checkPermission(android.Manifest.permission.BLUETOOTH_CONNECT)
val audioPermissionEnabled =
context.checkPermission(android.Manifest.permission.RECORD_AUDIO)

val neededPermissions = mutableListOf(
android.Manifest.permission.RECORD_AUDIO
)

val permissionsEnabled = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
neededPermissions.add(android.Manifest.permission.BLUETOOTH_CONNECT)

audioPermissionEnabled && bluetoothPermissionEnabled
} else {
audioPermissionEnabled
}

if (permissionsEnabled) {
if (audioPermissionEnabled) {
permissionGranted()
} else {
audioRecordPermissionLauncher.launch(neededPermissions.toTypedArray())
audioRecordPermissionLauncher.launch(android.Manifest.permission.RECORD_AUDIO)
}
}
}
4 changes: 2 additions & 2 deletions app/src/main/res/values-af/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1229,7 +1229,7 @@
<string name="record_audio_max_file_size_reached_title">Recording Stopped</string>
<string name="record_audio_max_file_size_reached_text">File size for audio messages is limited to %1$d MB.</string>
<string name="record_audio_unable_due_to_ongoing_call">You can’t record an audio message during a call.</string>
<string name="permission_dialog_title">App permissions</string>
<string name="call_permission_dialog_title">App permission</string>
<string name="call_permission_dialog_description">To make a call, allow Wire to access your microphone and to find nearby devices in your device settings.</string>
<string name="label_not_now">Not Now</string>
<string name="last_message_composite_with_missing_text">sent an interactive message</string>
Expand All @@ -1255,7 +1255,7 @@
<string name="biometrics_prompt_dialog_title">Authenticate with biometrics</string>
<string name="biometrics_prompt_dialog_subtitle">To unlock Wire</string>
<string name="biometrics_use_passcode_button">Use passcode</string>
<string name="biometrics_app_unlock_too_many_attempts">Too many attempts on Biometrics. Unlock with passcode instead.</string>
<string name="biometrics_app_unlock_too_many_attempts">Too many attempts on biometrics. Unlock with passcode instead.</string>
<!-- e2ei-->
<string name="e2ei_certificate_details_screen_title">Certificate Details</string>
<string name="e2ei_certificate_details_copy_to_clipboard">Copy to Clipboard</string>
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/res/values-ar/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1325,7 +1325,7 @@
<string name="record_audio_max_file_size_reached_title">Recording Stopped</string>
<string name="record_audio_max_file_size_reached_text">File size for audio messages is limited to %1$d MB.</string>
<string name="record_audio_unable_due_to_ongoing_call">You can’t record an audio message during a call.</string>
<string name="permission_dialog_title">App permissions</string>
<string name="call_permission_dialog_title">App permission</string>
<string name="call_permission_dialog_description">To make a call, allow Wire to access your microphone and to find nearby devices in your device settings.</string>
<string name="label_not_now">Not Now</string>
<string name="last_message_composite_with_missing_text">sent an interactive message</string>
Expand All @@ -1351,7 +1351,7 @@
<string name="biometrics_prompt_dialog_title">Authenticate with biometrics</string>
<string name="biometrics_prompt_dialog_subtitle">To unlock Wire</string>
<string name="biometrics_use_passcode_button">Use passcode</string>
<string name="biometrics_app_unlock_too_many_attempts">Too many attempts on Biometrics. Unlock with passcode instead.</string>
<string name="biometrics_app_unlock_too_many_attempts">Too many attempts on biometrics. Unlock with passcode instead.</string>
<!-- e2ei-->
<string name="e2ei_certificate_details_screen_title">Certificate Details</string>
<string name="e2ei_certificate_details_copy_to_clipboard">Copy to Clipboard</string>
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/res/values-bn/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1229,7 +1229,7 @@
<string name="record_audio_max_file_size_reached_title">Recording Stopped</string>
<string name="record_audio_max_file_size_reached_text">File size for audio messages is limited to %1$d MB.</string>
<string name="record_audio_unable_due_to_ongoing_call">You can’t record an audio message during a call.</string>
<string name="permission_dialog_title">App permissions</string>
<string name="call_permission_dialog_title">App permissions</string>
<string name="call_permission_dialog_description">To make a call, allow Wire to access your microphone and to find nearby devices in your device settings.</string>
<string name="label_not_now">Not Now</string>
<string name="last_message_composite_with_missing_text">sent an interactive message</string>
Expand All @@ -1255,7 +1255,7 @@
<string name="biometrics_prompt_dialog_title">Authenticate with biometrics</string>
<string name="biometrics_prompt_dialog_subtitle">To unlock Wire</string>
<string name="biometrics_use_passcode_button">Use passcode</string>
<string name="biometrics_app_unlock_too_many_attempts">Too many attempts on Biometrics. Unlock with passcode instead.</string>
<string name="biometrics_app_unlock_too_many_attempts">Too many attempts on biometrics. Unlock with passcode instead.</string>
<!-- e2ei-->
<string name="e2ei_certificate_details_screen_title">Certificate Details</string>
<string name="e2ei_certificate_details_copy_to_clipboard">Copy to Clipboard</string>
Expand Down
Loading

0 comments on commit 43d336e

Please sign in to comment.