'telephonyManager.listen not working after targetSdkVersion is set to 31 or android 12
After i upgrade the targetSdkVersion to 31 telephonyManager.listen is not working. Consider following line of code:
telephonyManager.listen(phoneStateListener,PhoneStateListener.LISTEN_CALL_STATE);
The logcat error message is as given below:
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)
I have added following permission on the Android Manifiest file but still not working.
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
Before targeting below 31 or Android 12 it was working perfectly. How to solve this problem on Android SDK 31 ? Thanks in advance.
Solution 1:[1]
When target API 31 TelephonyManager.listen gives: java.lang.SecurityException: listen
So does TelephonyManager.registerTelephonyCallback, Except when ENABLE_GET_CALL_STATE_PERMISSION_PROTECTION is disabled.
Developer Options / App Compatibility Changes / Select Application / Enabled for targetSdkVersion >= 31
Since TelephonyManager.listen is deprecated in API level 31 and TelephonyManager.registerTelephonyCallback is added in API level 31, you should make code like this:
UPDATE added examples for callStateListener
and 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;
Links to documentation:
Because TelephonyCallback.CallStateListener requires Manifest.permission.READ_PHONE_STATE and this permission has protection level dangerous, you should ask for run time permissions following this guide: Request app permissions
Solution 2:[2]
this is the way I'm doing it:
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)
}
}
I'm targeting Android 12, API 31 and I don't have the READ_PHONE_STATE permission
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | kingston |