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)
+ }
}