Android Studio Kotlin中基于Firebase实时数据库的来电拦截实现求助
实现基于Firebase拦截列表的来电拦截(BroadcastReceiver方案)
一、前置权限配置
首先在AndroidManifest.xml中添加必要权限,确保应用能读取电话状态并拦截来电:
<uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.CALL_PHONE" /> <!-- Android 10+ 专属拦截权限 --> <uses-permission android:name="android.permission.ANSWER_PHONE_CALLS" /> <!-- Android 9及以下拦截来电权限 --> <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
二、本地缓存拦截列表(必做优化)
BroadcastReceiver中直接访问Firebase会有延迟,甚至引发ANR,建议将拦截列表缓存到本地,同时监听Firebase的blocklist节点变化,实时更新缓存:
// 监听blocklist节点,同步更新本地缓存 blocklistRef.addValueEventListener(object : ValueEventListener { override fun onDataChange(snapshot: DataSnapshot) { val blockedNumbers = mutableSetOf<String>() snapshot.children.forEach { child -> val number = child.key ?: return@forEach if (child.value as Boolean) blockedNumbers.add(number) } // 保存到SharedPreferences val sharedPref = getSharedPreferences("BlocklistCache", MODE_PRIVATE) sharedPref.edit().putStringSet("blocked_numbers", blockedNumbers).apply() } override fun onCancelled(error: DatabaseError) { // 处理数据库读取错误 } })
三、实现来电拦截BroadcastReceiver
创建PhoneBlockReceiver类,继承自BroadcastReceiver,实现拦截逻辑:
class PhoneBlockReceiver : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { // 读取本地缓存的拦截列表 val sharedPref = context.getSharedPreferences("BlocklistCache", Context.MODE_PRIVATE) val blockedNumbers = sharedPref.getStringSet("blocked_numbers", emptySet()) ?: emptySet() // 获取来电号码并统一格式 val incomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER) incomingNumber?.let { rawNumber -> val formattedNumber = rawNumber.replace("[^\\d+]".toRegex(), "") if (blockedNumbers.contains(formattedNumber)) { // 执行拦截操作 try { val telephonyManager = context.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { telephonyManager.endCall() } else { // 旧版本通过反射调用endCall val method = telephonyManager.javaClass.getDeclaredMethod("endCall") method.isAccessible = true method.invoke(telephonyManager) } // 终止广播传递,避免系统处理来电 abortBroadcast() } catch (e: Exception) { e.printStackTrace() } } } } }
四、注册BroadcastReceiver
在AndroidManifest.xml中注册接收器,设置高优先级确保先于系统处理来电:
<receiver android:name=".PhoneBlockReceiver" android:enabled="true" android:exported="true"> <intent-filter android:priority="999"> <action android:name="android.intent.action.PHONE_STATE" /> </intent-filter> </receiver>
关键注意事项
- 号码格式必须统一:Firebase中存储的是
+91xxxxxxxxxx格式,拦截时需将来电号码转换成相同格式(去掉空格、括号等符号),避免匹配失败。 - Android 10+ 厂商适配:部分品牌对来电拦截有自定义限制,可能需要引导用户手动开启应用的拦截权限。
- 禁止耗时操作:BroadcastReceiver中不能执行网络请求等耗时任务,本地缓存是必须的优化手段。
内容的提问来源于stack exchange,提问作者Undefined man
相关产品推荐
相关产品推荐

