Unas de las cuestiones a tener en cuenta si queremos que nuestra App funcionen, son los Permisos en Android (Android Permissions).
Si el dispositivo posee instalado Android 6 Marshmallow (Nivel de API 23), o el atributo de la App TargetSdkVersion es 23 o superior, el usuario debe aceptar los permisos riesgosos.
Por ende no solamente debemos colocar el permiso en el Manifest de la App, sino realizar las funcione que soliciten al usuario dichos permisos para que puedan aceptarlos o rechazarlos.
Cuales son los Permisos peligrosos
Los permisos están divididos en dos grupos, los permisos comunes o normales y los permisos peligrosos.
Con respecto a los permisos comunes, como por ejemplo el uso de Internet, solo hace falta declararlos en el manifest, mientras que para los permisos peligrosos necesitamos la autorización del usuario.
Para poder otorgar los permisos en Delphi deberemos ir al menú Proyect -> Options.
En la ventana de opciones del proyecto, iremos a la sección Application -> Uses Permissions. En la sección Target deberemos seleccionar Android Platform 32 o 64 bits según la versión a compilar.
Nos aparecerá en primera instancia un listado de los permisos comunes, que con solo seleccionarlos, ya lo podremos utilizar en la App y por debajo los Dangerous Permissions.
Solicitar permisos de Android desde Delphi
En este caso realizaremos el ejemplo solicitando el permiso de Localización. Primero iremos al menú Proyect -> Options y en la ventada de opciones de proyecto abrimos la sección Application – > Uses Permissions.
Dentro de los permisos comunes seleccionamos Internet, y en los permisos peligrosos seleccionamos los permisos Access Coarse Location y Access Fine Location.
Al usuario solo le deberemos solicitar autorización por los dos últimos permisos ya que son peligrosos.
La unidad en Delphi que maneja los permisos es System.Permissions por lo que deberemos agregarla en los Uses.
En segundo lugar declaramos una variable global para cada uno de los permisos peligrosos que queremos solicitar. Quedando el código de la siguiente manera:
uses
System.SysUtils, System.Types, System.UITypes,
System.Classes, System.Variants, FMX.Types,
FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
System.Permissions;
type
TForm1 = class(TForm)
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
// Variables Dangerous Permissions
vPermissionCoarseLocation: string;
vPermissionFineLocation: string;
implementation
{$R *.fmx}
end.
En el evento OnCreate del Formulario colocamos el siguiente código, donde asignamos el valor de cada permiso a las variables declaradas con anterioridad, no sin antes agregar en los Uses las unidades Androidapi.Helpers y Androidapi.JNI.Os:
Uses
Androidapi.Helpers, Androidapi.JNI.Os
...
procedure TFLogin.FormCreate(Sender: TObject);
begin
vPermissionCoarseLocation := JStringToString(TJManifest_permission.JavaClass.ACCESS_COARSE_LOCATION);
vPermissionFineLocation := JStringToString(TJManifest_permission.JavaClass.ACCESS_FINE_LOCATION);
end;
Cabe aclarar que hasta la versión 6 de Andorid, los permisos se mostraban en el momento de la instalación de la App.
A partir del nivel 23 de la API, la autorización de los permisos peligrosos al usuario, se le puede solicitar en cualquier momento de la ejecución.
En este ejemplo lo colocamos en el evento OnShow del formulario, pero recuerda que se puede solicitar en cualquier momento, siempre antes de que se utilice lo que el permiso autoriza.
El procedimiento para solicitar la autorización es PermissionsService.RequestPermissions([<array_de_permisos>], <procedimiento_de_aterrizaje>).
procedure TForm1.FormShow(Sender: TObject);
begin
if TOSVersion.Check(6) then
begin
PermissionsService.RequestPermissions([vPermissionCoarseLocation, vPermissionFineLocation], LocationPermissionRequestResult);
end
end;
procedure TForm1.LocationPermissionRequestResult(Sender: TObject;
const APermissions: TArray<string>;
const AGrantResults: TArray<TPermissionStatus>);
var
LocationPermissionGranted: Boolean;
begin
LocationPermissionGranted := (Length(AGrantResults) = 2) and
(AGrantResults[0] = TPermissionStatus.Granted) and
(AGrantResults[1] = TPermissionStatus.Granted);
if LocationPermissionGranted then
begin
ShowMessage('Se aceptaron todos los permisos.');
end
else
begin
ShowMessage('No se han haceptado los permisos.');
end;
end;
Lo que realizamos en el evento OnShow es chequear si la versión de Android es igual o superior a 6, y si es verdadero, solicitamos la autorización del permiso, pasando como parámetros un array con los permisos a solicitar y el procedimiento de aterrizaje de permisos.
En el procedimiento LocationPermissionRequestResult que pasamos como procedimiento de aterrizaje de la autorización de los permisos, podemos chequear si el usuario autorizó o no los permisos solicitados y tomar las medidas correspondientes.
Por ejemplo, si queremos mostrar la posición del usuario en un mapa y el usuario no autoriza la geolocalización, no mostraremos el mapa y advertiremos al usuario de la negación al permiso.
Ejemplo de Permisos en Andrid desde Delphi
El código completo de la unidad para solicitar los permisos de geolocalización al usuario, quedaría de la siguiente manera:
unit Unit1;
interface
uses
System.SysUtils, System.Types, System.UITypes,
System.Classes, System.Variants, FMX.Types,
FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
System.Permissions, Androidapi.Helpers, Androidapi.JNI.Os;
type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure LocationPermissionRequestResult(Sender: TObject;
const APermissions: TArray<string>;
const AGrantResults: TArray<TPermissionStatus>);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
// Permissions
vPermissionCoarseLocation: string;
vPermissionFineLocation: string;
implementation
{$R *.fmx}
procedure TForm1.FormCreate(Sender: TObject);
begin
vPermissionCoarseLocation := JStringToString(TJManifest_permission.JavaClass.ACCESS_COARSE_LOCATION);
vPermissionFineLocation := JStringToString(TJManifest_permission.JavaClass.ACCESS_FINE_LOCATION);
end;
procedure TForm1.FormShow(Sender: TObject);
begin
if TOSVersion.Check(6) then
begin
PermissionsService.RequestPermissions([vPermissionCoarseLocation, vPermissionFineLocation], LocationPermissionRequestResult);
end
end;
procedure TForm1.LocationPermissionRequestResult(Sender: TObject;
const APermissions: TArray<string>;
const AGrantResults: TArray<TPermissionStatus>);
var
LocationPermissionGranted: Boolean;
begin
LocationPermissionGranted := (Length(AGrantResults) = 2) and
(AGrantResults[0] = TPermissionStatus.Granted) and
(AGrantResults[1] = TPermissionStatus.Granted);
if LocationPermissionGranted then
begin
ShowMessage('Se aceptaron todos los permisos.');
end
else
begin
ShowMessage('No se han haceptado los permisos.');
end;
end;
end.
Si todavía tienes alguna dudo o consulta déjame un comentario.