Geocoding with callback not processed (into DataModule)

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

Hi,

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

This topic was automatically closed 60 minutes after the last reply. New replies are no longer allowed.

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.