Google se compromete a impulsar la igualdad racial para las comunidades afrodescendientes. Obtén información al respecto.

Prácticas recomendadas sobre permisos de apps

Las solicitudes de permisos protegen la información confidencial disponible en un dispositivo y solo deben usarse cuando el acceso a la información es necesario para el funcionamiento de tu app. En este documento, se brindan sugerencias sobre las formas en que podría lograr la misma (o mejor) funcionalidad sin necesidad de acceder a esa información. No es un análisis exhaustivo sobre cómo funcionan los permisos en el sistema operativo Android.

Para obtener un panorama general sobre los permisos de Android, consulta la Descripción general de permisos. Para obtener información sobre cómo trabajar con permisos en tu código, consulta Cómo solicitar permisos de la app.

Principios básicos del trabajo con permisos de Android

Te recomendamos que sigas estos principios básicos cuando trabajes con permisos de Android:

N.º 1: solo usa los permisos necesarios para el funcionamiento de tu app. Según la forma en que uses los permisos, puede haber otra alternativa para hacer lo que necesitas (intents de sistema, identificadores, colocación de llamadas telefónicas en segundo plano) sin depender del acceso a información sensible.

N.º 2: presta atención a los permisos que se requieren para las bibliotecas. Cuando incluyes una biblioteca, también heredas sus requisitos de permisos. Debes tener noción de lo que incluirás, los permisos que se requieren y cuál es su propósito.

N.º 3: sé transparente. Cuando solicites permisos, sé claro con respecto a la información a la que accedes y la razón por la que lo haces, de manera que los usuarios puedan tomar decisiones fundamentadas. Haz que la información esté disponible junto con la solicitud de permiso que incluya los diálogos correspondientes durante la instalación, el tiempo de ejecución o la actualización.

N.º 4: crea accesos explícitos al sistema. Si les indicas continuamente cuando accedes a funciones sensibles (como la cámara o el micrófono), los usuarios verán con claridad los momentos en los que recopiles datos. De esta forma, evitarás la percepción de que lo haces de forma clandestina.

En las secciones restantes de esta guía, se abordan estas reglas con mayor profundidad en el contexto del desarrollo de apps para Android.

Permisos en Android 6.0 y versiones posteriores

Android 6.0 Marshmallow incorporó un nuevo modelo de permisos mediante el cual las apps pueden solicitar permisos a los usuarios durante el tiempo de ejecución, y no antes de la instalación. Las apps que admiten el nuevo modelo solicitan permisos cuando se necesitan los servicios o los datos que estos protegen. Si bien esto no cambia (necesariamente) el comportamiento general de las apps, introduce algunas modificaciones relevantes en la manera en que se manejan los datos sensibles del usuario.

Mayor contexto circunstancial: en el contexto de tu app, se solicita permiso a los usuarios durante el tiempo de ejecución para acceder a las funcionalidades que abarcan esos grupos de permisos. Los usuarios son más sensibles al contexto en el que se solicita el permiso y, si lo que solicitas no coincide con el propósito de tu app, es incluso más importante proporcionarles una explicación detallada del motivo por el cual necesitas el permiso. Siempre que sea posible, debes proporcionar una explicación de la solicitud, tanto cuando la realizas como en un diálogo de seguimiento (si el usuario la rechaza).

Mayor flexibilidad para otorgar permisos: los usuarios pueden denegar el acceso a los permisos individuales en el momento en que se solicitan y en la configuración. Aún así, pueden sorprenderse cuando falla la funcionalidad como resultado de esto. Te recomendamos que controles la cantidad de usuarios que deniegan permisos (p. ej., mediante Google Analytics), de manera que puedas refactorizar tu app para evitar depender de ese permiso o proporcionar una mejor explicación del motivo por el cual lo necesitas para que tu app funcione correctamente. También debes asegurarte de que este maneje excepciones creadas cuando los usuarios rechacen solicitudes de permisos o los desactiven en la configuración.

Mayor carga de transacciones: se solicitará a los usuarios que otorguen acceso a grupos de permisos de manera individual y no en conjunto. Esta acción hace que minimizar la cantidad de permisos que solicitas sea sumamente importante, ya que aumenta la carga de otorgamiento de permisos para el usuario y la probabilidad de que se rechace al menos una de las solicitudes.

Permisos que requieren que te conviertas en un controlador predeterminado

Algunas apps dependen del acceso a la información sensible del usuario que se relaciona con sus registros de llamadas y mensajes SMS. Si quieres solicitar los permisos específicos para registros de llamadas y mensajes SMS, y publicar tu app en Play Store, debes solicitar al usuario que configure tu app como controlador predeterminado para una función principal del sistema antes de solicitar estos permisos de tiempo de ejecución.

Para obtener más información sobre los controladores predeterminados, incluidos lineamientos sobre cómo enviar solicitudes de estos a los usuarios, consulta la guía sobre permisos que se usan solo en controladores predeterminados.

Evita solicitar permisos innecesarios

Cada vez que solicitas un permiso, obligas al usuario a tomar una decisión. Debes reducir al mínimo la cantidad de veces que realizas estas solicitudes. Si el dispositivo del usuario ejecuta Android 6.0 (API nivel 23) o una versión posterior, cada vez que pruebe una función nueva de la app que requiera un permiso, la app deberá interrumpir el trabajo del usuario con una solicitud de permiso. Si ejecuta una versión anterior de Android, deberá otorgar todos los permisos de la app al instalarla. Si la lista es muy extensa o parece inapropiada, es posible que el usuario decida no instalar tu app. Por esos motivos, debes reducir al mínimo la cantidad de permisos que necesita tu app.

En esta sección, se ofrecen alternativas para casos prácticos comunes que te ayudarán a limitar la cantidad de solicitudes de permisos que realices. Como la cantidad y el tipo de permisos solicitados al usuario afectan las descargas, en comparación con otras apps similares que solicitan menos permisos, te recomendamos evitar pedirlos para funcionalidades innecesarias.

Mejor usa un intent

En muchos casos, puedes elegir entre dos formas para que tu app realice una tarea. Puede solicitar permiso para realizar una tarea por sí misma, o bien usar un intent y asignársela a otra app.

Por ejemplo, supongamos que tu app necesita tomar fotos con la cámara del dispositivo. Entonces, puede solicitar el permiso CAMERA, que le permitirá acceder directamente a la cámara. De esta manera, la app usará las API de la cámara para controlarla y tomar una foto. Este enfoque le otorga a tu app el control total del proceso de fotografía, y te permite incorporar la IU de la cámara a la aplicación.

Sin embargo, si la solicitud de acceso a los datos del usuario es poco frecuente (es decir, si al usuario no le molesta que aparezca un diálogo durante el tiempo de ejecución cada vez que necesites acceder a los datos), puedes usar una solicitud basada en intents. Android proporciona algunos intents del sistema que las aplicaciones pueden usar sin solicitar permisos, ya que el usuario elige, en todo caso, qué quiere compartir con la app cuando se emite la solicitud basada en intents.

Por ejemplo, se puede usar un tipo de acción de intent MediaStore.ACTION_IMAGE_CAPTURE o MediaStore.ACTION_VIDEO_CAPTURE para capturar imágenes o videos sin usar directamente el objeto Cámara (y sin solicitar el permiso). En ese caso, el intent del sistema solicitará permiso al usuario en nombre tuyo cada vez que se capture una imagen.

De manera similar, si necesitas realizar una llamada telefónica o acceder a los contactos del usuario, entre otras acciones, puedes crear un intent apropiado o bien solicitar el permiso y acceder directamente a los objetos correspondientes. Ambos enfoques tienen ventajas y desventajas.

Si usas permisos, sucede lo siguiente:

  • Tu app controla por completo la experiencia del usuario cuando realizas la operación. Sin embargo, un control tan amplio sumará complejidad a tu código, ya que deberás diseñar una IU acorde.
  • Se solicita permiso al usuario una sola vez, ya sea durante el tiempo de ejecución o la instalación (según la versión de Android que ejecute). Luego, tu app podrá realizar la operación sin requerir interacción adicional por parte del usuario. Pero, si este no otorga el permiso (o lo revoca más adelante), la app ya no podrá realizar la operación.

Si usas un intent, sucede lo siguiente:

  • No debes diseñar la IU para la operación. La app que controla el intent proporciona la IU.
  • El usuario puede usar la app que prefiera para realizar la tarea. Por ejemplo, puede seleccionar su app de fotografía favorita para tomar una foto.
  • Si el usuario no tiene una aplicación predeterminada para la operación, el sistema le solicitará que elija una. Si el usuario no designa un controlador predeterminado, es probable que se muestre un diálogo adicional cada vez que realice la operación.

No abrumes al usuario

Si el dispositivo del usuario ejecuta Android 6.0 (API nivel 23) o una versión posterior, deberá otorgarle permisos a la app cuando la abra. Si envías al usuario muchas solicitudes de permisos a la vez, podrías abrumarlo y hacer que cierre la app. En su lugar, deberías pedir permisos cuando los necesites.

En algunos casos, es probable que uno o más permisos sean absolutamente esenciales para la app. Quizá convenga solicitar todos esos permisos apenas se inicia la app. Por ejemplo, si creas una app de fotografía, requerirá acceso a la cámara del dispositivo. Por lo tanto, cuando el usuario inicie la app por primera vez, no se sorprenderá si se le solicita permiso para usar la cámara. Sin embargo, si la app tiene además una función para compartir fotos con los contactos del usuario, no deberías solicitar el permiso READ_CONTACTS la primera vez que se inicia la app. En su lugar, espera a que el usuario intente utilizar esta función para solicitarlo.

Si tu app incluye un instructivo, te recomendamos solicitar los permisos esenciales cuando finalice la secuencia del tutorial.

Detén el contenido cuando se pierda el foco de audio

En este caso, la app debe ejecutarse en segundo plano cuando el usuario recibe una llamada telefónica, y volver a primer plano cuando esta finalice.

El enfoque común en estos casos (por ejemplo, cuando el reproductor multimedia se pone en silencio o pausa la reproducción durante una llamada telefónica) consiste en detectar los cambios en el estado de la llamada mediante PhoneStateListener o utilizar un objeto de escucha para la transmisión de android.intent.action.PHONE_STATE. El problema de esta solución es que requiere el permiso de READ_PHONE_STATE. Esto obliga al usuario a otorgar acceso a una amplia variedad de secciones de datos sensibles, como los ID del dispositivo y del hardware de SIM, además del número de teléfono de la llamada entrante. Además, los eventos LISTEN_CELL_LOCATION y LISTEN_CELL_INFO requieren un permiso de ubicación cuando una app se ejecuta en Android 10 (API nivel 29) o versiones posteriores (específicamente ACCESS_FINE_LOCATION, si la app está orientada a Android 10 o versiones posteriores).

Puedes detectar si un usuario está en una llamada telefónica sin los permisos READ_PHONE_STATE o MODIFY_PHONE_STATE si solicitas AudioFocus para tu app, que no requiere permisos explícitos (porque no accede a información confidencial). Simplemente inserta el código necesario para colocar en segundo plano tu audio en el controlador de eventos onAudioFocusChange(); se ejecutará de forma automática cuando cambie el foco de audio del SO. Puedes encontrar documentación más detallada sobre cómo hacerlo aquí.

Determina el dispositivo en el que se ejecuta tu instancia

En este caso, necesitas un identificador único para determinar en qué dispositivo se está ejecutando la instancia de tu app.

Las apps pueden tener preferencias o mensajería específicas por dispositivo (p. ej., guardar en la nube una lista de reproducción específica del dispositivo de un usuario, de manera que pueda tener varias para su vehículo y en el hogar). Una solución común es aprovechar los identificadores de dispositivos como Device IMEI, pero esto requiere el grupo de permisos Device ID and call information (PHONE en M+). También utiliza un identificador que no se puede restablecer, y que comparten todas las aplicaciones.

Hay dos alternativas para usar estos tipos de identificadores:

  1. Usar la API de InstanceID com.google.android.gms.iid. getInstance(Context context).getID() mostrará un identificador de dispositivo único para la instancia de tu aplicación. Como resultado, se obtiene un identificador limitado a las instancias de la app, que se puede usar como clave al almacenar información sobre la app, y se restablece si el usuario vuelve a instalarla.
  2. Crea tu propio identificador limitado al almacenamiento de tu app usando funciones básicas del sistema, como randomUUID().

Crea un identificador único para publicidad o estadísticas del usuario

En este caso, necesitas un identificador único a fin de crear un perfil para los usuarios que no accedieron a tu app (p. ej. para la orientación de anuncios o la medición de conversiones).

Crear un perfil para publicidad y estadísticas de usuarios puede requerir un identificador compartido con otras aplicaciones. Entre las soluciones comunes para esto, se incluyen el uso de identificadores del dispositivo como Device IMEI, que requieren el grupo de permisos Device ID and call information (PHONE en el nivel de API 23 y versiones posteriores) y que el usuario no puede restablecer. En cualquiera de estos casos, además de usar un identificador que no se puede restablecer y solicitar un permiso que pueda parecer extraño a los usuarios, también infringirás las Políticas del programa para desarrolladores de Google Play.

Lamentablemente, en estos casos, usar la API de InstanceID com.google.android.gms.iid o funciones del sistema para crear un ID limitado a la app no es una solución adecuada, ya que podría ser necesario compartir el ID con diferentes apps. Una solución alternativa es usar el Advertising Identifier disponible en la clase AdvertisingIdClient.Info a través del método getId(). Puedes crear un objeto AdvertisingIdClient.Info con el método getAdvertisingIdInfo(Context) y llamar al método getId() para usar el identificador. Ten en cuenta que este método es de bloqueo, por lo que no debes llamarlo desde el subproceso principal. Puedes encontrar una explicación detallada de este método aquí.

Conoce las bibliotecas con las que trabajas

En ocasiones, las bibliotecas que usas en tu app requieren permisos. Por ejemplo, las bibliotecas de anuncios y estadísticas pueden requerir acceso al grupo de permisos LOCATION para implementar la funcionalidad requerida. Sin embargo, desde la perspectiva del usuario, la solicitud de permiso proviene de tu app, y no de la biblioteca.

Así como los usuarios seleccionan apps que usan menos permisos para la misma funcionalidad, los desarrolladores deben revisar sus bibliotecas y seleccionar SDK de terceros que no soliciten permisos innecesarios. Por ejemplo, si usas una biblioteca que proporciona la funcionalidad de ubicación, asegúrate de no solicitar el permiso FINE_LOCATION, a menos que estés usando la funcionalidad de orientación basada en la ubicación.

Limita el acceso en segundo plano a la ubicación

Cuando se ejecuta tu app en segundo plano, el acceso a la ubicación debe ser fundamental para la funcionalidad principal de la app y mostrar un beneficio claro a los usuarios.

Explica por qué se necesitan los permisos

En el diálogo de permisos que muestra el sistema cuando llamas a requestPermissions(), se indican los permisos que necesita tu app, pero no se indica el motivo. A veces, esto puede confundir al usuario. Se recomienda explicarle los motivos por los cuales tu app necesita esos permisos antes de llamar a requestPermissions().

Según estudios, los usuarios se sienten más cómodos con las solicitudes de permisos si saben para qué los necesita la app. Un estudio de usuarios mostró lo siguiente:

[…] La disposición de un usuario para otorgar cierto permiso a una app determinada se ve notablemente afectada por el propósito asociado con ese permiso. Por ejemplo, la disposición de un usuario a otorgar acceso a su ubicación variará en función de si la solicitud se realiza para admitir la funcionalidad principal de la app o para compartir esa información con una red de publicidad o una empresa de análisis estadísticos.1

Conforme a la investigación de su grupo, el profesor Jason Hong de la CMU llegó a la siguiente conclusión:

[…] Cuando las personas saben por qué una app usa información sensible como su ubicación (por ejemplo, para publicidad orientada), se sienten más cómodas que cuando se les dice simplemente que la app utiliza los servicios de ubicación.1

En consecuencia, si solo usas una fracción de las llamadas de la API que pertenecen a un grupo de permisos, te será más fácil indicar explícitamente los permisos que usas y por qué. Por ejemplo:

  • Si solo usas la ubicación aproximada, infórmalo al usuario en la descripción de tu app o los artículos de ayuda.
  • Si necesitas acceso a los mensajes SMS para recibir códigos de autenticación que protegen al usuario contra actividades fraudulentas, infórmaselo en la descripción de tu app o la primera vez que accedas a los datos.

    Nota: Si la app se orienta a dispositivos que ejecutan Android 8.0 (API nivel 26) o versiones posteriores, no solicites el permiso READ_SMS como parte de la verificación de las credenciales del usuario. En su lugar, genera un token específico de la app con createAppSpecificSmsToken() y, luego, pásalo a otra app o servicio que pueda enviar un mensaje de verificación por SMS.

En ciertos casos, resulta favorable informar a los usuarios respecto del acceso a datos sensibles en tiempo real. Por ejemplo, si accedes a la cámara o al micrófono, se recomienda que se lo informes al usuario con un ícono de notificación en algún sector de tu app, o bien en la bandeja de notificaciones (si la app se ejecuta en segundo plano), de manera que no parezca que recopilas datos de forma clandestina.

Por último, si tienes que solicitar un permiso para realizar alguna tarea en tu app, pero el motivo no está claro para el usuario, busca una manera de informarle por qué necesitas los permisos más sensibles.

Prueba ambos modelos de permisos

A partir de Android 6.0 (API nivel 23), los usuarios otorgan y revocan permisos de apps durante el tiempo de ejecución, en lugar de hacerlo cuando instalan la app. Como resultado, tendrás que probar tu app en una variedad más amplia de condiciones. Antes de Android 6.0, podías suponer razonablemente que, si tu app estaba ejecutándose, significaba que tenía todos los permisos declarados en su manifiesto. A partir de Android 6.0, el usuario puede activar o desactivar los permisos de cualquier app, incluso una que se oriente al nivel de API 22 o inferior. Deberías realizar una prueba para asegurarte de que tu app funcione de manera correcta, independientemente de si cuenta o no con los permisos.

Las siguientes sugerencias te ayudarán a encontrar los problemas de código relacionados con los permisos en los dispositivos que ejecutan API nivel 23 o posterior:

  • Identifica los permisos actuales de tu app y las rutas de acceso de códigos relacionadas.
  • Prueba los flujos del usuario en los datos y servicios protegidos por permisos.
  • Prueba con varias combinaciones de permisos otorgados o revocados. Por ejemplo, en el manifiesto de una app de cámara, podrían indicarse CAMERA, READ_CONTACTS, ACCESS_FINE_LOCATION. Debes probar la app con cada uno de esos permisos activados y desactivados, para asegurarte de que la app pueda controlar todas las configuraciones de permisos sin inconvenientes.
  • Usa la herramienta de adb para administrar los permisos desde la línea de comandos:
    • Enumera los permisos y estados por grupo:
      $ adb shell pm list permissions -d -g
    • Otorga o revoca uno o más permisos:
      $ adb shell pm [grant|revoke] <permission-name> ...
  • Analiza tu app en busca de servicios que usen permisos.

Recursos adicionales

Referencias

[1] Modeling Users’ Mobile App Privacy Preferences: Restoring Usability in a Sea of Permission Settings, por J. Lin B. Liu, N. Sadeh y J. Hong. En actas de SOUPS 2014.