java - 在 targetSdkVersion 设置为 31 或 android 12 后,telephonyManager.listen 不起作用

标签 java android

在我将 targetSdkVersion 升级到 31 后,telephonyManager.listen 不起作用。考虑以下代码行:
telephonyManager.listen(phoneStateListener,PhoneStateListener.LISTEN_CALL_STATE);
logcat 错误信息如下:

2022-02-27 13:51:36.313 6426-6426/com.example.app E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.app, PID: 6426
java.lang.RuntimeException: Unable to start service com.example.app.myPlayService@7ace64e with Intent { cmp=com.example.app/.myPlayService (has extras) }: java.lang.SecurityException: listen
    at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:4657)
    at android.app.ActivityThread.access$2000(ActivityThread.java:247)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2091)
    at android.os.Handler.dispatchMessage(Handler.java:106)
    at android.os.Looper.loopOnce(Looper.java:201)
    at android.os.Looper.loop(Looper.java:288)
    at android.app.ActivityThread.main(ActivityThread.java:7839)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
 Caused by: java.lang.SecurityException: listen
    at android.os.Parcel.createExceptionOrNull(Parcel.java:2425)
    at android.os.Parcel.createException(Parcel.java:2409)
    at android.os.Parcel.readException(Parcel.java:2392)
    at android.os.Parcel.readException(Parcel.java:2334)
    at com.android.internal.telephony.ITelephonyRegistry$Stub$Proxy.listenWithEventList(ITelephonyRegistry.java:1036)
    at android.telephony.TelephonyRegistryManager.listenFromListener(TelephonyRegistryManager.java:250)
    at android.telephony.TelephonyManager.listen(TelephonyManager.java:5999)
    at com.example.app.myPlayService.onStartCommand(myPlayService.java:186)
    at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:4639)
    at android.app.ActivityThread.access$2000(ActivityThread.java:247) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2091) 
    at android.os.Handler.dispatchMessage(Handler.java:106) 
    at android.os.Looper.loopOnce(Looper.java:201) 
    at android.os.Looper.loop(Looper.java:288) 
    at android.app.ActivityThread.main(ActivityThread.java:7839) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003) 
 Caused by: android.os.RemoteException: Remote stack trace:
    at com.android.internal.telephony.TelephonyPermissions.enforceCarrierPrivilege(TelephonyPermissions.java:634)
    at com.android.internal.telephony.TelephonyPermissions.checkReadPhoneState(TelephonyPermissions.java:149)
    at com.android.internal.telephony.TelephonyPermissions.checkCallingOrSelfReadPhoneState(TelephonyPermissions.java:94)
    at com.android.server.TelephonyRegistry.checkListenerPermission(TelephonyRegistry.java:3093)
    at com.android.server.TelephonyRegistry.listen(TelephonyRegistry.java:1024)
我在 Android Manifiest 文件上添加了以下权限,但仍然无法正常工作。
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
在低于 31 或 Android 12 之前,它运行良好。如何在 Android SDK 31 上解决这个问题?提前致谢。

最佳答案

当目标 API 31 TelephonyManager.listen给出:java.lang.SecurityException: listenTelephonyManager.registerTelephonyCallback 也是如此, 除非 ENABLE_GET_CALL_STATE_PERMISSION_PROTECTION被禁用。
开发人员选项/应用程序兼容性更改/选择应用程序/为 targetSdkVersion >= 31 启用
TelephonyManager.listen在 API 级别 31 和 TelephonyManager.registerTelephonyCallback 中已弃用在 API 级别 31 中添加,您应该编写如下代码:
更新 callStateListener 添加了示例和 phoneStateListener

    private void registerCallStateListener() {
        if (!callStateListenerRegistered) {
            TelephonyManager telephonyManager = (TelephonyManager) getSystemService(TELEPHONY_SERVICE);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
                if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED) {
                    telephonyManager.registerTelephonyCallback(getMainExecutor(), callStateListener);
                    callStateListenerRegistered = true;
                }
            } else {
                telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
                callStateListenerRegistered = true;
            }
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.S)
    private static abstract class CallStateListener extends TelephonyCallback implements TelephonyCallback.CallStateListener {
        @Override
        abstract public void onCallStateChanged(int state);
    }

    private boolean callStateListenerRegistered = false;

    private CallStateListener callStateListener = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) ?
            new CallStateListener() {
                @Override
                public void onCallStateChanged(int state) {
                    // Handle call state change
                }
            }
            : null;

    private PhoneStateListener phoneStateListener = (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) ?
            new PhoneStateListener() {
                @Override
                public void onCallStateChanged(int state, String phoneNumber) {
                    // Handle call state change
                }
            }
            : null;

文档链接:
  • TelephonyCallback.CallStateListener
  • PhoneStateListener .

  • 因为TelephonyCallback.CallStateListener需要 Manifest.permission.READ_PHONE_STATE并且此权限具有危险的保护级别,您应该按照本指南请求运行时权限:Request app permissions

    关于java - 在 targetSdkVersion 设置为 31 或 android 12 后,telephonyManager.listen 不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71285519/

    相关文章:

    java - Jasper Reports 5.0.1 中的文件解析器

    android - 加载数据而不暂停 fragment 中的 Activity

    android - OpenGL 着色器。传递 float 数组

    java - 是否有默认的 ExecutorService 或我注定要创建一个并维护它以获得 Future objetcs?

    java - Android机器不在网络上

    java - 有没有办法将数字(在我的例子中是 double )转换为java中的复数?

    Android VpnService - 如何检查 VpnService 是否已启动?

    java - Emacs:设置java模式本地的键。

    android - 将数据从 fragment 传输到 Activity - 不断返回空对象

    android - 如何使用 Jetpack 导航组件从 ViewPager 的 fragment 导航到其他 fragment ?