I had the same exact issue with Samsung Gear smartwatch. You see "Unknown" because the caller's name is resolved against device contacts (hence regular GSM calls work as expected). The solution is following:
- I assume that you know the
displayName
(caller's name) and address
(caller's phone number). The address is the Uri which might look like sip:1234567
or tel:+1234567
, it doesn't really matter.
- You need to create a temporary contact with your caller's
displayName
and phoneNumber
. The phoneNumber
here should be Uri.schemeSpecificPart
of the address (the part after :
). The avatar/icon can also be added.
ContentProviderOperation.newInsert(Data.CONTENT_URI)
.withValueBackReference(Data.RAW_CONTACT_ID, 0)
.withValue(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE)
.withValue(StructuredName.GIVEN_NAME, displayName)
.build()
ContentProviderOperation.newInsert(Data.CONTENT_URI)
.withValueBackReference(Data.RAW_CONTACT_ID, 0)
.withValue(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE)
.withValue(Phone.NUMBER, phoneNumber)
.build()
- After adding this contact you need to let
ConnectionService
know that there is now a contact that corresponds to the Connection you created for your VoIP call. contactManager
is my class where aforementioned operations are executed, accountHandle
is a android.telecom.AccountHandle
that is used to
register PhoneAccount
(via telecomManager.registerPhoneAccount()
), address
is our Uri with phone number.
contactManager.createOrUpdateTempContact(address.schemeSpecificPart, displayName)
telecomManager.addNewIncomingCall(accountHandle, bundleOf("key.call.address" to address))
- After calling
addNewIncomingCall
the ConnectionService::onCreateIncomingConnection()
callback will be triggered, and in this function you should set the address:
override fun onCreateIncomingConnection(
connectionManagerPhoneAccount: PhoneAccountHandle?,
request: ConnectionRequest?
): Connection {
val newConnection = // Instantiate your Connection class implementation
request?.let{
newConnection.setAddress(request.extras.getParcelable("key.call.address") as? Uri, TelecomManager.PRESENTATION_ALLOWED)
newConnection.extras = request.extras
}
// Setting up newConnection further (set audioModeIsVoip, connectionProperties, etc.)
return newConnection
}
- You can safely remove the temp contact after the call was answered/rejected.
N.B.
- I omitted posting the whole create/update/delete temp contact code for brevity.
ConnectionRequest.address
returns null
for me in onCreateIncomingConnection()
, that's why I pass it in extras
.
- I played with
setCallerDisplayName()
function and the common sense says that it should be there, but the fix was not related to it.
- In my experience sometimes the incoming call UI on the smartwatch shows phone number first and only after few seconds the name of the contact is displayed. I still didn't manage to fix this delay.