Here is the minimum that I needed to do in order make my app (baresip VoIP client) eligible as default Phone app:
In AndroidManifest.xml I added this permission:
<uses-permission android:name="android.permission.CALL_PHONE" />
In AndroidManifest.xml I added these two intent filters to MainActivity:
<intent-filter>
<action android:name="android.intent.action.DIAL" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<action android:name="android.intent.action.DIAL" />
<action android:name="android.intent.action.CALL" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="tel" />
<data android:scheme="sip" />
</intent-filter>
In AndroidManifest.xml I added this new service:
<service
android:name=".InCallService"
android:enabled="true"
android:exported="true"
android:permission="android.permission.BIND_INCALL_SERVICE" >
<meta-data
android:name="android.telecom.IN_CALL_SERVICE_UI"
android:value="true" />
<meta-data
android:name="android.telecom.IN_CALL_SERVICE_CAR_MODE_UI"
android:value="false" />
<intent-filter>
<action android:name="android.telecom.InCallService" />
</intent-filter>
</service>
I didn't check if the meta-data entries are really needed.
Then I implemented the InCallService service like this:
package <my package>
import android.app.Service
import android.content.Intent
import android.os.IBinder
// This is needed in order to allow choosing <my app> as default Phone app
class InCallService : Service() {
override fun onBind(intent: Intent): IBinder {
TODO("Return the communication channel to the service.")
}
}
Finally, if there is need to request default dialer role from the app (and not only from Android Apps settings, it can be done like this (at API level 29+):
val dialerRoleRequest = registerForActivityResult(
ActivityResultContracts.StartActivityForResult()
) {
Log.d(TAG, "dialerRoleRequest succeeded: ${it.resultCode == Activity.RESULT_OK}")
}
if (roleManager.isRoleAvailable(RoleManager.ROLE_DIALER) &&
!roleManager.isRoleHeld(RoleManager.ROLE_DIALER))
dialerRoleRequest.launch(roleManager.createRequestRoleIntent(RoleManager.ROLE_DIALER))
Removing of default dialer role needs to be done from Android Apps settings.