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

Cómo solicitar permisos de la app

Cada app para Android se ejecuta en una zona de pruebas con acceso limitado. Si la app necesita usar recursos o información ajenos a su propia zona de pruebas, puedes declarar un permiso y configurar una solicitud de permiso que proporcione este acceso. Estos pasos forman parte del flujo de trabajo para usar permisos.

Si declaras algún permiso riesgoso y, si tu app está instalada en un dispositivo con Android 6.0 (nivel de API 23) o una versión posterior, debes seguir los pasos de esta guía a fin de solicitar los permisos riesgosos durante el tiempo de ejecución.

Si no declaras ningún permiso riesgoso o si tu app se instala en un dispositivo con Android 5.1 (nivel de API 22) o una versión anterior, los permisos se otorgan de manera automática y no necesitas completar los demás pasos de esta página.

Principios básicos

Los principios básicos para solicitar permisos durante el tiempo de ejecución son los siguientes:

  • Solicita permisos en contexto cuando el usuario comience a interactuar con la función que lo requiere.
  • No bloquees al usuario. Proporciona siempre la opción de cancelar un flujo de IU educativo relacionado con los permisos.
  • Si el usuario rechaza o revoca un permiso que necesita una función, debes realizar una degradación elegante de tu app para que pueda seguir usándola; para ello, puedes inhabilitar la función que requiere el permiso.
  • No des por sentado ningún comportamiento del sistema. Por ejemplo, no supongas que todos los permisos aparecen en el mismo grupo de permisos. Esos grupos simplemente ayudan al sistema a minimizar la cantidad de diálogos que se presentan al usuario cuando una app solicita permisos relacionados entre sí.

Flujo de trabajo para solicitar permisos

Antes de declarar y solicitar permisos de tiempo de ejecución en tu app, evalúa si es necesario. Puedes completar muchos casos de uso en la app, como tomar fotos, pausar la reproducción de contenido multimedia y mostrar anuncios relevantes, sin declarar ningún permiso.

Si concluyes que la app necesita declarar y solicitar permisos de tiempo de ejecución, completa estos pasos:

  1. En el archivo de manifiesto de la app, declara los permisos que podría necesitar.
  2. Diseña la UX de tu app para que se asocien determinadas acciones con permisos de tiempo de ejecución específicos. Los usuarios deberían saber qué acciones pueden requerir la habilitación de un permiso para que la app acceda a sus datos privados.
  3. Espera a que el usuario invoque la tarea o acción de la app que requiere acceso a datos privados específicos. En ese momento, la app puede solicitar el permiso de tiempo de ejecución necesario para acceder a esos datos.
  4. Verifica si el usuario ya otorgó el permiso de tiempo de ejecución que requiere la app. De ser así, esta ya puede acceder a los datos privados del usuario. De lo contrario, continúa con el paso siguiente.

    Deberás comprobar si tienes ese permiso cada vez que realices una operación que lo requiera.

  5. Verifica si tu app debería mostrarle una justificación al usuario en la que se explique por qué la app necesita ese permiso durante el tiempo de ejecución. Si el sistema determina que no es necesario otorgar una justificación, continúa directamente con el siguiente paso, sin mostrar un elemento de la IU.

    En cambio, si el sistema determina que se debe proporcionar, muestra la justificación al usuario en un elemento de la IU. En ella, se debe explicar claramente a qué datos intenta acceder la app y qué beneficios puede proporcionarle al usuario si este otorga el permiso de tiempo de ejecución. Después de que el usuario acepte la justificación, continúa con el siguiente paso.

  6. Solicita el permiso de tiempo de ejecución que requiere tu app para poder acceder a los datos privados del usuario. El sistema muestra un mensaje de permiso de tiempo de ejecución, como el que se muestra en la página de resumen de permisos.

  7. Verifica la respuesta del usuario, ya sea que haya elegido otorgar o rechazar el permiso de tiempo de ejecución.

  8. Si el usuario otorgó el permiso a tu app, esta podrá acceder a sus datos privados. En cambio, si el usuario rechazó el permiso, deberás reducir la experiencia en la app de forma elegante para que siga proporcionando funcionalidad, incluso sin la información protegida por ese permiso.

En la figura 1, se ilustran el flujo de trabajo y el conjunto de decisiones asociados con este proceso:

Figura 1: Diagrama en el que se muestra el flujo de trabajo para declarar y solicitar permisos de tiempo de ejecución en Android

Determina si tu app ya recibió el permiso

Para verificar si el usuario ya otorgó un permiso en particular a tu app, pasa ese permiso al método ContextCompat.checkSelfPermission(). Este método muestra PERMISSION_GRANTED o PERMISSION_DENIED, según si tu app tiene el permiso o no.

Explica el motivo por el que la app necesita el permiso

Si el método ContextCompat.checkSelfPermission() muestra PERMISSION_DENIED, llama a shouldShowRequestPermissionRationale(). Si este método muestra true, enseña una IU educativa al usuario. En esta IU, describe por qué la función que el usuario quiere habilitar necesita un permiso en particular.

Solicita permisos

Después de que el usuario vea una IU educativa, o de que el valor que muestra shouldShowRequestPermissionRationale() indique que esta vez no necesitas mostrar una IU educativa, solicita el permiso. Los usuarios ven un diálogo de permisos del sistema en el que pueden elegir si desean otorgar un permiso en particular a tu app.

Por lo general, administras un código de solicitud como parte de la solicitud de permiso y lo incluyes en tu lógica de devolución de llamada de permiso. Otra opción es usar el contrato RequestPermission, que se incluye en una biblioteca de AndroidX, en el que permites que el sistema administre el código de solicitud de permiso por ti. Debido a que usar el contrato RequestPermission simplifica tu lógica, se recomienda que lo uses siempre que sea posible.

Permite que el sistema administre el código de solicitud de permiso

Para permitir que el sistema administre el código de solicitud asociado a una solicitud de permisos, agrega una dependencia en la siguiente biblioteca del archivo build.gradle de tu módulo.

Luego puedes usar una de las siguientes clases:

En los siguientes pasos, se muestra cómo usar el contrato RequestPermission. El proceso es casi el mismo para el contrato RequestMultiplePermissions.

  1. En la lógica de inicialización de tu actividad o fragmento, pasa una implementación de ActivityResultCallback a una llamada a registerForActivityResult(). La interfaz ActivityResultCallback define el modo en el que tu app controla la respuesta del usuario a la solicitud de permiso.

    Mantén una referencia al valor que muestra registerForActivityResult(), que es del tipo ActivityResultLauncher.

  2. Para mostrar el diálogo de permisos del sistema cuando sea necesario, llama al método launch() en la instancia de ActivityResultLauncher que guardaste en el paso anterior.

    Después de llamar a launch(), aparecerá el diálogo de permisos del sistema. Cuando el usuario toma una decisión, el sistema invoca de forma asíncrona tu implementación de ActivityResultCallback, que definiste en el paso anterior.

    Nota: Tu app no puede personalizar el diálogo que aparece cuando llamas a launch(). Si deseas proporcionar más información o contexto al usuario, cambia la IU de tu app a fin de que sea más fácil para los usuarios comprender por qué una función necesita un permiso en particular. Por ejemplo, puedes cambiar el texto del botón que habilita la función.

    Además, el texto del diálogo de permisos del sistema hace referencia al grupo de permisos asociado con el permiso que solicitaste. Esta forma de agrupar permisos está diseñada para la facilidad de uso del sistema, y tu app no debería depender de los permisos dentro o fuera de un grupo de permisos específico.

En el siguiente fragmento de código, se muestra cómo controlar la respuesta de permisos:

Kotlin

// Register the permissions callback, which handles the user's response to the
// system permissions dialog. Save the return value, an instance of
// ActivityResultLauncher. You can use either a val, as shown in this snippet,
// or a lateinit var in your onAttach() or onCreate() method.
val requestPermissionLauncher =
    registerForActivityResult(RequestPermission()
    ) { isGranted: Boolean ->
        if (isGranted) {
            // Permission is granted. Continue the action or workflow in your
            // app.
        } else {
            // Explain to the user that the feature is unavailable because the
            // features requires a permission that the user has denied. At the
            // same time, respect the user's decision. Don't link to system
            // settings in an effort to convince the user to change their
            // decision.
        }
    }

Java

// Register the permissions callback, which handles the user's response to the
// system permissions dialog. Save the return value, an instance of
// ActivityResultLauncher, as an instance variable.
private ActivityResultLauncher<String> requestPermissionLauncher =
    registerForActivityResult(new RequestPermission(), isGranted -> {
        if (isGranted) {
            // Permission is granted. Continue the action or workflow in your
            // app.
        } else {
            // Explain to the user that the feature is unavailable because the
            // features requires a permission that the user has denied. At the
            // same time, respect the user's decision. Don't link to system
            // settings in an effort to convince the user to change their
            // decision.
        }
    });

Y en este fragmento de código, se muestra el proceso recomendado para verificar un permiso y solicitar un permiso al usuario cuando sea necesario:

Kotlin

when {
    ContextCompat.checkSelfPermission(
            CONTEXT,
            Manifest.permission.REQUESTED_PERMISSION
            ) == PackageManager.PERMISSION_GRANTED -> {
        // You can use the API that requires the permission.
    }
    shouldShowRequestPermissionRationale(...) -> {
        // In an educational UI, explain to the user why your app requires this
        // permission for a specific feature to behave as expected. In this UI,
        // include a "cancel" or "no thanks" button that allows the user to
        // continue using your app without granting the permission.
        showInContextUI(...)
    }
    else -> {
        // You can directly ask for the permission.
        // The registered ActivityResultCallback gets the result of this request.
        requestPermissionLauncher.launch(
                Manifest.permission.REQUESTED_PERMISSION)
    }
}

Java

if (ContextCompat.checkSelfPermission(
        CONTEXT, Manifest.permission.REQUESTED_PERMISSION) ==
        PackageManager.PERMISSION_GRANTED) {
    // You can use the API that requires the permission.
    performAction(...);
} else if (shouldShowRequestPermissionRationale(...)) {
    // In an educational UI, explain to the user why your app requires this
    // permission for a specific feature to behave as expected. In this UI,
    // include a "cancel" or "no thanks" button that allows the user to
    // continue using your app without granting the permission.
    showInContextUI(...);
} else {
    // You can directly ask for the permission.
    // The registered ActivityResultCallback gets the result of this request.
    requestPermissionLauncher.launch(
            Manifest.permission.REQUESTED_PERMISSION);
}

Administra por tu cuenta el código de solicitud de permiso

En lugar de permitir que el sistema administre el código de solicitud de permiso, puedes administrarlo por tu cuenta como alternativa. Para hacerlo, incluye el código de solicitud en una llamada a requestPermissions().

En el siguiente fragmento de código, se muestra cómo solicitar un permiso con un código de solicitud:

Kotlin

when {
    ContextCompat.checkSelfPermission(
            CONTEXT,
            Manifest.permission.REQUESTED_PERMISSION
            ) == PackageManager.PERMISSION_GRANTED -> {
        // You can use the API that requires the permission.
        performAction(...)
    }
    shouldShowRequestPermissionRationale(...) -> {
        // In an educational UI, explain to the user why your app requires this
        // permission for a specific feature to behave as expected. In this UI,
        // include a "cancel" or "no thanks" button that allows the user to
        // continue using your app without granting the permission.
        showInContextUI(...)
    }
    else -> {
        // You can directly ask for the permission.
        requestPermissions(CONTEXT,
                arrayOf(Manifest.permission.REQUESTED_PERMISSION),
                REQUEST_CODE)
    }
}

Java

if (ContextCompat.checkSelfPermission(
        CONTEXT, Manifest.permission.REQUESTED_PERMISSION) ==
        PackageManager.PERMISSION_GRANTED) {
    // You can use the API that requires the permission.
    performAction(...);
} else if (shouldShowRequestPermissionRationale(...)) {
    // In an educational UI, explain to the user why your app requires this
    // permission for a specific feature to behave as expected. In this UI,
    // include a "cancel" or "no thanks" button that allows the user to
    // continue using your app without granting the permission.
    showInContextUI(...);
} else {
    // You can directly ask for the permission.
    requestPermissions(CONTEXT,
            new String[] { Manifest.permission.REQUESTED_PERMISSION },
            REQUEST_CODE);
}

Una vez que el usuario responde al diálogo de permisos del sistema, este invoca la implementación de onRequestPermissionsResult() de tu app. El sistema pasa la respuesta del usuario al diálogo de permisos, así como el código de solicitud que definiste, como se muestra en el siguiente fragmento de código:

Kotlin

override fun onRequestPermissionsResult(requestCode: Int,
        permissions: Array<String>, grantResults: IntArray) {
    when (requestCode) {
        PERMISSION_REQUEST_CODE -> {
            // If request is cancelled, the result arrays are empty.
            if ((grantResults.isNotEmpty() &&
                    grantResults[0] == PackageManager.PERMISSION_GRANTED)) {
                // Permission is granted. Continue the action or workflow
                // in your app.
            } else {
                // Explain to the user that the feature is unavailable because
                // the features requires a permission that the user has denied.
                // At the same time, respect the user's decision. Don't link to
                // system settings in an effort to convince the user to change
                // their decision.
            }
            return
        }

        // Add other 'when' lines to check for other
        // permissions this app might request.
        else -> {
            // Ignore all other requests.
        }
    }
}

Java

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions,
        int[] grantResults) {
    switch (requestCode) {
        case PERMISSION_REQUEST_CODE:
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0 &&
                    grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // Permission is granted. Continue the action or workflow
                // in your app.
            }  else {
                // Explain to the user that the feature is unavailable because
                // the features requires a permission that the user has denied.
                // At the same time, respect the user's decision. Don't link to
                // system settings in an effort to convince the user to change
                // their decision.
            }
            return;
        }
        // Other 'case' lines to check for other
        // permissions this app might request.
    }
}

Controla la denegación de permisos

Si el usuario rechaza una solicitud de permiso, tu app debe ayudar a los usuarios a comprender las implicaciones de esta denegación. En particular, tu app debe informar a los usuarios sobre las funciones que no se pueden usar debido a la falta de permiso. Cuando lo hagas, ten en cuenta las siguientes recomendaciones:

  • Orienta la atención del usuario. Destaca una parte específica de la IU de tu app en la que la funcionalidad sea limitada porque no tiene los permisos necesarios. Estos son algunos ejemplos de lo que puedes hacer:

    • Muestra un mensaje en el que habrían aparecido los resultados o los datos de la función.
    • Muestra un botón diferente que contenga un ícono y un color de error.
  • Brinda información específica. No muestres un mensaje genérico; en su lugar, menciona qué funciones no están disponibles porque tu app no tiene el permiso necesario.

  • No bloquees la interfaz de usuario. En otras palabras, no muestres un mensaje de advertencia de pantalla completa que impida a los usuarios seguir usando tu app.

Al mismo tiempo, la app debe respetar la decisión del usuario de denegar un permiso. A partir de Android 11 (nivel de API 30), si el usuario presiona Rechazar para un permiso específico más de una vez durante la instalación de la app en un dispositivo, no verá el diálogo de permisos del sistema si tu app solicita ese permiso nuevamente. La acción del usuario implica "no volver a preguntar". En versiones anteriores, los usuarios veían el diálogo de permisos del sistema cada vez que tu app solicitaba un permiso a menos que el usuario hubiera seleccionado una opción o casilla de verificación de "no volver a preguntar".

En algunas situaciones, se puede denegar automáticamente el permiso, sin que el usuario realice ninguna acción (de manera similar, también se puede otorgar automáticamente un permiso). Es importante no dar nada por sentado sobre el comportamiento automático. Cada vez que tu app necesite acceder a una función que requiera un permiso, deberás verificar que se le otorgue ese permiso.

Para proporcionar la mejor experiencia del usuario cuando solicitas permisos para una app, también puedes consultar las Prácticas recomendadas para solicitar permisos de apps.

Permisos únicos

La opción &quot;Solo esta vez&quot; es el segundo de los tres botones en la pantalla de diálogo.
Figura 2: Diálogo del sistema que aparece cuando una app solicita un permiso único

A partir de Android 11 (nivel de API 30), cada vez que tu app solicita un permiso relacionado con la ubicación, el micrófono o la cámara, el diálogo de permisos para el usuario contiene una opción llamada Solo esta vez, como la que se muestra en la figura 2. Si el usuario selecciona esta opción, se otorgará un permiso único temporal a la app.

Luego la app podrá acceder a los datos relacionados durante un período que dependerá del comportamiento de tu app y de las acciones del usuario:

  • Mientras su actividad sea visible, la app podrá acceder a los datos.
  • Si el usuario envía la app a segundo plano, esta podrá seguir accediendo a los datos durante un breve período.
  • Si inicias un servicio en primer plano mientras la actividad está visible y el usuario lleva la app a segundo plano, esta puede continuar accediendo a los datos hasta que se detenga ese servicio.
  • Si el usuario revoca el permiso único (por ejemplo, en la configuración del sistema), la app no podrá acceder a los datos, independientemente de si iniciaste un servicio en primer plano. Al igual que con cualquier otro permiso, si el usuario revoca el permiso único de la app, finalizará el proceso.

La próxima vez que el usuario abra tu app y una función requiera acceso a la ubicación, el micrófono o la cámara, se le solicitará nuevamente el permiso.

Permisos de restablecimiento automático de apps que no se usan

Si tu app está orientada a Android 11 (nivel de API 30) o a versiones posteriores, y no se usó durante algunos meses, el sistema restablecerá automáticamente los permisos de tiempo de ejecución sensibles que el usuario otorgó a la app a fin de proteger sus datos. Esta acción tiene el mismo efecto que si el usuario viera un permiso en la configuración del sistema y cambiara el nivel de acceso de tu app a Rechazar.

Si tu app sigue las prácticas recomendadas para solicitar permisos durante el tiempo de ejecución, no es necesario que realices ningún cambio.

Cómo solicitar al usuario que inhabilite el restablecimiento automático

Si es necesario, puedes pedirle al usuario que evite que el sistema restablezca los permisos de tu app. Esto es útil en situaciones en las que los usuarios esperan que tu app funcione principalmente en segundo plano, incluso sin interactuar con ella, como en los siguientes casos prácticos:

Figura 3: El usuario inhabilitó el restablecimiento automático de permisos para una app determinada.
  • Cuando se proporciona contenido apto para todo público.
  • Cuando se sincronizan datos.
  • Cuando te comunicas con dispositivos inteligentes.
  • Cuando te vinculas con dispositivos complementarios.

Para direccionar al usuario a la página de tu app en la configuración del sistema, invoca un intent que incluya la acción de intent Intent.ACTION_AUTO_REVOKE_PERMISSIONS. Desde esta pantalla, los usuarios pueden evitar que el sistema restablezca los permisos de tu app de la siguiente manera:

  1. Presiona la opción Permisos, que carga la pantalla de configuración Permisos de la app.
  2. Desactiva la opción Quitar los permisos si la app está en desuso, como se muestra en la figura 3.

Cómo determinar si el restablecimiento automático está inhabilitado

Para comprobar si la función de restablecimiento automático está inhabilitada, llama a isAutoRevokeWhitelisted(). Si ese método muestra true, el sistema no restablecerá automáticamente los permisos de tu app.

Solicita convertirte en el controlador predeterminado si es necesario

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.

A fin de obtener más información sobre los controladores predeterminados, así como orientación para mostrar una solicitud de estos a los usuarios, consulta la guía sobre permisos que se usan solo en controladores predeterminados.

Prueba los permisos de tiempo de ejecución

En esta sección, se describe cómo probar varios aspectos de los permisos de tiempo de ejecución.

Otorga todos los permisos de tiempo de ejecución

Para otorgar todos los permisos de tiempo de ejecución automáticamente cuando instalas una app en un emulador o dispositivo de prueba, usa la opción -g para el comando adb shell install, como se muestra en el siguiente fragmento de código:

adb shell install -g PATH_TO_APK_FILE

Cómo realizar un restablecimiento automático de los permisos de tu app

A fin de verificar si el sistema restablece los permisos de tu app, haz lo siguiente:

  1. Registra el tiempo predeterminado que el sistema espera para restablecer los permisos de una app. De esa manera, puedes restablecerla después de realizar las pruebas:

    threshold=$(adb shell device_config get permissions \
      auto_revoke_unused_threshold_millis2)
    
  2. Reduce el tiempo que el sistema espera para restablecer los permisos. En el siguiente ejemplo, se modifica el sistema de manera que restablezca los permisos de una app solo un segundo después de que dejas de interactuar con ella:

    adb shell device_config put permissions \
      auto_revoke_unused_threshold_millis2 1000
    
  3. Invoca el proceso de restablecimiento automático de forma manual, como se muestra en el siguiente fragmento. Antes de ejecutar este comando, asegúrate de que se haya activado durante unos 45 segundos el dispositivo de prueba.

    adb shell cmd jobscheduler run -u 0 -f \
      com.google.android.permissioncontroller 2
    
  4. Verifica que tu app pueda controlar el evento de restablecimiento automático.

  5. Restablece el tiempo predeterminado que espera el sistema antes de restablecer automáticamente los permisos de una app:

    adb shell device_config put permissions \
      auto_revoke_unused_threshold_millis2 $threshold
    

Recursos adicionales

Para obtener información adicional sobre permisos, consulta los siguientes artículos:

Para descubrir cómo solicitar permisos, descarga las siguientes apps de ejemplo:

  • Ejemplo de RuntimePermissionsBasic de Android Java | Kotlin