13

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.

AndreasSt
  • 163
  • 7

1 Answers1

7

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
}
  • 2
    The blog has more information/context. Worth checking out – Freedom_Ben Aug 30 '19 at 22:36
  • The default Samsung phone app does not check for `android.content.ContactDirectory` in other apps. It is possible that you could download a different phone app that does check for that, in which case this does work for Samsung. – Jacob Michaelis Oct 17 '19 at 22:28
  • @Jacob Michaelis I've downloaded another phone app on a Samsung S9, but unfortunately I wasn't able to get the caller ID from my own app. On Motorola it works very well indeed. Could you please provide more informations how to make this possible for Samsung phones as well? Maybe you have found some workaround already? Which antoher phone app did you install on a Samsung phone to get this working? Did you have to root the phone before? Many thanks in advance. Cheers. – BWappsAndmore Aug 03 '20 at 11:13
  • 1
    I have not actually been able to find another phone app that checks for the right intent on Samsung. I guess until I do, and I test that it works on Samsung, I can't confirm that the issue isn't SamsungOS rather than the app. My speculation is based on a knowledge of how Android Intents work, so I assumed that an app would simply need to look for the right Intent to use the Caller ID info. Interested to see if anyone has figured this out. – Jacob Michaelis Aug 04 '20 at 16:20
  • I faced the same problem.Do you have a solution for Samsung devices? This doesn't work with the default Samsung dialer. – Enes BAŞKAYA Nov 03 '21 at 07:19