2024年Android 13读取手机状态失效问题求助
解决Android 13上通话状态BroadcastReceiver失效问题
核心原因
Android 13(API 33)对电话权限和广播机制做了收紧:
- 静态注册的
BroadcastReceiver无法接收大部分隐式广播(包括ACTION_PHONE_STATE_CHANGED),这一限制从Android 8.0开始逐步强化,Android 13彻底阻断静态注册的触发路径。 - 电话相关权限拆分更细,获取通话时长、类型等信息需要额外权限。
具体修复步骤
更新权限配置与动态申请
在AndroidManifest.xml中声明必要权限:<uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.READ_CALL_LOG" /> <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />由于这些是危险权限,必须在代码中动态申请(示例为Kotlin):
private const val REQUEST_PHONE_PERMS = 1001 fun checkPhonePermissions(context: Context) { val neededPermissions = arrayOf( Manifest.permission.READ_PHONE_STATE, Manifest.permission.READ_CALL_LOG, Manifest.permission.PROCESS_OUTGOING_CALLS ) val missingPermissions = neededPermissions.filter { ContextCompat.checkSelfPermission(context, it) != PackageManager.PERMISSION_GRANTED } if (missingPermissions.isNotEmpty()) { ActivityCompat.requestPermissions(context as Activity, missingPermissions.toTypedArray(), REQUEST_PHONE_PERMS) } }替换静态注册为动态注册
删除AndroidManifest.xml中静态注册的InfluencerCallBroadcastReceiver,改为在Activity或前台服务中动态注册(确保App在前台时能稳定接收广播):private lateinit var callReceiver: InfluencerCallBroadcastReceiver override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // 先检查权限再注册 checkPhonePermissions(this) callReceiver = InfluencerCallBroadcastReceiver() val filter = IntentFilter().apply { addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED) addAction(Intent.ACTION_NEW_OUTGOING_CALL) } registerReceiver(callReceiver, filter) } override fun onDestroy() { super.onDestroy() // 务必注销接收器,避免内存泄漏 unregisterReceiver(callReceiver) }调整广播接收器逻辑适配Android 13
在InfluencerCallBroadcastReceiver中,获取通话时长等信息时,需通过CallLog.Calls内容提供者查询(依赖READ_CALL_LOG权限),示例:override fun onReceive(context: Context?, intent: Intent?) { if (intent?.action == TelephonyManager.ACTION_PHONE_STATE_CHANGED) { val state = intent.getStringExtra(TelephonyManager.EXTRA_STATE) if (state == TelephonyManager.EXTRA_STATE_IDLE) { // 通话结束,查询最新通话记录 context?.let { ctx -> if (ContextCompat.checkSelfPermission(ctx, Manifest.permission.READ_CALL_LOG) == PackageManager.PERMISSION_GRANTED) { val cursor = ctx.contentResolver.query( CallLog.Calls.CONTENT_URI, arrayOf(CallLog.Calls.DURATION, CallLog.Calls.TYPE, CallLog.Calls.NUMBER), "${CallLog.Calls.DATE} > ?", arrayOf((System.currentTimeMillis() - 60000).toString()), "${CallLog.Calls.DATE} DESC" ) cursor?.use { if (it.moveToFirst()) { val duration = it.getLong(it.getColumnIndexOrThrow(CallLog.Calls.DURATION)) val type = it.getInt(it.getColumnIndexOrThrow(CallLog.Calls.TYPE)) val number = it.getString(it.getColumnIndexOrThrow(CallLog.Calls.NUMBER)) // 上传至服务器的逻辑 uploadCallDetails(duration, type, number) } } } } } } }处理后台运行限制
如果需要App在后台也能监听通话状态,必须启动前台服务(Android 12+对后台服务限制严格),在服务中完成广播接收器的注册,并显示前台通知。
内容的提问来源于stack exchange,提问作者Deepjyoty nath
相关产品推荐
相关产品推荐

