SecurityException: SubscriptionManager – Pero declaré los permisos
¡Oh mi! ¡Este es uno de esos momentos con Android en los que te golpeas la frente como qué!
Esta es la documentación oficial para usar SubscriptionManager.addOnSubscriptionChangedListener
Regístrese para cambios en la lista activa
SubscriptionInfo
Registros o en las grabaciones individuales. Cuando ocurre un cambio, el método onSubscriptionsChanged del oyente se llama inmediatamente si hay una notificación. El método onSubscriptionChanged también se activa una vez cuando se llama a esta función.https://developer.android.com/reference/android/telephony/SubscriptionManager#addOnSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnSubscriptionsChangedListener)
No afirma que se requieran permisos de Android. Sin embargo, para cuando esté leyendo esto, es probable que haya visto el mismo seguimiento de pila que yo en sus informes de Crashlytics o PlayStore.
java.lang.RuntimeException:
at android.app.ActivityThread.handleBindApplication (ActivityThread.java:6654)
at android.app.ActivityThread.-wrap2 (Unknown Source)
at android.app.ActivityThread$H.handleMessage (ActivityThread.java:2084)
at android.os.Handler.dispatchMessage (Handler.java:109)
at android.os.Looper.loop (Looper.java:166)
at android.app.ActivityThread.main (ActivityThread.java:7555)
at java.lang.reflect.Method.invoke (Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run (RuntimeInit.java:469)
at com.android.internal.os.ZygoteInit.main (ZygoteInit.java:963)
Caused by: java.lang.SecurityException:
at android.os.Parcel.readException (Parcel.java:2016)
at android.os.Parcel.readException (Parcel.java:1962)
at com.android.internal.telephony.ITelephonyRegistry$Stub$Proxy.addOnSubscriptionsChangedListener (ITelephonyRegistry.java:491)
at android.telephony.SubscriptionManager.addOnSubscriptionsChangedListener (SubscriptionManager.java:518)
Hmmm que pasa! Bueno, resulta que la devolución de llamada se describe de la siguiente manera:
Una clase de escucha que se usa para monitorear los cambios en los registros SubscriptionInfo.
Pero en realidad no te da eso SubscriptionInfo
Objeto. Sin embargo, otro método funciona: getActiveSubscriptionInfo
https://developer.android.com/reference/android/telephony/SubscriptionManager#getActiveSubscriptionInfo(int)
Y mira, este método requiere permiso de Android:
Llame al SubscriptionInfo activo con el Sub-ID de entrada.
Requiere permiso:
READ_PHONE_STATE
o que la aplicación de llamadas tiene derechos de operador de red (consulteTelephonyManager#hasCarrierPrivileges
).
RequeridoManifest.permission.READ_PHONE_STATE
https://developer.android.com/reference/android/telephony/SubscriptionManager#getActiveSubscriptionInfo(int)
La primera conclusión a la que llegué fue que Huawei (y los proveedores que también venden la versión AOSP) han modificado ligeramente su implementación y este oyente necesita permiso.
Lo he visto antes, es absolutamente posible, pero ¿vamos en 2020? de ninguna manera. Entonces, con un poco más de investigación y lectura de los documentos del Por supuesto Oyente, ¡lo encontré!
Los permisos android.Manifest.permission.READ_PHONE_STATE son necesarios para poder llamar a #onSubscriptionsChanged.
https://developer.android.com/reference/android/telephony/SubscriptionManager.OnSubscriptionsChangedListener
No necesita permiso de seguridad para agregar un oyente modificado. pero necesitas permiso para que se llame a su oyente. Ese es el problema.
Nos encontramos con esto porque configuramos el oyente al iniciar la aplicación, pero no pedimos permiso hasta que se requirió la función (Mejor práctica de UX). La solución práctica que tuvimos que elegir fue buscar permiso al iniciar la aplicación o mover al oyente para que comience a escuchar solo cuando el usuario dio permiso.
¡Feliz Androiding! Y recuerda siempre RTFM.