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

use*_*099 11 java android

我将 targetSdkVersion 升级到 31 telephonyManager.listen 不起作用。考虑以下代码行:

\n

telephonyManager.listen(phoneStateListener,PhoneStateListener.LISTEN_CALL_STATE);

\n

logcat错误信息如下:

\n
2022-02-27 13:51:36.313 6426-6426/com.example.app E/AndroidRuntime: FATAL EXCEPTION: main\nProcess: com.example.app, PID: 6426\njava.lang.RuntimeException: Unable to start service com.example.app.myPlayService@7ace64e with Intent { cmp=com.example.app/.myPlayService (has extras) }: java.lang.SecurityException: listen\n    at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:4657)\n    at android.app.ActivityThread.access$2000(ActivityThread.java:247)\n    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2091)\n    at android.os.Handler.dispatchMessage(Handler.java:106)\n    at android.os.Looper.loopOnce(Looper.java:201)\n    at android.os.Looper.loop(Looper.java:288)\n    at android.app.ActivityThread.main(ActivityThread.java:7839)\n    at java.lang.reflect.Method.invoke(Native Method)\n    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)\n    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)\n Caused by: java.lang.SecurityException: listen\n    at android.os.Parcel.createExceptionOrNull(Parcel.java:2425)\n    at android.os.Parcel.createException(Parcel.java:2409)\n    at android.os.Parcel.readException(Parcel.java:2392)\n    at android.os.Parcel.readException(Parcel.java:2334)\n    at com.android.internal.telephony.ITelephonyRegistry$Stub$Proxy.listenWithEventList(ITelephonyRegistry.java:1036)\n    at android.telephony.TelephonyRegistryManager.listenFromListener(TelephonyRegistryManager.java:250)\n    at android.telephony.TelephonyManager.listen(TelephonyManager.java:5999)\n    at com.example.app.myPlayService.onStartCommand(myPlayService.java:186)\n    at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:4639)\n    at android.app.ActivityThread.access$2000(ActivityThread.java:247)\xc2\xa0\n    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2091)\xc2\xa0\n    at android.os.Handler.dispatchMessage(Handler.java:106)\xc2\xa0\n    at android.os.Looper.loopOnce(Looper.java:201)\xc2\xa0\n    at android.os.Looper.loop(Looper.java:288)\xc2\xa0\n    at android.app.ActivityThread.main(ActivityThread.java:7839)\xc2\xa0\n    at java.lang.reflect.Method.invoke(Native Method)\xc2\xa0\n    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:548)\xc2\xa0\n    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)\xc2\xa0\n Caused by: android.os.RemoteException: Remote stack trace:\n    at com.android.internal.telephony.TelephonyPermissions.enforceCarrierPrivilege(TelephonyPermissions.java:634)\n    at com.android.internal.telephony.TelephonyPermissions.checkReadPhoneState(TelephonyPermissions.java:149)\n    at com.android.internal.telephony.TelephonyPermissions.checkCallingOrSelfReadPhoneState(TelephonyPermissions.java:94)\n    at com.android.server.TelephonyRegistry.checkListenerPermission(TelephonyRegistry.java:3093)\n    at com.android.server.TelephonyRegistry.listen(TelephonyRegistry.java:1024)\n
Run Code Online (Sandbox Code Playgroud)\n

我已在 Android Manifyst 文件上添加了以下权限,但仍然无法正常工作。

\n
<uses-permission android:name="android.permission.READ_PHONE_STATE" />\n
Run Code Online (Sandbox Code Playgroud)\n

在定位低于 31 或 Android 12 之前,它运行得很好。在Android SDK 31上如何解决这个问题?提前致谢。

\n

use*_*374 16

当目标 API 31 TelephonyManager.listen给出时:java.lang.SecurityException: listen

TelephonyManager.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;

Run Code Online (Sandbox Code Playgroud)

文档链接:

由于TelephonyCallback.CallStateListener需要Manifest.permission.READ_PHONE_STATE并且此权限的保护级别为危险,因此您应该按照本指南请求运行时权限:请求应用程序权限

  • @user1801374 但我的问题是 WhatsApp 的表现如何。在没有电话状态许可的情况下,他们正在 API 级别 31 中处理呼叫状态。我已经验证了它并且工作正常。 (3认同)

inn*_*ler 6

您在提供 LISTEN_CALL_STATE 时调用监听将触发 onCallStateChanged() 回调。

telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
Run Code Online (Sandbox Code Playgroud)

正如您在文档中看到的,如果您的目标是 Android 31 或更高版本,则 onCallStateChanged() 需要 READ_PHONE_STATE。

需要权限:针对 API 级别 31+ 的应用程序的 READ_PHONE_STATE。

请参阅: https: //developer.android.com/reference/android/telephony/PhoneStateListener#onCallStateChanged(int,%20java.lang.String)

因此,要解决此问题,只需在调用监听调用之前请求权限(但仅当代码在 Android 31+ 上执行时),如下所示:

    // for API 31+: you need to first check for READ_PHONE_STATE permission to be able to listen to LISTEN_CALL_STATE
    if (Build.VERSION.SDK_INT >= 31)
    {
        if(ContextCompat.checkSelfPermission(this, Manifest.permission.READ_PHONE_STATE) == PackageManager.PERMISSION_GRANTED)
            telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
    }
    else // no permission needed
        telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CALL_STATE);
Run Code Online (Sandbox Code Playgroud)


kin*_*ton 0

这就是我这样做的方式:

    private suspend fun updateServiceState() {
        withContext(Dispatchers.Main) {
            telephonyManager.listen(object : PhoneStateListener() {
                override fun onServiceStateChanged(state: ServiceState) {
                    telephonyManager.listen(this, LISTEN_NONE)
                    ...
                }
            }, PhoneStateListener.LISTEN_SERVICE_STATE)

        }
    }
Run Code Online (Sandbox Code Playgroud)

我的目标是 Android 12、API 31,但没有 READ_PHONE_STATE 权限