提供来自我的应用的呼入电话的呼叫者ID

15

我想编写一个应用程序,可以通过查找我的应用程序内的一个表格(例如SQLite数据库表格),来识别来电号码。

我已经在iOS上使用了Call Directory Extension实现了这个功能,但是在Android上,我找到的唯一选择是使用一个BroadcastReceiver和弹出窗口来显示联系人信息。

ContactsContract.Directory似乎提供了创建自定义目录的可能性,让原生通话应用程序能够查找呼叫方标识。不幸的是,我找不到任何关于如何完成这个任务的好例子。

是否有人知道是否可以使用ContactsContract.Directory来实现呼叫方标识,或者在Android中是否有类似于Call Directory Extension的东西?如果是这样,一个示例代码将非常有帮助。

1个回答

7

我刚刚写了一个关于如何使这个工作的教程。在此处查看: https://simplenexus.dev/2019/08/27/android-caller-id.html

让这个工作的基本方法是:

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
该博客有更多的信息/背景。值得一看。 - Freedom_Ben
1
我实际上还没有找到另一个检查三星正确意图的手机应用程序。我猜在我找到并测试它在三星上是否有效之前,我无法确认问题不是三星操作系统而不是应用程序。我的推测基于对Android Intent工作方式的了解,因此我认为应用程序只需要查找正确的Intent即可使用Caller ID信息。有兴趣看看是否有人已经解决了这个问题。 - Jacob Michaelis
我遇到了同样的问题。你有解决三星设备的方法吗?这在默认的三星拨号器上不起作用。 - Enes BAŞKAYA
@JacobMichaelis 我已经从GitHub存储库克隆了该应用程序,并正在尝试在模拟器上测试它。 当有来电时,似乎没有调用该应用程序。 我在com.example.simplecallerid.callerid.CallerIDProvider中添加了调试打印,但我只看到onCreate内部的打印。我尝试在API级别31和级别29的设备上运行 - 两者都显示相同的行为。 你有什么想法可能是问题? - Noa Drach
@NoaDrach 很抱歉我没有维护示例存储库,所以最近的 Android 版本可能有所变化。我想说我是在3年前做的吧?总之,我记得在模拟器上有问题,测试物理设备要容易得多。我认为我所做的就是创建一个 Google Voice 账户,使用它来伪造打电话给自己,然后将该电话号码分配给测试呼叫者 ID。 https://github.com/SimpleNexus/simplecallerid - Jacob Michaelis
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接