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 de Android se ejecuta en una zona de pruebas con acceso limitado. Si una app necesita usar recursos o información ajenos a su propia zona de pruebas, debe solicitar el permiso correspondiente. Para declarar que la app necesita un permiso, debes incluirlo en el manifiesto de la app y, luego, solicitar al usuario que apruebe cada permiso durante el tiempo de ejecución (en Android 6.0 y versiones posteriores).

Los principios básicos 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.

En esta página se explica el proceso paso a paso para agregar permisos a tu app y solicitarlos en el tiempo de ejecución según sea necesario.

Cómo agregar permisos al manifiesto

En todas las versiones de Android, para declarar que la app necesita un permiso, coloca un elemento <uses-permission> en el manifiesto como elemento secundario del elemento <manifest> de nivel superior.

Por ejemplo, una app que necesita acceso a Internet incluiría la siguiente línea en su manifiesto:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.example.snazzyapp">

    <uses-permission android:name="android.permission.INTERNET"/>
    <!-- other permissions go here -->

    <application ...>
        ...
    </application>
</manifest>

El comportamiento del sistema después de declarar un permiso depende de qué tan sensible sea este. Algunos se consideran "normales", por lo que el sistema los otorga inmediatamente después de la instalación. Otros se consideran "peligrosos", por lo que el usuario debe otorgar el acceso a tu app de manera explícita. Para obtener más información sobre los diferentes tipos de permisos, consulta Niveles de protección.

Cómo verificar si tu app tiene permisos

Si tu app necesita un permiso peligroso, deberás verificar si tienes ese permiso cada vez que realices una operación que lo requiera. En Android 6.0 (nivel 23 de API) y versiones posteriores, los usuarios pueden revocar permisos peligrosos desde cualquier app en cualquier momento.

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. 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 biblioteca androidx.activity del archivo build.gradle de tu módulo. Usa la versión 1.2.0 o posterior de la biblioteca.

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 onRequestPermissionsResults(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 deniega 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 para 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, debes verificar que se le otorgue ese permiso.

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

Cómo solicitar la conversión a 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.

Cómo declarar permisos por nivel de API

Para declarar permisos únicamente en dispositivos que admiten permisos durante el tiempo de ejecución (es decir, que ejecuten Android 6.0 [nivel 23 de API] o versiones posteriores), debes incluir la etiqueta uses-permission-sdk-23 en lugar de uses-permission.

Cuando usas cualquiera de estas etiquetas, puedes establecer el atributo maxSdkVersion para especificar que, en dispositivos que ejecutan versiones posteriores, no se necesita ningún permiso en particular.

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, descarga las siguientes apps de ejemplo:

  • Ejemplo de RuntimePermissionsBasic de Android Java | Kotlin