Simple Phone
This project shows the absolute minimum an Android Phone app needs to implement to replace the native phone app and provide the UI when making calls.
This app uses minSdkVersion 23
, because that's when the APIs supporting this were added.
Becoming a default Phone 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.
Filters in the AndroidManifest improve a bit over that minimum, to allow setting the app as the default Dialer, and launching dialer from web browser. The Dialer app in AOSP has even more filters declared.
Anyway, this will make your app available in the Settings -> Apps & notifications -> Advanced -> Default apps -> Phone app:
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:
Handling calls
You need to define an InCallService
implementation the system will bind to and notify you about the call:
<service
android:name=".CallService"
android:permission="android.permission.BIND_INCALL_SERVICE">
<meta-data
android:name="android.telecom.IN_CALL_SERVICE_UI"
android:value="true" />
<intent-filter>
<action android:name="android.telecom.InCallService" />
</intent-filter>
</service>
There you should handle at least onCallAdded
(set up listeners on Call
, start your UI - activity - for the call) and onCallRemoved
(remove listeners), like CallService
does in a simplified way.
If the user wants to answer the call, you need to invoke the method Call#answer(int)
(with VideoProfile.STATE_AUDIO_ONLY
for example). In this example CallActivity
reacts to user input by calling those methods on Call
object shared through the OngoingCall
singleton.
Check out Call.Callback
for events that can happen with a single call. This sample uses just the onStateChanged
callback, to update the UI and finish the activity when the remote party hangs up.