I have a fmx form with nothing more than a LocationSensor
, a Memo
and a Button
on it and used the code below to display the coordinates in a memo. When I have GPS turned on on my phone "1" and "2" are shown when I click the button, so that seems to work, but there are no lines in my Memo added. I tried different code examples but not a single one worked for me to display coordinates in any way.
I use a Samsung A3 (SM-A310F) with at first stock rom (Android 7) and now with Lineage 17.1 (based on Android 10) to test it and on both versions nothing with GPS Coordinates worked so far. I use Delphi 10.3.3 Community Edition.
What am I doing wrong?
unit Unit1;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes,
System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.ScrollBox,
FMX.Memo, FMX.Controls.Presentation, FMX.StdCtrls, System.Sensors,
System.Sensors.Components,
Androidapi.JNI.Location,
Androidapi.JNIBridge,
FMX.Helpers.Android,
Androidapi.JNI.GraphicsContentViewText,
Androidapi.Helpers;
type
TForm1 = class(TForm)
Button1: TButton;
Memo1: TMemo;
LocationSensor1: TLocationSensor;
procedure Button1Click(Sender: TObject);
procedure LocationSensor1LocationChanged(Sender: TObject;
const OldLocation, NewLocation: TLocationCoord2D);
private
{ Private-Deklarationen }
public
{ Public-Deklarationen }
end;
var
Form1: TForm1;
implementation
{$R *.fmx}
procedure TForm1.Button1Click(Sender: TObject);
var
locationManager: JLocationManager;
begin
LocationSensor1.Active := true;
locationManager := TJLocationManager.Wrap
(((SharedActivity.getSystemService(TJContext.JavaClass.LOCATION_SERVICE))
as ILocalObject).GetObjectID);
if locationManager.isProviderEnabled(TJLocationManager.JavaClass.GPS_PROVIDER)
then
begin
showmessage('1');
end;
if locationManager.isProviderEnabled
(TJLocationManager.JavaClass.NETWORK_PROVIDER) then
begin
showmessage('2');
end;
end;
procedure TForm1.LocationSensor1LocationChanged(Sender: TObject;
const OldLocation, NewLocation: TLocationCoord2D);
begin
Memo1.Lines.Add(FloatToStr(NewLocation.Longitude));
Memo1.Lines.Add(FloatToStr(NewLocation.Latitude));
end;
end.
Update: I found a spanish solution (see below)
I found a solution on YouTube in spanish: https://www.youtube.com/watch?v=iiPFpzGICws which links me to this file: https://drive.google.com/file/d/1kGHlaaSfSfeAcOsiWG7mAsH5Vl_kXdzS/view
I dont know any Spanish, but I try to understand, what he does and I will reuse his version for my app now. It is the only version on the Internet I found so far and it works awesome.
So in case the links get deleted here is the code provided:
unit Form_Principal;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Layouts,
FMX.WebBrowser, FMX.StdCtrls, FMX.Controls.Presentation, FMX.Objects,
System.Permissions, System.Sensors, System.Sensors.Components;
type
TForm1 = class(TForm)
WebBrowser: TWebBrowser;
Layout1: TLayout;
Switch: TSwitch;
Label1: TLabel;
Layout2: TLayout;
RoundRect1: TRoundRect;
lbl_endereco: TLabel;
LocationSensor: TLocationSensor;
procedure FormCreate(Sender: TObject);
procedure SwitchClick(Sender: TObject);
procedure LocationSensorLocationChanged(Sender: TObject; const OldLocation,
NewLocation: TLocationCoord2D);
procedure lbl_enderecoClick(Sender: TObject);
private
{ Private declarations }
Location: TLocationCoord2D;
FGeocoder: TGeocoder;
{$IFDEF ANDROID}
Access_Fine_Location, Access_Coarse_Location : string;
procedure DisplayRationale(Sender: TObject;
const APermissions: TArray<string>; const APostRationaleProc: TProc);
procedure LocationPermissionRequestResult
(Sender: TObject; const APermissions: TArray<string>;
const AGrantResults: TArray<TPermissionStatus>);
{$ENDIF}
procedure OnGeocodeReverseEvent(const Address: TCivicAddress);
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.fmx}
uses FMX.DialogService
{$IFDEF ANDROID}
,Androidapi.Helpers, Androidapi.JNI.JavaTypes, Androidapi.JNI.Os
{$ENDIF}
;
{$IFDEF ANDROID}
procedure TForm1.DisplayRationale(Sender: TObject;
const APermissions: TArray<string>; const APostRationaleProc: TProc);
var
I: Integer;
RationaleMsg: string;
begin
for I := 0 to High(APermissions) do
begin
if (APermissions[I] = Access_Coarse_Location) or (APermissions[I] = Access_Fine_Location) then
RationaleMsg := 'O app precisa de acesso ao GPS para obter sua localização'
end;
TDialogService.ShowMessage(RationaleMsg,
procedure(const AResult: TModalResult)
begin
APostRationaleProc;
end)
end;
procedure TForm1.LocationPermissionRequestResult
(Sender: TObject; const APermissions: TArray<string>;
const AGrantResults: TArray<TPermissionStatus>);
var
x : integer;
begin
if (Length(AGrantResults) = 2) and
(AGrantResults[0] = TPermissionStatus.Granted) and
(AGrantResults[1] = TPermissionStatus.Granted) then
Form1.LocationSensor.Active := true
else
begin
Switch.IsChecked := false;
TDialogService.ShowMessage
('Não é possível acessar o GPS porque o app não possui acesso')
end;
end;
{$ENDIF}
procedure TForm1.OnGeocodeReverseEvent(const Address: TCivicAddress);
var
msg : string;
begin
msg := Address.AdminArea + ', ' +
Address.CountryCode + ', ' +
Address.CountryName + ', ' +
Address.FeatureName + ', ' +
Address.Locality + ', ' +
Address.PostalCode + ', ' +
Address.SubAdminArea + ', ' +
Address.SubLocality + ', ' +
Address.SubThoroughfare + ', ' +
Address.Thoroughfare;
TDialogService.ShowMessage(msg);
end;
procedure TForm1.LocationSensorLocationChanged(Sender: TObject;
const OldLocation, NewLocation: TLocationCoord2D);
var
lt, lg, url : string;
begin
Location := NewLocation;
lt := StringReplace(Format('%2.6f', [NewLocation.Latitude]), ',', '.', [rfReplaceAll]);
lg := StringReplace(Format('%2.6f', [NewLocation.Longitude]), ',', '.', [rfReplaceAll]);
LocationSensor.Active := false;
Switch.IsChecked := false;
url := 'https://maps.google.com/maps?q=' + lt + ',' + lg;
WebBrowser.Navigate(url);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
{$IFDEF ANDROID}
Access_Coarse_Location := JStringToString(TJManifest_permission.JavaClass.ACCESS_COARSE_LOCATION);
Access_Fine_Location := JStringToString(TJManifest_permission.JavaClass.ACCESS_FINE_LOCATION);
{$ENDIF}
end;
procedure TForm1.lbl_enderecoClick(Sender: TObject);
begin
try
// Tratando a instancia TGeocoder...
if not Assigned(FGeocoder) then
begin
if Assigned(TGeocoder.Current) then
FGeocoder := TGeocoder.Current.Create;
if Assigned(FGeocoder) then
FGeocoder.OnGeocodeReverse := OnGeocodeReverseEvent;
end;
// Tratar a traducao do endereco...
if Assigned(FGeocoder) and not FGeocoder.Geocoding then
FGeocoder.GeocodeReverse(Location);
except
showmessage('Erro no serviço Geocoder');
end;
end;
procedure TForm1.SwitchClick(Sender: TObject);
begin
if Switch.IsChecked then
begin
{$IFDEF ANDROID}
PermissionsService.RequestPermissions([Access_Coarse_Location,
Access_Fine_Location],
LocationPermissionRequestResult,
DisplayRationale);
{$ENDIF}
{$IFDEF IOS}
LocationSensor.Active := true;
{$ENDIF}
end;
end;
end.