Permisos en Xamarin.Android

Información general

Las aplicaciones Android se ejecutan en su propio espacio aislado y, por motivos de seguridad, no tienen acceso a determinados recursos del sistema o hardware en el dispositivo. El usuario debe conceder explícitamente permiso a la aplicación para poder usar estos recursos. Por ejemplo, una aplicación no puede acceder al GPS en un dispositivo sin el permiso explícito del usuario. Android inicia una Java.Lang.SecurityException excepción si una aplicación intenta acceder a un recurso protegido sin permiso.

Los permisos se declaran en la AndroidManifest.xml el desarrollador de aplicaciones cuando se desarrolla la aplicación. Android tiene dos flujos de trabajo diferentes para obtener el consentimiento del usuario para esos permisos:

  • En el caso de las aplicaciones destinadas a Android 5.1 (nivel de API 22) o inferior, la solicitud de permiso se produjo cuando se instaló la aplicación. Si el usuario no concedía los permisos, la aplicación no se instalaría. Una vez instalada la aplicación, no hay ninguna manera de revocar los permisos, excepto mediante la desinstalación de la aplicación.
  • A partir de Android 6.0 (nivel de API 23), a los usuarios se les ha dado más control sobre los permisos. pueden conceder o revocar permisos siempre que la aplicación esté instalada en el dispositivo. En esta captura de pantalla se muestra la configuración de permisos para la aplicación Contactos de Google. Enumera los distintos permisos y permite al usuario habilitar o deshabilitar los permisos:

Pantalla Permisos de ejemplo

Las aplicaciones Android deben comprobar en tiempo de ejecución para ver si tienen permiso para acceder a un recurso protegido. Si la aplicación no tiene permiso, debe realizar solicitudes mediante las nuevas API proporcionadas por el Android SDK para que el usuario conceda los permisos. Los permisos se dividen en dos categorías:

  • Permisos normales: se trata de permisos que suponen un riesgo de seguridad pequeño para la seguridad o privacidad del usuario. Android 6.0 concederá automáticamente permisos normales en el momento de la instalación. Consulte la documentación de Android para obtener una lista completa de los permisos normales.
  • Permisos peligrosos: a diferencia de los permisos normales, los permisos peligrosos son los que protegen la seguridad o privacidad del usuario. El usuario los debe conceder explícitamente. Enviar o recibir un mensaje SMS es un ejemplo de una acción que requiere un permiso peligroso.

Importante

La categoría a la que pertenece un permiso puede cambiar con el tiempo. Es posible que un permiso clasificado como permiso "normal" se pueda elevar en niveles de API futuros a un permiso peligroso.

Los permisos peligrosos se dividen en grupos de permisos. Un grupo de permisos contendrán permisos que están relacionados lógicamente. Cuando el usuario concede permiso a un miembro de un grupo de permisos, Android concede automáticamente permiso a todos los miembros de ese grupo. Por ejemplo, el STORAGE grupo de permisos contiene los permisos y WRITE_EXTERNAL_STORAGEREAD_EXTERNAL_STORAGE . Si el usuario concede permiso a READ_EXTERNAL_STORAGE , el permiso se concede automáticamente al mismo WRITE_EXTERNAL_STORAGE tiempo.

Antes de solicitar uno o varios permisos, es un procedimiento recomendado proporcionar una explicación de por qué la aplicación requiere el permiso antes de solicitar el permiso. Una vez que el usuario comprende la lógica, la aplicación puede solicitar permiso al usuario. Al comprender la lógica, el usuario puede tomar una decisión informada si desea conceder el permiso y comprender las repercusiones si no lo hace.

Todo el flujo de trabajo de comprobación y solicitud de permisos se conoce como comprobación de permisos en tiempo de ejecución y se puede resumir en el diagrama siguiente:

Gráfico de flujo de comprobación de permisos en tiempo de ejecución

La biblioteca de compatibilidad de Android admite algunas de las nuevas API para permisos en versiones anteriores de Android. Estas API de backported comprobarán automáticamente la versión de Android en el dispositivo, por lo que no es necesario realizar una comprobación de nivel de API cada vez.

En este documento se explica cómo agregar permisos a una aplicación de Xamarin.Android y cómo las aplicaciones que tienen como destino Android 6.0 (nivel de API 23) o superior deben realizar una comprobación de permisos en tiempo de ejecución.

Nota:

Es posible que los permisos de hardware puedan afectar a la forma en que la aplicación se filtra por Google Play. Por ejemplo, si la aplicación requiere permiso para la cámara, Google Play mostrará la aplicación en el Google Play Store en un dispositivo que no tenga instalada una cámara.

Requisitos

Se recomienda encarecidamente que los proyectos de Xamarin.Android incluyan el paquete de NuGet Xamarin.Android.Support.Compat. Este paquete volverá a proporcionar API específicas de permisos a versiones anteriores de Android, lo que proporciona una interfaz común sin necesidad de comprobar constantemente la versión de Android en la que se ejecuta la aplicación.

Solicitud de permisos del sistema

El primer paso para trabajar con permisos de Android es declarar los permisos en el archivo de manifiesto de Android. Esto debe hacerse independientemente del nivel de API de destino de la aplicación.

Las aplicaciones que tienen como destino Android 6.0 o posterior no pueden suponer que, dado que el usuario concedió permiso en algún momento del pasado, el permiso será válido la próxima vez. Una aplicación que tenga como destino Android 6.0 siempre debe realizar una comprobación de permisos en tiempo de ejecución. Las aplicaciones que tienen como destino Android 5.1 o versiones inferiores no necesitan realizar una comprobación de permisos en tiempo de ejecución.

Nota:

Las aplicaciones solo deben solicitar los permisos que necesitan.

Declarar permisos en el manifiesto

Los permisos se agregan al AndroidManifest.xml con el elemento . Por ejemplo, si una aplicación va a buscar la posición del dispositivo, requiere permisos de ubicación correctos y de curso. Los dos elementos siguientes se agregan al manifiesto:

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

Es posible declarar los permisos mediante la compatibilidad con la herramienta integrada en Visual Studio:

  1. Haga doble clic en Propiedades en la Explorador de soluciones y seleccione la pestaña Manifiesto de Android en la ventana Propiedades:

    Permisos necesarios en la pestaña Manifiesto de Android

  2. Si la aplicación aún no tiene un AndroidManifest.xml, haga clic en No AndroidManifest.xml encontrado. Haga clic para agregar uno como se muestra a continuación:

    Sin AndroidManifest.xml mensaje

  3. Seleccione los permisos que necesite la aplicación en la lista Permisos necesarios y guárdelo:

    Permisos CAMERA de ejemplo seleccionados

Xamarin.Android agregará automáticamente algunos permisos en tiempo de compilación a las compilaciones de depuración. Esto facilitará la depuración de la aplicación. En concreto, dos permisos importantes son INTERNET y READ_EXTERNAL_STORAGE . Estos permisos establecidos automáticamente no aparecerán habilitados en la lista Permisos necesarios. Sin embargo, las compilaciones de versión solo usan los permisos establecidos explícitamente en la lista Permisos necesarios.

En el caso de las aplicaciones destinadas a Android 5.1 (nivel de API 22) o inferior, no es necesario hacer nada más. Las aplicaciones que se ejecutarán en Android 6.0 (API 23 nivel 23) o posterior deben continuar con la sección siguiente sobre cómo realizar comprobaciones de permisos en tiempo de ejecución.

Comprobaciones de permisos en tiempo de ejecución en Android 6.0

El método (disponible con la biblioteca de compatibilidad de Android) se usa para comprobar si se ha concedido ContextCompat.CheckSelfPermission un permiso específico. Este método devolverá una Android.Content.PM.Permission enumeración que tiene uno de dos valores:

  • Permission.Granted : se ha concedido el permiso especificado.
  • Permission.Denied : no se ha concedido el permiso especificado.

Este fragmento de código es un ejemplo de cómo comprobar el permiso Cámara en una actividad:

if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.Camera) == (int)Permission.Granted) 
{
    // We have permission, go ahead and use the camera.
} 
else 
{
    // Camera permission is not granted. If necessary display rationale & request.
}

Es un procedimiento recomendado informar al usuario sobre por qué es necesario un permiso para una aplicación para que se pueda tomar una decisión informada para conceder el permiso. Un ejemplo de esto sería una aplicación que toma fotos y etiquetas geográficas. El usuario tiene claro que el permiso de cámara es necesario, pero puede que no esté claro por qué la aplicación también necesita la ubicación del dispositivo. La lógica debe mostrar un mensaje para ayudar al usuario a comprender por qué es deseable el permiso de ubicación y que se requiere el permiso de cámara.

El ActivityCompat.ShouldShowRequestPermissionRationale método se usa para determinar si el razonamiento debe mostrarse al usuario. Este método devolverá si se debe mostrar la lógica de un true permiso determinado. En esta captura de pantalla se muestra un ejemplo de una barra de sonido mostrada por una aplicación que explica por qué la aplicación debe conocer la ubicación del dispositivo:

Justificación de la ubicación

Si el usuario concede el permiso, se ActivityCompat.RequestPermissions(Activity activity, string[] permissions, int requestCode) debe llamar al método . Este método requiere los parámetros siguientes:

  • activity: se trata de la actividad que solicita los permisos y que Android debe informar de los resultados.
  • permisos: una lista de los permisos que se solicitan.
  • requestCode: valor entero que se usa para hacer coincidir los resultados de la solicitud de permiso con una llamada. Este valor debería ser mayor que cero.

Este fragmento de código es un ejemplo de los dos métodos que se han analizado. En primer lugar, se realiza una comprobación para determinar si se debe mostrar la justificación de los permisos. Si se va a mostrar la justificación, se muestra una barra de barras de barras con la lógica. Si el usuario hace clic en Aceptar en la barra de menús, la aplicación solicitará los permisos. Si el usuario no acepta la justificación, la aplicación no debe continuar con la solicitud de permisos. Si no se muestra la justificación, la actividad solicitará el permiso:

if (ActivityCompat.ShouldShowRequestPermissionRationale(this, Manifest.Permission.AccessFineLocation)) 
{
    // Provide an additional rationale to the user if the permission was not granted
    // and the user would benefit from additional context for the use of the permission.
    // For example if the user has previously denied the permission.
    Log.Info(TAG, "Displaying camera permission rationale to provide additional context.");

    var requiredPermissions = new String[] { Manifest.Permission.AccessFineLocation };
    Snackbar.Make(layout, 
                   Resource.String.permission_location_rationale,
                   Snackbar.LengthIndefinite)
            .SetAction(Resource.String.ok, 
                       new Action<View>(delegate(View obj) {
                           ActivityCompat.RequestPermissions(this, requiredPermissions, REQUEST_LOCATION);
                       }    
            )
    ).Show();
}
else 
{
    ActivityCompat.RequestPermissions(this, new String[] { Manifest.Permission.Camera }, REQUEST_LOCATION);
}

RequestPermission Se puede llamar a incluso si el usuario ya ha concedido permiso. Las llamadas posteriores no son necesarias, pero proporcionan al usuario la oportunidad de confirmar (o revocar) el permiso. Cuando se llama a , el control se entrega al sistema operativo, que mostrará una interfaz de RequestPermission usuario para aceptar los permisos:

Cuadro de diálogo de permssion

Una vez finalizado el usuario, Android devolverá los resultados a la actividad a través de un método de devolución de llamada, OnRequestPermissionResult . Este método forma parte de la interfaz ActivityCompat.IOnRequestPermissionsResultCallback que debe implementar la actividad . Esta interfaz tiene un único método, , que Android invocará para informar a OnRequestPermissionsResult la actividad de las opciones del usuario. Si el usuario ha concedido el permiso, la aplicación puede continuar y usar el recurso protegido. A continuación se muestra un OnRequestPermissionResult ejemplo de cómo implementar:

public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults)
{
    if (requestCode == REQUEST_LOCATION) 
    {
        // Received permission result for camera permission.
        Log.Info(TAG, "Received response for Location permission request.");

        // Check if the only required permission has been granted
        if ((grantResults.Length == 1) && (grantResults[0] == Permission.Granted)) {
            // Location permission has been granted, okay to retrieve the location of the device.
            Log.Info(TAG, "Location permission has now been granted.");
            Snackbar.Make(layout, Resource.String.permission_available_camera, Snackbar.LengthShort).Show();            
        } 
        else 
        {
            Log.Info(TAG, "Location permission was NOT granted.");
            Snackbar.Make(layout, Resource.String.permissions_not_granted, Snackbar.LengthShort).Show();
        }
    } 
    else 
    {
        base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
    }
}

Resumen

En esta guía se describe cómo agregar y comprobar los permisos en un dispositivo Android. Diferencias en el modo en que funcionan los permisos entre las aplicaciones android antiguas (nivel de API 23) y las nuevas < aplicaciones android (nivel de API > 22). Se ha analizado cómo realizar comprobaciones de permisos en tiempo de ejecución en Android 6.0.