You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 07:17:51