Solicita permisos de tiempo de ejecución

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 de tiempo de ejecución 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 para 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 un permiso 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, como un flujo que explica los motivos para solicitar 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. Permite que los usuarios sepan 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é 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, si eligió otorgar o denegar 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, 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

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

Algunas investigaciones muestran que los usuarios se sienten más cómodos con las solicitudes de permisos si saben para qué los necesita la app, por ejemplo, si el permiso se necesita con el fin de admitir una función principal de la app o con fines publicitarios. En consecuencia, si solo usas una fracción de las llamadas a 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.

En ciertos casos, resulta útil 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 en la bandeja de notificaciones (si la aplicación se ejecuta en segundo plano), de manera que no parezca que recopilas datos de forma clandestina.

Por último, si tienes que solicitar un permiso a fin de 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.

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.

Además, si tu app solicita un permiso relacionado con la ubicación, el micrófono o la cámara, procura explicar por qué tu app necesita acceso a esa información.

Solicita permisos

Después de que el usuario vea una IU educativa, o de que el valor que muestra shouldShowRequestPermissionRationale() indique que 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.

Para ello, usa 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, es la solución recomendada siempre que sea posible. Sin embargo, si es necesario, también puedes administrar un código de solicitud como parte de la solicitud de permiso e incluirlo en la lógica de devolución de llamada de permiso.

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
            // feature 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
            // feature 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.
    }
    ActivityCompat.shouldShowRequestPermissionRationale(
            this, Manifest.permission.REQUESTED_PERMISSION) -> {
        // In an educational UI, explain to the user why your app requires this
        // permission for a specific feature to behave as expected, and what
        // features are disabled if it's declined. In this UI, include a
        // "cancel" or "no thanks" button that lets the user 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 (ActivityCompat.shouldShowRequestPermissionRationale(
        this, Manifest.permission.REQUESTED_PERMISSION)) {
    // In an educational UI, explain to the user why your app requires this
    // permission for a specific feature to behave as expected, and what
    // features are disabled if it's declined. In this UI, include a
    // "cancel" or "no thanks" button that lets the user 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(...)
    }
    ActivityCompat.shouldShowRequestPermissionRationale(
            this, Manifest.permission.REQUESTED_PERMISSION) -> {
        // In an educational UI, explain to the user why your app requires this
        // permission for a specific feature to behave as expected, and what
        // features are disabled if it's declined. In this UI, include a
        // "cancel" or "no thanks" button that lets the user 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 (ActivityCompat.shouldShowRequestPermissionRationale(
        this, Manifest.permission.REQUESTED_PERMISSION)) {
    // In an educational UI, explain to the user why your app requires this
    // permission for a specific feature to behave as expected, and what
    // features are disabled if it's declined. In this UI, include a
    // "cancel" or "no thanks" button that lets the user 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 feature 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 feature 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.
    }
}

Solicita permisos de ubicación

Cuando solicites permisos de ubicación, sigue las mismas prácticas recomendadas para cualquier otro permiso de tiempo de ejecución. Una diferencia importante cuando se trata de permisos de ubicación es que el sistema incluye varios permisos relacionados con la ubicación. Los permisos que solicites y el modo en que los solicites dependerán de los requisitos de ubicación del caso de uso de tu app.

Ubicación en primer plano

Si tu app contiene una función que comparte o recibe información de ubicación solo una vez o durante un tiempo definido, esa función requiere acceso a la ubicación en primer plano. Estos son algunos ejemplos:

  • Dentro de una app de navegación, una función permite a los usuarios obtener instrucciones paso a paso.
  • Dentro de una app de mensajería, una función permite a los usuarios compartir su ubicación actual con otro usuario.

El sistema considera que tu app usa la ubicación en primer plano si una función accede a la ubicación actual del dispositivo en una de las siguientes situaciones:

  • Una actividad que pertenece a tu app es visible.
  • Tu app ejecuta un servicio en primer plano. Cuando se ejecuta un servicio en primer plano, el sistema muestra una notificación persistente para atraer la atención del usuario. Tu app conserva el acceso cuando se coloca en segundo plano, por ejemplo, cuando el usuario presiona el botón Inicio en su dispositivo o apaga la pantalla.

    En Android 10 (nivel de API 29) y versiones posteriores, debes declarar un tipo de servicio en primer plano de location, como se muestra en el siguiente fragmento de código. En versiones anteriores de Android, se recomienda que declares este tipo de servicio en primer plano.

    <!-- Recommended for Android 9 (API level 28) and lower. -->
    <!-- Required for Android 10 (API level 29) and higher. -->
    <service
        android:name="MyNavigationService"
        android:foregroundServiceType="location" ... >
        <!-- Any inner elements go here. -->
    </service>
    

Declara la necesidad de una ubicación en primer plano cuando tu app solicite el permiso ACCESS_COARSE_LOCATION o el permiso ACCESS_FINE_LOCATION, como se muestra en el siguiente fragmento:

<manifest ... >
  <!-- Include this permission any time your app needs location information. -->
  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

  <!-- Include only if your app benefits from precise location access. -->
  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
</manifest>

Ubicación en segundo plano

Una app requiere acceso a la ubicación en segundo plano si una función dentro de la app comparte constantemente la ubicación con otros usuarios o usa la API de geovallado. Entre los ejemplos, se incluyen los siguientes:

  • Dentro de una app familiar para compartir la ubicación, una función permite que los usuarios compartan la ubicación de forma continua con los miembros de la familia.
  • Dentro de una app de IoT, una función permite al usuario configurar sus dispositivos de la casa, de modo que se apaguen cuando el usuario salga de su casa y se vuelvan a activar cuando regrese.

El sistema considera que tu app usa la ubicación en segundo plano si accede a la ubicación actual del dispositivo en una situación diferente de la descrita en la sección Ubicación en primer plano. La exactitud de la ubicación en segundo plano es la misma que la exactitud de la ubicación en primer plano, que depende de los permisos de ubicación que declare tu app.

En Android 10 (nivel de API 29) y versiones posteriores, debes declarar el permiso ACCESS_BACKGROUND_LOCATION en el manifiesto de tu app para solicitar acceso a la ubicación en segundo plano durante el tiempo de ejecución. En las versiones anteriores de Android, cuando tu app recibe acceso a la ubicación en primer plano, también recibe automáticamente acceso a la ubicación en segundo plano.

<manifest ... >
  <!-- Required only when requesting background location access on
       Android 10 (API level 29) and higher. -->
  <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
</manifest>

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 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, aclara 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 hubieran seleccionado una opción o casilla de verificación de "no volver a preguntar".

Si un usuario deniega una solicitud de permiso más de una vez, se considerará una denegación permanente. Es muy importante solicitarles permisos a los usuarios solo cuando necesitan acceso a una función específica. De lo contrario, podrías perder, de forma inadvertida, la capacidad de volver a solicitar permisos.

En algunas situaciones, se puede denegar automáticamente el permiso, sin que el usuario realice ninguna acción (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, verifica que se le otorgue ese permiso.

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

Inspecciona el estado de denegación durante las pruebas y la depuración

Para identificar si una app tiene permisos denegados de manera permanente (con fines de depuración y prueba), usa el siguiente comando:

adb shell dumpsys package PACKAGE_NAME

Donde PACKAGE_NAME es el nombre del paquete que se inspeccionará.

El resultado del comando contiene secciones que se ven de la siguiente manera:

...
runtime permissions:
  android.permission.POST_NOTIFICATIONS: granted=false, flags=[ USER_SENSITIVE_WHEN_GRANTED|USER_SENSITIVE_WHEN_DENIED]
  android.permission.ACCESS_FINE_LOCATION: granted=false, flags=[ USER_SET|USER_FIXED|USER_SENSITIVE_WHEN_GRANTED|USER_SENSITIVE_WHEN_DENIED]
  android.permission.BLUETOOTH_CONNECT: granted=false, flags=[ USER_SENSITIVE_WHEN_GRANTED|USER_SENSITIVE_WHEN_DENIED]
...

USER_SET marca los permisos que el usuario rechazó. USER_FIXED marca los permisos que se rechazaron de forma permanente cuando se selecciona Rechazar dos veces.

Para asegurarte de que los verificadores vean el diálogo de la solicitud durante la prueba, restablece estas marcas cuando termines de depurar la app. Para ello, usa el siguiente comando:

adb shell pm clear-permission-flags PACKAGE_NAME PERMISSION_NAME user-set user-fixed

PERMISSION_NAME es el nombre del permiso que deseas restablecer.

Para ver una lista completa de los permisos de la app para Android, visita la página de referencia de la API de permisos.

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 le 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.

El proceso de la app finaliza cuando se revoca el permiso

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.

Restablece permisos sin usar

Android proporciona varias formas de restablecer los permisos de tiempo de ejecución sin usar a su estado predeterminado y denegado, como las siguientes:

Cómo quitar el acceso de la app

En Android 13 (nivel de API 33) y versiones posteriores, puedes quitar el acceso de tu app a los permisos de tiempo de ejecución que ya no requiere. Cuando actualices la app, realiza este paso para que los usuarios tengan más probabilidades de entender los motivos por los que se solicitan permisos específicos. Este conocimiento ayuda a generar confianza entre los usuarios en tu app.

Para quitar el acceso a un permiso de tiempo de ejecución, pasa el nombre de ese permiso a revokeSelfPermissionOnKill(). Para quitar el acceso a un grupo de permisos de tiempo de ejecución al mismo tiempo, pasa una colección de nombres de permisos a revokeSelfPermissionsOnKill(). El proceso de eliminación de permisos se realiza de forma asíncrona y finaliza todos los procesos asociados con el UID de tu app.

Para que el sistema quite el acceso de tu app a los permisos, se deben finalizar todos los procesos vinculados a ella. Cuando llamas a la API, el sistema determina el momento en que es seguro finalizar estos procesos. Por lo general, el sistema espera hasta que tu app pase un período prolongado ejecutándose en segundo plano en lugar de en primer plano.

Para informar al usuario que tu app ya no requiere acceso a permisos de tiempo de ejecución específicos, muestra un diálogo la próxima vez que la inicie. Este diálogo puede incluir la lista de permisos.

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

Si tu app se orienta a Android 11 (nivel de API 30) o versiones posteriores, y no se usa durante algunos meses, el sistema restablece automáticamente los permisos de tiempo de ejecución sensibles que el usuario le otorgó a tu app para proteger sus datos. Obtén más información en la guía sobre la hibernación de apps.

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.

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

Otorga todos los permisos de tiempo de ejecución con fines de prueba

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

Recursos adicionales

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

Para obtener más información sobre cómo solicitar permisos, consulta los ejemplos de permisos.

También puedes completar este codelab que demuestra las prácticas recomendadas de privacidad.