Hi
I'm trying to integrate Geocoding (w Google) into xData service implementation using callback method to keep synchronous logic
function implemeting xData Service is called but unfortunately, the callback function seems not be called
Latitude := '';
Longitude:= '';
geocoder := TTMSFNCGeocoding.Create(ServerContainer); //<== ServerContainer = DataModule
geocoder.Service := gsGoogle;
geocoder.APIKey := 'zzzzzzz';
// Check if CodePostal is ... a CodePOstal
// Retrieve Lat, Long from ZIP code
sTempAdr := CodePostal+',France';
geocoder.GetGeocoding(sTempAdr,
procedure(const ARequest: TTMSFNCGeocodingRequest; const ARequestResult: TTMSFNCCloudBaseRequestResult)
begin
Longitude := ARequest.Items[0].Coordinate.longitude.ToString;
Latitude := ARequest.Items[0].Coordinate.Latitude.ToString;
end
);
..
FreeAndNil(geocoder);
Is there something to adjust in such case? I tried to implement in similar way to doc and to demo but without UI and inside a DataModule used with xData.
Thanks
Sylvain
The call itself is asynchronous, so the callback could be triggered after destroying the geocoder instance.
when the instance is destroyed prematurely, this could be the reason why the callback is not called. I suggest to keep the instance running for the lifetime of the application, or destroy it when the callback is triggered:
Latitude := '';
Longitude:= '';
geocoder := TTMSFNCGeocoding.Create(ServerContainer); //<== ServerContainer = DataModule
geocoder.Service := gsGoogle;
geocoder.APIKey := 'zzzzzzz';
// Check if CodePostal is ... a CodePOstal
// Retrieve Lat, Long from ZIP code
sTempAdr := CodePostal+',France';
geocoder.GetGeocoding(sTempAdr,
procedure(const ARequest: TTMSFNCGeocodingRequest; const ARequestResult: TTMSFNCCloudBaseRequestResult)
begin
Longitude := ARequest.Items[0].Coordinate.longitude.ToString;
Latitude := ARequest.Items[0].Coordinate.Latitude.ToString;
FreeAndNil(geocoder);
end
);
..
Thanks for solution,
now callback is fired but unfortunately my function exposing implementation for xData is ended before and JSON result empty and can't be populated by callback as it's a... callback.
Is there a way to call with synchronous way the geocoding function ?
I can try to wait for callback result from implementation function but I guess it isn't the cleanest way
Unfortunately no, there is no synchronous callback option included. We'll investigate if we can add such option. For now, you can create a lower level request that basically does the same, but in a synchronous way with the following code:
unit Unit10;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
FMX.TMSFNCCustomComponent, FMX.TMSFNCCloudBase, FMX.TMSFNCGeocoding, FMX.TMSFNCMapsCommonTypes,
FMX.Controls.Presentation, FMX.StdCtrls;
type
TForm10 = class(TForm)
TMSFNCGeocoding1: TTMSFNCGeocoding;
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
FRequestResult: string;
function GetGeocoding(AAddress: string): TTMSFNCMapsCoordinateRec;
procedure DoRequestAddress(
const ARequestResult: TTMSFNCCloudBaseRequestResult);
{ Private declarations }
public
{ Public declarations }
end;
var
Form10: TForm10;
implementation
{$R *.fmx}
uses
FMX.TMSFNCUtils;
procedure TForm10.Button1Click(Sender: TObject);
var
c: TTMSFNCMapsCoordinateRec;
begin
c := GetGeocoding('MyAddress');
end;
procedure TForm10.DoRequestAddress(const ARequestResult: TTMSFNCCloudBaseRequestResult);
begin
FRequestResult := ARequestResult.ResultString;
end;
function TForm10.GetGeocoding(AAddress: string): TTMSFNCMapsCoordinateRec;
var
req: TTMSFNCGeocodingRequest;
lon, lat: Double;
begin
Result := DefaultCoordinate;
TMSFNCGeocoding1.APIKey := '';
TMSFNCGeocoding1.Service := gsHere;
TMSFNCGeocoding1.Request.Clear;
TMSFNCGeocoding1.Request.ClearHeaders;
TMSFNCGeocoding1.Request.Name := 'GET GEOCODING';
TMSFNCGeocoding1.Request.Method := TMSFNCGeocoding1.GeocodingInstance.GetRequestMethod;
TMSFNCGeocoding1.Request.Host := TMSFNCGeocoding1.GeocodingInstance.GetHost;
TMSFNCGeocoding1.Request.Path := TMSFNCGeocoding1.GeocodingInstance.GetPath(TTMSFNCUtils.URLEncode(AAddress));
TMSFNCGeocoding1.Request.Query := TMSFNCGeocoding1.GeocodingInstance.GetQuery(TTMSFNCUtils.URLEncode(AAddress));
TMSFNCGeocoding1.Request.PostData := TMSFNCGeocoding1.GeocodingInstance.GetPostData;
TMSFNCGeocoding1.ExecuteRequest(DoRequestAddress, nil, False);
if FRequestResult <> '' then
begin
req := TMSFNCGeocoding1.GeocodingRequests.Add;
TMSFNCGeocoding1.GeocodingInstance.Parse(req, FRequestResult);
lon := req.Items[0].Coordinate.longitude;
lat := req.Items[0].Coordinate.Latitude;
Result := CreateCoordinate(lat, lon);
end;
end;
end.