Android应用如何在后台检测来电?需实现完全关闭时仍可检测
Android 后台来电检测(应用完全关闭时生效)
要实现类似Truecaller的后台来电检测效果,核心是让检测逻辑脱离应用进程的常规生命周期,结合前台服务+动态广播注册,同时规避系统的电池优化和后台限制,具体步骤如下:
1. 申请必要权限
在AndroidManifest.xml中声明权限:
<uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" /> <!-- Android 13+ 需添加通知权限以启动前台服务 --> <uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
其中READ_PHONE_STATE属于危险权限,需要在代码中动态申请,用户授权后才能启动检测服务。
2. 实现前台服务+动态广播接收器
Android 8.0及以上版本限制了静态广播的接收范围,因此必须在前台服务中动态注册电话状态广播,确保应用被完全关闭后仍能检测来电:
2.1 创建来电检测前台服务
class CallDetectionService : Service() { private lateinit var phoneStateReceiver: PhoneStateReceiver override fun onCreate() { super.onCreate() // 初始化并注册广播接收器 phoneStateReceiver = PhoneStateReceiver() val intentFilter = IntentFilter(TelephonyManager.ACTION_PHONE_STATE_CHANGED) registerReceiver(phoneStateReceiver, intentFilter) // 启动前台服务,避免被系统回收 startForeground(NOTIFICATION_ID, createForegroundNotification()) } override fun onDestroy() { super.onDestroy() // 注销广播接收器 unregisterReceiver(phoneStateReceiver) } override fun onBind(intent: Intent): IBinder? = null private fun createForegroundNotification(): Notification { val channelId = "call_detection_channel" // Android 8.0+ 创建通知渠道 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val channel = NotificationChannel( channelId, "来电检测服务", NotificationManager.IMPORTANCE_LOW // 低优先级,避免打扰用户 ) getSystemService(NotificationManager::class.java).createNotificationChannel(channel) } // 点击通知跳转回应用 val launchIntent = packageManager.getLaunchIntentForPackage(packageName) val pendingIntent = PendingIntent.getActivity( this, 0, launchIntent, PendingIntent.FLAG_IMMUTABLE ) return NotificationCompat.Builder(this, channelId) .setContentTitle("来电检测中") .setContentText("后台运行以监测来电") .setSmallIcon(R.drawable.ic_notification) .setContentIntent(pendingIntent) .setPriority(NotificationCompat.PRIORITY_LOW) .build() } companion object { const val NOTIFICATION_ID = 1001 } }
在Manifest中声明服务:
<service android:name=".CallDetectionService" android:foregroundServiceType="phoneCall" /> <!-- Android 12+ 指定服务类型 -->
2.2 实现来电状态广播接收器
class PhoneStateReceiver : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { val telephonyManager = context?.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager when (telephonyManager.callState) { TelephonyManager.CALL_STATE_RINGING -> { // 来电响铃,获取来电号码并处理 val incomingNumber = intent?.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER) // 此处添加你的来电检测逻辑(如号码识别、播报等) } TelephonyManager.CALL_STATE_OFFHOOK -> { // 电话接通,可执行对应逻辑 } TelephonyManager.CALL_STATE_IDLE -> { // 电话挂断/空闲,重置状态 } } } }
3. 开机自启动配置
添加开机广播接收器,确保设备重启后服务自动启动:
class BootCompletedReceiver : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent?) { if (intent?.action == Intent.ACTION_BOOT_COMPLETED) { val serviceIntent = Intent(context, CallDetectionService::class.java) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { context?.startForegroundService(serviceIntent) } else { context?.startService(serviceIntent) } } } }
在Manifest中注册接收器:
<receiver android:name=".BootCompletedReceiver" android:enabled="true" android:exported="true"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> </intent-filter> </receiver>
4. 规避电池优化
国产厂商的电池优化会强制杀死后台服务,需引导用户将应用加入电池白名单:
// 检查是否已忽略电池优化 fun isIgnoringBatteryOptimizations(context: Context): Boolean { val powerManager = context.getSystemService(Context.POWER_SERVICE) as PowerManager return powerManager.isIgnoringBatteryOptimizations(context.packageName) } // 请求忽略电池优化 fun requestIgnoreBatteryOptimization(context: Context) { val intent = Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS) intent.data = Uri.parse("package:${context.packageName}") context.startActivity(intent) }
关键注意事项
- Android 12+ 必须指定
foregroundServiceType="phoneCall",否则前台服务可能无法正常启动。 - 部分厂商(小米、华为、OPPO等)存在额外的后台限制,需在应用内引导用户手动开启「自启动」权限。
- 动态权限申请必须在用户授权后再启动服务,避免权限不足导致功能失效。
内容的提问来源于stack exchange,提问作者Sahil Malik
相关产品推荐
相关产品推荐

