I want to write an App that can identify the phone number of incoming (unknown) calls by looking into a table inside my app (e.g. an SQLite Database Table).
I already implemented this in iOS using a Call Directory Extension, but for Android the only option I can find is using a BroadcastReceiver with a popup above the native incoming call screen to show contact information.
ContactsContract.Directory seems to offer the possibility to create custom directories where the native call app could look up the caller id. Unfortunately, I can't find any good examples on how to accomplish this.
Does anybody know if it is possible to implement the caller id using the ContactsContract.Directory or if there is something similar in Android to the Call Directory Extension in Android? If that is the case, an example code would be really helpful.
Step 1: On the Home Screen, tap Phone. Step 2: Press the left menu button and tap Settings. Step 3: Under Call settings, tap Supplementary services. Step 4: Tap Caller ID to turn it on or off.
I just barely wrote a tutorial on how to get this working. Check it out here: https://simplenexus.dev/2019/08/27/android-caller-id.html
The basics of how to get this working are:
AndroidManifest.xml
<provider
android:name=".callerid.CallerIDProvider"
android:authorities="@string/callerid_authority"
android:readPermission="android.permission.READ_CONTACTS"
android:enabled="true"
android:exported="true">
<meta-data
android:name="android.content.ContactDirectory"
android:value="true"/></provider>
CallerIDProvider.kt
private var userRepository: UserRepository? = null
private val uriMatcher = UriMatcher(UriMatcher.NO_MATCH)
override fun onCreate(): Boolean {
context?.let {
val userDao = UserDatabase.getDatabase(it).userDao()
userRepository = UserRepository(userDao)
val authority = it.getString(R.string.callerid_authority)
uriMatcher.addURI(authority, "directories", DIRECTORIES)
uriMatcher.addURI(authority, "phone_lookup/*", PHONE_LOOKUP)
}
return true
}
override fun query(uri: Uri, projection: Array<out String>?, selection: String?, selectionArgs: Array<out String>?, sortOrder: String?): Cursor? {
when (uriMatcher.match(uri)) {
DIRECTORIES -> {
val label = context?.getString(R.string.app_name) ?: return null
val cursor = MatrixCursor(projection)
projection?.map { column ->
when (column) {
Directory.ACCOUNT_NAME,
Directory.ACCOUNT_TYPE,
Directory.DISPLAY_NAME -> label
Directory.TYPE_RESOURCE_ID -> R.string.app_name
Directory.EXPORT_SUPPORT -> Directory.EXPORT_SUPPORT_SAME_ACCOUNT_ONLY
Directory.SHORTCUT_SUPPORT -> Directory.SHORTCUT_SUPPORT_NONE
else -> null
}
}?.let { cursor.addRow(it) }
return cursor
}
PHONE_LOOKUP -> {
userRepository?.let { userRepo ->
val phoneNumber = uri.pathSegments[1]
val cursor = MatrixCursor(projection)
val user = runBlocking(Dispatchers.IO) { userRepo.getUser(phoneNumber) }
user?.let { u ->
projection?.map { column ->
when (column) {
PhoneLookup._ID -> -1
PhoneLookup.DISPLAY_NAME -> u.fullName
PhoneLookup.LABEL -> u.phoneLabel
else -> null
}
}?.let { cursor.addRow(it) }
}
return cursor
}
}
}
return null
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With