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

Android 11+设备来电检测崩溃:Permission Denial异常求助

Android 11+ 来电检测权限授予后崩溃问题

问题详情

开发来电检测功能时,在API >=30(Android 11及以上)设备上,用户授予权限后应用直接崩溃,Logcat输出如下异常信息:

FATAL EXCEPTION: main
 Process: com.example.callerdetecter, PID: 11623
 java.lang.SecurityException: Permission Denial: not allowed to send broadcast android.intent.action.PHONE_STATE from pid=11623, uid=11219
 at android.os.Parcel.createExceptionOrNull(Parcel.java:2374)
 at android.os.Parcel.createException(Parcel.java:2358)
 at android.os.Parcel.readException(Parcel.java:2341)
 at android.os.Parcel.readException(Parcel.java:2283)
 at android.app.IActivityManager$Stub$Proxy.broadcastIntentWithFeature(IActivityManager.java:5623)
 at android.app.ContextImpl.sendBroadcast(ContextImpl.java:1115)
 at android.content.ContextWrapper.sendBroadcast(ContextWrapper.java:468)
 at android.content.ContextWrapper.sendBroadcast(ContextWrapper.java:468)
 at com.example.callerdetecter.MainActivity.prepareBroadcast(MainActivity.java:73)
 at com.example.callerdetecter.MainActivity.lambda$onCreate$0$com-example-callerdetecter-MainActivity(MainActivity.java:33)
 at com.example.callerdetecter.MainActivity$$ExternalSyntheticLambda0.onClick(Unknown Source:2)
 at android.view.View.performClick(View.java:7503)
 at com.google.android.material.button.MaterialButton.performClick(MaterialButton.java:1218)
 at android.view.View.performClickInternal(View.java:7480)
 at android.view.View.access$3600(View.java:813)
 at android.view.View$PerformClick.run(View.java:28445)
 at android.os.Handler.handleCallback(Handler.java:938)
 at android.os.Handler.dispatchMessage(Handler.java:99)
 at android.os.Looper.loop(Looper.java:223)
 at android.app.ActivityThread.main(ActivityThread.java:7950)
 at java.lang.reflect.Method.invoke(Native Method)
 at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:603)
 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
 Caused by: android.os.RemoteException: Remote stack trace:
 at com.android.server.am.ActivityManagerService.broadcastIntentLocked(ActivityManagerService.java:16429)
 at com.android.server.am.ActivityManagerService.broadcastIntentLocked(ActivityManagerService.java:162
 at com.android.server.am.ActivityManagerService.broadcastIntentWithFeature(ActivityManagerService.java:17116)
 at android.app.IActivityManager$Stub.onTransact(IActivityManager.java:2306)
 at com.android.server.am.ActivityManagerService.onTransact(ActivityManagerService.java:2926)

问题原因

Android 11(API 30)及以上版本对系统广播做了严格限制:android.intent.action.PHONE_STATE是受保护的系统广播,仅系统应用有权发送。你的代码在MainActivity.prepareBroadcast方法(第73行)中调用sendBroadcast发送该广播,直接触发了SecurityException。

修复方案

1. 删除非法广播发送逻辑

找到MainActivity.java第73行的sendBroadcast调用,删除发送android.intent.action.PHONE_STATE广播的代码。

2. 正确实现来电检测(接收系统广播)

来电检测的核心是接收系统发出的通话状态广播,而非自行发送:

  • 动态注册广播接收器(推荐方式,适配Android 12+的隐式广播限制):
    private BroadcastReceiver callStateReceiver;
    
    @Override
    protected void onResume() {
        super.onResume();
        callStateReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                String action = intent.getAction();
                if (TelephonyManager.ACTION_PHONE_STATE_CHANGED.equals(action)) {
                    // 处理来电状态变化逻辑
                    String state = intent.getStringExtra(TelephonyManager.EXTRA_STATE);
                    if (TelephonyManager.EXTRA_STATE_RINGING.equals(state)) {
                        String incomingNumber = intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
                        // 处理来电号码
                    }
                }
            }
        };
        IntentFilter filter = new IntentFilter(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
        registerReceiver(callStateReceiver, filter);
    }
    
    @Override
    protected void onPause() {
        super.onPause();
        if (callStateReceiver != null) {
            unregisterReceiver(callStateReceiver);
        }
    }
    
  • 若使用静态注册(仅适配Android 11及以下,Android 12+需动态注册):
    <receiver android:name=".CallStateReceiver">
        <intent-filter>
            <action android:name="android.intent.action.PHONE_STATE" />
        </intent-filter>
    </receiver>
    

3. 确保权限配置完整

在AndroidManifest.xml中添加权限:

<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<!-- 若需读取来电号码,Android 10+还需添加以下权限 -->
<uses-permission android:name="android.permission.READ_CALL_LOG" />

并在运行时请求权限:

private static final int REQUEST_PHONE_PERMISSIONS = 100;

private void requestPhonePermissions() {
    String[] permissions = {
            Manifest.permission.READ_PHONE_STATE,
            Manifest.permission.READ_CALL_LOG
    };
    if (ContextCompat.checkSelfPermission(this, permissions[0]) != PackageManager.PERMISSION_GRANTED
            || ContextCompat.checkSelfPermission(this, permissions[1]) != PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(this, permissions, REQUEST_PHONE_PERMISSIONS);
    }
}

内容的提问来源于stack exchange,提问作者SUSMITA BHATTACHARYA

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 00:34:55