Replacing default Phone app on Android 6 and 7 with InCallService

Android API level 23 added InCallService to provide the user-interface for managing phone calls. The documentation provides an example manifest registration but I couldn't get it to work. The app compiles fine but Default Apps in settings doesn't show my app.

The only place I found any information about the subject was a StackOverflow question that was closed a year ago. Comment on that question proposed to add android.intent.action.DIAL activity but that didn't help me either. I have tried various combinations of other intent's too (android.intent.action.CALL_DIAL and android.intent.action.ANSWER) in my activity.

Are there any working examples of code needed to replace the phone app? Do the classes need to provide some working methods for the app to show?


Solution 1:

The app compiles fine but Default Apps in settings doesn't show my app.

To have your app listed as a Phone app, you must have an activity with at least those intent filters (to handle both cases mentioned in documentation of ACTION_DIAL, also mentioned in DefaultDialerManager hidden class):

<intent-filter>
    <action android:name="android.intent.action.DIAL" />
    <data android:scheme="tel" />
</intent-filter>
<intent-filter>
    <action android:name="android.intent.action.DIAL" />
</intent-filter>

And to be honest, that's a bit counterintuitive, because setting the default Phone app is separate from setting a default Dialer – the former controls only the ongoing call UI, while the latter controls only the dialing UI.

The above minimum can be improved a bit, to allow setting your dialer as a default, and launching from web browser, by using these intent filters instead:

<intent-filter>
    <!-- Handle links from other applications -->
    <action android:name="android.intent.action.VIEW" />
    <action android:name="android.intent.action.DIAL" />
    <!-- Populate the system chooser -->
    <category android:name="android.intent.category.DEFAULT" />
    <!-- Handle links in browsers -->
    <category android:name="android.intent.category.BROWSABLE" />
    <data android:scheme="tel" />
</intent-filter>
<intent-filter>
    <action android:name="android.intent.action.DIAL" />
    <category android:name="android.intent.category.DEFAULT" />
</intent-filter>

The Dialer app in AOSP has even more filters declared.

You can make it easier for the user to set your app as the default Phone app with the help from TelecomManager:

if (getSystemService(TelecomManager::class.java).defaultDialerPackage != packageName) {
    Intent(TelecomManager.ACTION_CHANGE_DEFAULT_DIALER)
            .putExtra(TelecomManager.EXTRA_CHANGE_DEFAULT_DIALER_PACKAGE_NAME, packageName)
            .let(::startActivity)
}

This will show a dialog similar to this:

change default dialer dialog

Refer to Answer incoming call using android.telecom and InCallService for what you need to do to actually handle the calls themselves.

Here's the code for an app that implements the minimum needed to handle dialing, and accepting/rejecting/ending calls in its own UI:

https://github.com/arekolek/simple-phone