From 34e000e3bb9a2aa99772b8244e8b97fb2eaddfc8 Mon Sep 17 00:00:00 2001 From: Sylvain Berfini Date: Mon, 28 Feb 2022 11:18:00 +0100 Subject: [PATCH] BLUETOOTH_CONNECT permission is required starting Android 12 --- CHANGELOG.md | 1 + app/src/main/AndroidManifest.xml | 5 ++ .../ConferenceWaitingRoomFragment.kt | 12 +++++ .../ConferenceWaitingRoomViewModel.kt | 2 +- .../linphone/activities/voip/CallActivity.kt | 11 +++++ .../compatibility/Api31Compatibility.kt | 5 ++ .../linphone/compatibility/Compatibility.kt | 9 ++++ .../org/linphone/utils/PermissionHelper.kt | 4 ++ .../conference_waiting_room_fragment.xml | 49 ++++++++++--------- 9 files changed, 73 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e35f249a5..20ac29e20 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ Group changes to describe their impact on the project, as follows: ## [4.6.2] - Unreleased ### Added +- Request BLUETOOTH_CONNECT permission on Android 12+ devices, if not we won't be notified when a BT device is being connected/disconnected while app is alive. - LDAP settings if SDK is built with OpenLDAP (requires 5.1.1 or higher linphone-sdk), will add contacts if any - SIP addresses & phone numbers can be selected in history & contact details view - Text can be selected in file viewer & config viewer diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 7c804cb23..fd3ad0fa0 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -32,6 +32,11 @@ + + + () + if (!PermissionHelper.get().hasRecordAudioPermission()) { Log.i("[Conference Waiting Room] Asking for RECORD_AUDIO permission") permissionsRequiredList.add(Manifest.permission.RECORD_AUDIO) } + if (!PermissionHelper.get().hasCameraPermission()) { Log.i("[Conference Waiting Room] Asking for CAMERA permission") permissionsRequiredList.add(Manifest.permission.CAMERA) } + + if (Version.sdkAboveOrEqual(Version.API31_ANDROID_12) && !PermissionHelper.get().hasBluetoothConnectPermission()) { + Log.i("[Conference Waiting Room] Asking for BLUETOOTH_CONNECT permission") + permissionsRequiredList.add(Compatibility.BLUETOOTH_CONNECT) + } + if (permissionsRequiredList.isNotEmpty()) { val permissionsRequired = arrayOfNulls(permissionsRequiredList.size) permissionsRequiredList.toArray(permissionsRequired) @@ -161,6 +170,9 @@ class ConferenceWaitingRoomFragment : GenericFragment if (grantResults[i] == PackageManager.PERMISSION_GRANTED) { + Log.i("[Conference Waiting Room] BLUETOOTH_CONNECT permission has been granted") + } } } } diff --git a/app/src/main/java/org/linphone/activities/main/conference/viewmodels/ConferenceWaitingRoomViewModel.kt b/app/src/main/java/org/linphone/activities/main/conference/viewmodels/ConferenceWaitingRoomViewModel.kt index ff0b9c197..1e614560b 100644 --- a/app/src/main/java/org/linphone/activities/main/conference/viewmodels/ConferenceWaitingRoomViewModel.kt +++ b/app/src/main/java/org/linphone/activities/main/conference/viewmodels/ConferenceWaitingRoomViewModel.kt @@ -119,7 +119,7 @@ class ConferenceWaitingRoomViewModel : ViewModel() { } else { setEarpieceAudioRoute() } - updateAudioRouteState() + onAudioDevicesListUpdated() } override fun onCleared() { diff --git a/app/src/main/java/org/linphone/activities/voip/CallActivity.kt b/app/src/main/java/org/linphone/activities/voip/CallActivity.kt index 70a4f8fb2..733aad567 100644 --- a/app/src/main/java/org/linphone/activities/voip/CallActivity.kt +++ b/app/src/main/java/org/linphone/activities/voip/CallActivity.kt @@ -195,16 +195,24 @@ class CallActivity : ProximitySensorActivity() { @TargetApi(Version.API23_MARSHMALLOW_60) private fun checkPermissions() { val permissionsRequiredList = arrayListOf() + if (!PermissionHelper.get().hasRecordAudioPermission()) { Log.i("[Call] Asking for RECORD_AUDIO permission") permissionsRequiredList.add(Manifest.permission.RECORD_AUDIO) } + if (callsViewModel.currentCallData.value?.call?.currentParams?.isVideoEnabled == true && !PermissionHelper.get().hasCameraPermission() ) { Log.i("[Call] Asking for CAMERA permission") permissionsRequiredList.add(Manifest.permission.CAMERA) } + + if (Version.sdkAboveOrEqual(Version.API31_ANDROID_12) && !PermissionHelper.get().hasBluetoothConnectPermission()) { + Log.i("[Call] Asking for BLUETOOTH_CONNECT permission") + permissionsRequiredList.add(Compatibility.BLUETOOTH_CONNECT) + } + if (permissionsRequiredList.isNotEmpty()) { val permissionsRequired = arrayOfNulls(permissionsRequiredList.size) permissionsRequiredList.toArray(permissionsRequired) @@ -228,6 +236,9 @@ class CallActivity : ProximitySensorActivity() { Log.i("[Call] CAMERA permission has been granted") coreContext.core.reloadVideoDevices() } + Compatibility.BLUETOOTH_CONNECT -> if (grantResults[i] == PackageManager.PERMISSION_GRANTED) { + Log.i("[Call] BLUETOOTH_CONNECT permission has been granted") + } } } } diff --git a/app/src/main/java/org/linphone/compatibility/Api31Compatibility.kt b/app/src/main/java/org/linphone/compatibility/Api31Compatibility.kt index f87548504..392fe5844 100644 --- a/app/src/main/java/org/linphone/compatibility/Api31Compatibility.kt +++ b/app/src/main/java/org/linphone/compatibility/Api31Compatibility.kt @@ -19,6 +19,7 @@ */ package org.linphone.compatibility +import android.Manifest import android.annotation.TargetApi import android.app.* import android.content.Context @@ -173,5 +174,9 @@ class Api31Compatibility { Log.i("[Call] PiP auto enter enabled params set to $enable") } } + + fun hasBluetoothConnectPermission(context: Context): Boolean { + return Compatibility.hasPermission(context, Manifest.permission.BLUETOOTH_CONNECT) + } } } diff --git a/app/src/main/java/org/linphone/compatibility/Compatibility.kt b/app/src/main/java/org/linphone/compatibility/Compatibility.kt index 1b821404e..5f910e112 100644 --- a/app/src/main/java/org/linphone/compatibility/Compatibility.kt +++ b/app/src/main/java/org/linphone/compatibility/Compatibility.kt @@ -48,6 +48,8 @@ import org.linphone.telecom.NativeCallWrapper @Suppress("DEPRECATION") class Compatibility { companion object { + const val BLUETOOTH_CONNECT = "android.permission.BLUETOOTH_CONNECT" + fun hasPermission(context: Context, permission: String): Boolean { return when (Version.sdkAboveOrEqual(Version.API23_MARSHMALLOW_60)) { true -> Api23Compatibility.hasPermission(context, permission) @@ -73,6 +75,13 @@ class Compatibility { } } + fun hasBluetoothConnectPermission(context: Context): Boolean { + if (Version.sdkAboveOrEqual(Version.API31_ANDROID_12)) { + return Api31Compatibility.hasBluetoothConnectPermission(context) + } + return true + } + // See https://developer.android.com/about/versions/11/privacy/permissions#phone-numbers fun hasTelecomManagerPermissions(context: Context): Boolean { return if (Version.sdkAboveOrEqual(Version.API30_ANDROID_11)) { diff --git a/app/src/main/java/org/linphone/utils/PermissionHelper.kt b/app/src/main/java/org/linphone/utils/PermissionHelper.kt index 3d28a3b42..679a3b76a 100644 --- a/app/src/main/java/org/linphone/utils/PermissionHelper.kt +++ b/app/src/main/java/org/linphone/utils/PermissionHelper.kt @@ -73,4 +73,8 @@ class PermissionHelper private constructor(private val context: Context) { fun hasRecordAudioPermission(): Boolean { return hasPermission(Manifest.permission.RECORD_AUDIO) } + + fun hasBluetoothConnectPermission(): Boolean { + return Compatibility.hasBluetoothConnectPermission(context) + } } diff --git a/app/src/main/res/layout/conference_waiting_room_fragment.xml b/app/src/main/res/layout/conference_waiting_room_fragment.xml index c7a4deb64..5de2ad687 100644 --- a/app/src/main/res/layout/conference_waiting_room_fragment.xml +++ b/app/src/main/res/layout/conference_waiting_room_fragment.xml @@ -224,37 +224,38 @@ app:layout_constraintDimensionRatio="W,1:1" app:layout_constraintEnd_toStartOf="@id/speaker" /> - + app:layout_constraintStart_toStartOf="parent"> - + + + + +