diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ba239016..f255a7bbc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,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 6e3ac15d5..47d14f156 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -32,6 +32,11 @@ + + + () + if (!PermissionHelper.get().hasRecordAudioPermission()) { Log.i("[Incoming Call Activity] Asking for RECORD_AUDIO permission") permissionsRequiredList.add(Manifest.permission.RECORD_AUDIO) @@ -142,6 +143,11 @@ class IncomingCallActivity : GenericActivity() { permissionsRequiredList.add(Manifest.permission.CAMERA) } + if (Version.sdkAboveOrEqual(Version.API31_ANDROID_12) && !PermissionHelper.get().hasBluetoothConnectPermission()) { + Log.i("[Incoming Call Activity] Asking for BLUETOOTH_CONNECT permission") + permissionsRequiredList.add(Compatibility.BLUETOOTH_CONNECT) + } + if (permissionsRequiredList.isNotEmpty()) { val permissionsRequired = arrayOfNulls(permissionsRequiredList.size) permissionsRequiredList.toArray(permissionsRequired) @@ -164,6 +170,9 @@ class IncomingCallActivity : GenericActivity() { Log.i("[Incoming Call Activity] CAMERA permission has been granted") coreContext.core.reloadVideoDevices() } + Compatibility.BLUETOOTH_CONNECT -> if (grantResults[i] == PackageManager.PERMISSION_GRANTED) { + Log.i("[Incoming Call Activity] BLUETOOTH_CONNECT permission has been granted") + } } } } diff --git a/app/src/main/java/org/linphone/activities/call/OutgoingCallActivity.kt b/app/src/main/java/org/linphone/activities/call/OutgoingCallActivity.kt index 5dc2a1676..0d1b60597 100644 --- a/app/src/main/java/org/linphone/activities/call/OutgoingCallActivity.kt +++ b/app/src/main/java/org/linphone/activities/call/OutgoingCallActivity.kt @@ -35,6 +35,7 @@ import org.linphone.activities.call.viewmodels.CallViewModel import org.linphone.activities.call.viewmodels.CallViewModelFactory import org.linphone.activities.call.viewmodels.ControlsViewModel import org.linphone.activities.main.MainActivity +import org.linphone.compatibility.Compatibility import org.linphone.core.Call import org.linphone.core.tools.Log import org.linphone.databinding.CallOutgoingActivityBinding @@ -169,14 +170,22 @@ class OutgoingCallActivity : ProximitySensorActivity() { @TargetApi(Version.API23_MARSHMALLOW_60) private fun checkPermissions() { val permissionsRequiredList = arrayListOf() + if (!PermissionHelper.get().hasRecordAudioPermission()) { Log.i("[Outgoing Call Activity] Asking for RECORD_AUDIO permission") permissionsRequiredList.add(Manifest.permission.RECORD_AUDIO) } + if (viewModel.call.currentParams.isVideoEnabled && !PermissionHelper.get().hasCameraPermission()) { Log.i("[Outgoing Call Activity] Asking for CAMERA permission") permissionsRequiredList.add(Manifest.permission.CAMERA) } + + if (Version.sdkAboveOrEqual(Version.API31_ANDROID_12) && !PermissionHelper.get().hasBluetoothConnectPermission()) { + Log.i("[Outgoing Call Activity] Asking for BLUETOOTH_CONNECT permission") + permissionsRequiredList.add(Compatibility.BLUETOOTH_CONNECT) + } + if (permissionsRequiredList.isNotEmpty()) { val permissionsRequired = arrayOfNulls(permissionsRequiredList.size) permissionsRequiredList.toArray(permissionsRequired) @@ -200,6 +209,9 @@ class OutgoingCallActivity : ProximitySensorActivity() { Log.i("[Outgoing Call Activity] CAMERA permission has been granted") coreContext.core.reloadVideoDevices() } + Compatibility.BLUETOOTH_CONNECT -> if (grantResults[i] == PackageManager.PERMISSION_GRANTED) { + Log.i("[Incoming Call Activity] BLUETOOTH_CONNECT permission has been granted") + } } } } diff --git a/app/src/main/java/org/linphone/activities/call/fragments/ControlsFragment.kt b/app/src/main/java/org/linphone/activities/call/fragments/ControlsFragment.kt index 3765a4183..b2a209d2f 100644 --- a/app/src/main/java/org/linphone/activities/call/fragments/ControlsFragment.kt +++ b/app/src/main/java/org/linphone/activities/call/fragments/ControlsFragment.kt @@ -24,6 +24,7 @@ import android.animation.ValueAnimator import android.annotation.TargetApi import android.app.Dialog import android.content.Intent +import android.content.pm.PackageManager import android.content.pm.PackageManager.PERMISSION_GRANTED import android.os.Bundle import android.os.SystemClock @@ -40,6 +41,7 @@ import org.linphone.activities.call.viewmodels.ControlsViewModel import org.linphone.activities.call.viewmodels.SharedCallViewModel import org.linphone.activities.main.MainActivity import org.linphone.activities.main.viewmodels.DialogViewModel +import org.linphone.compatibility.Compatibility import org.linphone.core.Call import org.linphone.core.tools.Log import org.linphone.databinding.CallControlsFragmentBinding @@ -248,6 +250,9 @@ class ControlsFragment : GenericFragment() { Log.i("[Controls Fragment] CAMERA permission has been granted") coreContext.core.reloadVideoDevices() } + Compatibility.BLUETOOTH_CONNECT -> if (grantResults[i] == PERMISSION_GRANTED) { + Log.i("[Incoming Call Activity] BLUETOOTH_CONNECT permission has been granted") + } } } } else if (requestCode == 1) { @@ -276,6 +281,11 @@ class ControlsFragment : GenericFragment() { permissionsRequiredList.add(Manifest.permission.CAMERA) } + if (Version.sdkAboveOrEqual(Version.API31_ANDROID_12) && !PermissionHelper.get().hasBluetoothConnectPermission()) { + Log.i("[Controls Fragment] Asking for BLUETOOTH_CONNECT permission") + permissionsRequiredList.add(Compatibility.BLUETOOTH_CONNECT) + } + if (permissionsRequiredList.isNotEmpty()) { val permissionsRequired = arrayOfNulls(permissionsRequiredList.size) permissionsRequiredList.toArray(permissionsRequired) diff --git a/app/src/main/java/org/linphone/compatibility/Api31Compatibility.kt b/app/src/main/java/org/linphone/compatibility/Api31Compatibility.kt index 2d74d2b23..abc5ee1d1 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 @@ -155,5 +156,9 @@ class Api31Compatibility { Log.e("[Api31 Compatibility] Can't start service as foreground! $fssnae") } } + + 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 a1378f5c3..787b84d1d 100644 --- a/app/src/main/java/org/linphone/compatibility/Compatibility.kt +++ b/app/src/main/java/org/linphone/compatibility/Compatibility.kt @@ -47,6 +47,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) @@ -72,6 +74,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) + } }