Provide the caller id for incoming call from my own app
Asked Answered
H

1

15

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.

Houck answered 19/2, 2018 at 16:58 Comment(0)
L
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
}
Lowelllowenstein answered 30/8, 2019 at 22:2 Comment(8)
The blog has more information/context. Worth checking outCarolynncarolynne
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.Lowelllowenstein
@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.Converted
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.Lowelllowenstein
I faced the same problem.Do you have a solution for Samsung devices? This doesn't work with the default Samsung dialer.Hazing
@JacobMichaelis I've cloned the app from the GitHub repository and I'm trying to test it on an emulator. It doesn't seem like the app is being called when there is an incoming call. I added debug prints in com.example.simplecallerid.callerid.CallerIDProvider and I only see the ones inside onCreate I tried running on a device w/ API level 31 and level 29 - both show the same behaviour. any idea what might be the issue?Gaillard
@NoaDrach I'm sorry I haven't maintained the sample repo so maybe things have changed on the recent versions of Android. I want to say I made it 3 years ago? Anyway, I remember having problems on the emulator it's much easier to test on a physical device. I think what I did was just created an account with Google Voice and use that to fake phone calls to myself and just assign that phone number to the test caller ID. github.com/SimpleNexus/simplecalleridLowelllowenstein
@JacobMichaelis Thanks I started doing changes based on this issuetracker.google.com/issues/230950661 first change was to use a different read permission android.permission.BIND_DIRECTORY_SEARCH. I paused w/ this approach since I saw complaints it doesn't work on Samsung devices. I'll update if I have more findingsGaillard

© 2022 - 2024 — McMap. All rights reserved.