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

targetSdkVersion 31下TelephonyManager相关SecurityException问题求助

Android 12(targetSdkVersion 31)TelephonyManager 权限崩溃解决方案

问题场景

应用将targetSdkVersion设置为31后,出现以下SecurityException崩溃:

java.lang.SecurityException: listen
        at android.os.Parcel.createExceptionOrNull(Parcel.java:3023)
        at android.os.Parcel.createException(Parcel.java:3007)
        at android.os.Parcel.readException(Parcel.java:2990)
        at android.os.Parcel.readException(Parcel.java:2932)
        at com.android.internal.telephony.ITelephonyRegistry$Stub$Proxy.listenWithEventList(ITelephonyRegistry.java:1074)
        at android.telephony.TelephonyRegistryManager.listenFromListener(TelephonyRegistryManager.java:265)
        at android.telephony.TelephonyManager.listen(TelephonyManager.java:7210)
        at kr.co.test.test.zn.run(EBZRNNoneVideoCallActivity.java:1206)
        at android.os.Handler.handleCallback(Handler.java:942)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loopOnce(Looper.java:226)
        at android.os.Looper.loop(Looper.java:313)
        at android.app.ActivityThread.main(ActivityThread.java:8741)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1067)
     Caused by: android.os.RemoteException: Remote stack trace:
        at com.android.internal.telephony.TelephonyPermissions.enforceCarrierPrivilege(TelephonyPermissions.java:676)
        at com.android.internal.telephony.TelephonyPermissions.checkReadPhoneState(TelephonyPermissions.java:169)
        at com.android.internal.telephony.TelephonyPermissions.checkCallingOrSelfReadPhoneState(TelephonyPermissions.java:94)
        at com.android.server.TelephonyRegistry.checkListenerPermission(TelephonyRegistry.java:3424)
        at com.android.server.TelephonyRegistry.listen(TelephonyRegistry.java:1090)

按官方文档提示改用registerTelephonyCallback方法后,未授权调用仍触发SecurityException,且存在Android 11+权限适配混淆(误以为READ_PHONE_NUMBERS可替代READ_PHONE_STATE)。

解决方案

1. 纠正权限认知

registerTelephonyCallback用于监听电话状态(来电、信号等)时,Android 11+仍需READ_PHONE_STATE权限,READ_PHONE_NUMBERS仅用于读取电话号码,无法替代前者完成状态监听。

2. 正确配置与申请权限

  • Manifest声明:在AndroidManifest.xml中添加权限声明:
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    
  • 权限申请逻辑:Android 11+(API30)起,READ_PHONE_STATE属于受保护权限,无法通过常规弹窗请求,需引导用户到应用设置页手动开启:
    private static final int REQ_CODE_PHONE_STATE = 1001;
    
    private void checkPhoneStatePermission() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            if (checkSelfPermission(Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
                // 引导到应用设置页
                Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                Uri uri = Uri.fromParts("package", getPackageName(), null);
                intent.setData(uri);
                startActivity(intent);
            }
        } else {
            // Android 10及以下可正常请求权限
            requestPermissions(new String[]{Manifest.permission.READ_PHONE_STATE}, REQ_CODE_PHONE_STATE);
        }
    }
    

3. 调用前强制校验权限

在调用registerTelephonyCallback前必须检查权限状态,未授权时禁止调用:

TelephonyManager telephonyManager = getSystemService(TelephonyManager.class);
Executor mainExecutor = ContextCompat.getMainExecutor(this);
TelephonyCallback telephonyCallback = new TelephonyCallback() {
    @Override
    public void onCallStateChanged(int state) {
        super.onCallStateChanged(state);
        // 处理电话状态变化逻辑
    }
};

// 权限校验后再调用
if (checkSelfPermission(Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) {
    telephonyManager.registerTelephonyCallback(mainExecutor, telephonyCallback);
} else {
    // 提示用户授权或处理无权限场景
}

4. 适配TelephonyCallback的正确实现

根据业务需求选择对应监听接口,比如监听来电状态使用TelephonyCallback.CallStateListener,避免不必要的权限申请:

TelephonyCallback callStateCallback = new TelephonyCallback.CallStateListener() {
    @Override
    public void onCallStateChanged(int state) {
        switch (state) {
            case TelephonyManager.CALL_STATE_RINGING:
                // 来电响铃逻辑
                break;
            case TelephonyManager.CALL_STATE_OFFHOOK:
                // 通话中逻辑
                break;
            case TelephonyManager.CALL_STATE_IDLE:
                // 空闲状态逻辑
                break;
        }
    }
};

内容的提问来源于stack exchange,提问作者왕감자

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 15:45:31