Seguridad

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 (consulte TelephonyManager#hasCarrierPrivileges).
Requerido Manifest.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.

LEER  Revisión de desafío de código: lo que prefieren la mayoría de los revisores | Ben Daniel A. | noviembre de 2021

Publicaciones relacionadas

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Botón volver arriba