I have an application that makes calls using wifi and I wanted to use Self Manage Calls to better manage interoperability between calls from my app and others, in addition to better managing audio calls.
For that, I'm following this https://developer.android.com/guide/topics/connectivity/telecom/selfManaged.
Everything works great on incoming calls, when I receive a call I see the app handling events from ConnectionService and Connection. I'm using:
(...)
bundle.putParcelable(TelecomManager.EXTRA_INCOMING_CALL_ADDRESS, uri)
bundle.putParcelable(TelecomManager.EXTRA_INCOMING_CALL_EXTRAS, extraBundle)
telecomManager.addNewIncomingCall(phoneAccountHandle, bundle)
However, when I try to make a placeCall()
on some devices it presents the native dialer but I can see some events afterward reaching ConnectionService
In other devices (like oppo) it presents me a dialog saying "Call Failed cannot connect to mobile network", with the following warning:
Calling a method in the system process without a qualified user: android.app.ContextImpl.sendBroadcast:1175 android.content.ContextWrapper.sendBroadcast:489 com.android.server.telecom.oplus.OplusTelecomUtils.sendBroadCastToOcarForCallFailedType:1963 com.android.server.telecom.oplus.OplusTelecomUtils.startOplusErrorDialogActivity:326 com.android.server.telecom.oplus.OplusUserCallIntentProcessor.canGoOnPlaceCall:379
This is how I'm calling placeCall()
val uri: Uri = Uri.fromParts(PhoneAccount.SCHEME_TEL, number, "")
val phoneAccountHandle = PhoneAccountHandle(ComponentName(context, MyConnectionService::class.java), number)
registrationPhoneAccountHandle(phoneAccountHandle, uri)
val bundle = Bundle()
val extraBundle = Bundle()
bundle.putBoolean(TelecomManager.EXTRA_START_CALL_WITH_SPEAKERPHONE, false)
bundle.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, phoneAccountHandle)
bundle.putParcelable(TelecomManager.EXTRA_OUTGOING_CALL_EXTRAS, extraBundle)
telecomManager.placeCall(uri, bundle)
In order to register the phone account I'm doing
private fun registrationPhoneAccountHandle(phoneAccountHandle: PhoneAccountHandle, uri: Uri) {
val callAccountFlags = PhoneAccount.CAPABILITY_SELF_MANAGED
val phoneAccount = PhoneAccount.builder(phoneAccountHandle, "someId")
.setSupportedUriSchemes(listOf(PhoneAccount.SCHEME_TEL))
.setShortDescription("description")
.setAddress(uri)
.setCapabilities(callAccountFlags)
val extra = Bundle()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
extra.putBoolean(PhoneAccount.EXTRA_LOG_SELF_MANAGED_CALLS, false)
}
phoneAccount.setExtras(extra)
val accountBuild = phoneAccount.build()
telecomManager.registerPhoneAccount(accountBuild)
}
Regarding manifest permissions I Have the following:
<uses-permission android:name="android.permission.MANAGE_OWN_CALLS" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.READ_PHONE_NUMBERS" />
What am I missing here?
[EDITED]
With the following flag bundle.putInt(TelecomManager.EXTRA_START_CALL_WITH_VIDEO_STATE, VideoProfile.STATE_BIDIRECTIONAL)
and a custom scheme the native dialer no longer appears. However on Oppo X3 Lite it still displays a dialog, like in the picture, but with the message "Could not place call" and the message on stack. Is there any method to check if the Oppo is not allowed to place calls?
Calling a method in the system process without a qualified user
Try this: Change 2 following lines in PhoneAccount initialization: