diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 5bf85a42e..b096a298d 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -42,6 +42,9 @@
+
+
+
-->
+
+
+
+
+
+
.
+ */
+package org.linphone.telecom
+
+import android.content.Context
+import android.net.Uri
+import android.os.Build
+import android.telecom.CallRedirectionService
+import android.telecom.PhoneAccount
+import android.telecom.PhoneAccountHandle
+import android.telecom.TelecomManager
+import androidx.annotation.RequiresApi
+import androidx.core.net.toUri
+import org.linphone.LinphoneApplication.Companion.coreContext
+import org.linphone.core.tools.Log
+
+@RequiresApi(Build.VERSION_CODES.Q)
+class TelecomRedirectionService : CallRedirectionService() {
+ companion object {
+ private const val TAG = "[Telecom Redirection Service]"
+ }
+
+ override fun onPlaceCall(
+ handle: Uri,
+ initialPhoneAccount: PhoneAccountHandle,
+ allowInteractiveResponse: Boolean
+ ) {
+ Log.i("$TAG onPlaceCall called with URI [$handle]")
+
+ if (handle.scheme != "tel") {
+ placeCallUnmodified()
+ return
+ }
+
+ val number = handle.toString().substring("tel:".length)
+ Log.i("$TAG Extracted number [$number] from tel: URI")
+
+ val telecomManager: TelecomManager = coreContext.context.getSystemService(Context.TELECOM_SERVICE) as TelecomManager
+ val phoneAccountHandleList: List = telecomManager.selfManagedPhoneAccounts
+ var found = false
+ for (phoneAccountHandle in phoneAccountHandleList) {
+ val phoneAccount: PhoneAccount =
+ telecomManager.getPhoneAccount(phoneAccountHandle)
+ Log.i("$TAG handle [$phoneAccountHandle] componentName = ${phoneAccountHandle.componentName}")
+ if (phoneAccountHandle.componentName.packageName == coreContext.context.packageName) {
+ Log.i("$TAG PLACING CALL!")
+ redirectCall("sip:sylvain@sip.linphone.org".toUri(), phoneAccountHandle, allowInteractiveResponse)
+ found = true
+ }
+ }
+ if (!found) {
+ Log.i("$TAG No matching phone account handle found :'(")
+ placeCallUnmodified()
+ }
+ }
+}
diff --git a/app/src/main/java/org/linphone/ui/main/MainActivity.kt b/app/src/main/java/org/linphone/ui/main/MainActivity.kt
index 56c69c961..ee8905f6c 100644
--- a/app/src/main/java/org/linphone/ui/main/MainActivity.kt
+++ b/app/src/main/java/org/linphone/ui/main/MainActivity.kt
@@ -22,6 +22,8 @@ package org.linphone.ui.main
import android.Manifest
import android.annotation.SuppressLint
import android.app.Dialog
+import android.app.role.RoleManager
+import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Color
@@ -89,6 +91,8 @@ class MainActivity : GenericActivity() {
private const val CHAT_FRAGMENT_ID = 3
private const val MEETINGS_FRAGMENT_ID = 4
+ private const val REDIRECT_ROLE_REQUEST_CODE = 1
+
const val ARGUMENTS_CHAT = "Chat"
const val ARGUMENTS_CONVERSATION_ID = "ConversationId"
}
@@ -391,6 +395,8 @@ class MainActivity : GenericActivity() {
Log.d("$TAG savedInstanceState is null but intent isn't, handling it")
handleIntent(intent)
}
+
+ requestCallRedirectionRole()
}
override fun onPause() {
@@ -849,4 +855,24 @@ class MainActivity : GenericActivity() {
}
}
}
+
+ private val requestPermissionLauncher = registerForActivityResult(
+ ActivityResultContracts.RequestMultiplePermissions()
+ ) { isGranted ->
+
+ }
+
+ private fun requestCallRedirectionRole() {
+ requestPermissionLauncher.launch(arrayOf(Manifest.permission.READ_PHONE_STATE, Manifest.permission.READ_PHONE_NUMBERS))
+ if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.Q) {
+ val roleManager: RoleManager = getSystemService(Context.ROLE_SERVICE) as RoleManager
+ // Check if the app needs to register call redirection role.
+ val shouldRequestRole = roleManager.isRoleAvailable(RoleManager.ROLE_CALL_REDIRECTION) &&
+ !roleManager.isRoleHeld(RoleManager.ROLE_CALL_REDIRECTION)
+ if (shouldRequestRole) {
+ val intent = roleManager.createRequestRoleIntent(RoleManager.ROLE_CALL_REDIRECTION)
+ startActivityForResult(intent, REDIRECT_ROLE_REQUEST_CODE)
+ }
+ }
+ }
}