Can't find DWFusedLocationClientDelegate

Still struggling with location stuff. I have taken DW.Loaction.FusedLocation.Android
and put it into a programme. Unfortunately I am getting the error below:

var
LocMainForm : tLocMainForm;
xLocation : tLocation;
xFusedLocationClientDelegate : tFusedLocationClientDelegate;
xNmeaMessageListener : tNmeaMessageListener;


Code:
xLocation := tLocation.Create;
xFusedLocationClientDelegate := tFusedLocationClientDelegate.Create(xLocation);
xNmeaMessageListener := tNmeaMessageListener.Create(xLocation);

xLocation.OnNmeaMessage := pOnNmeaMessageEvent;
xLocation.OnLocationChange := pLocationChangeEvent;
xLocation.OnSetMockLocationResult := pOnSetMockLocationResult;
xLocation.OnSetMockModeResult := pOnSetMockModeResult;

xFusedLocationClientDelegate.Flocation := xLocation;
xFusedLocationClientDelegate.useCallback;

Error:
Crashes with EJNI fatal error
Java Type com/delphiworlds/kastri/DWFusedLocationClientDelegate could not be found.
(even though it’s in the source file)

This error means dw-fusedlocation-3.0.0.jar (from the Lib folder of Kastri) has not been added to the project, as per these instructions in the ABLSticky demo.

Thanks - that got rid of the first problem. Now for the second:

Still struggling:

var
LocMainForm : tLocMainForm;
xLocation : tLocation;
xFusedLocationClientDelegate : tFusedLocationClientDelegate;
xNmeaMessageListener : tNmeaMessageListener;


Code:
xLocation := tLocation.Create;
xFusedLocationClientDelegate := tFusedLocationClientDelegate.Create(xLocation);
xNmeaMessageListener := tNmeaMessageListener.Create(xLocation);

xLocation.OnNmeaMessage := pOnNmeaMessageEvent;
xLocation.OnLocationChange := pLocationChangeEvent;
xLocation.OnSetMockLocationResult := pOnSetMockLocationResult;
xLocation.OnSetMockModeResult := pOnSetMockModeResult;

xFusedLocationClientDelegate.Flocation := xLocation;
xFusedLocationClientDelegate.useCallback;

xLocation.SetInterval(1000);

xLocation.Resume

Error:
Kills the app. On going over it with the debuggeer, get
file Thunk_blocks.s not found.

Gave up on the DW.Android.Location.pas one, and went back to the LocationSensor one.

Added:
tGpsStatus_NmeaListener = class(TJGpsStatus_NmeaListener)
procedure onNmeaReceived(timestamp: Int64; nmea: JString); cdecl;//Deprecated
end;

var
Lis : tGpsStatus_NmeaListener;

But in the code

begin
LocationManagerService := tAndroidHelper.Context.getSystemService(
TJContext.JavaClass.LOCATION_SERVICE);
FLocationManager := TJLocationManager.Wrap(
(LocationManagerService as ILocalObject).GetObjectID);

fLocationManager.addNmeaListener(Lis);

     it wants Lis to be a JGpsStatus_NmeaListener, not a tGpsStatus_NmeaListener.

But if I put tGpsStatus_NmeaListener there, I cannot work out how to get it to
connect to my LocationManager (ie make it possible to use the routine
procedure NmeaListen(timestamp : int64; NmeaMessage : jString);

Dear Everyone,
I am still having the agonies of the damned trying to make some sense out of location stuff. Here is the latest contribution, using DW.FusedLocationAndroid. It compiles OK, loads OK, instals OK, then dies with “Java type com\delphiworlds/kastri/DWFusedLocationClient could not be found.”

I spent 7 hours with ChatGPT trying to sore it out. It kept talling me that I needed a Kastri.aar. I worked through multiple things Android Studio, and every suggestion failed until ChatGPT crashed at the end of it!

The files are on https://59b7770ca3fb18e4e90d-52e2682744779750b5103bbecf998085.ssl.cf2.rackcdn.com/Loc.zip
and this includes DW.fusedlocation..android.pas, and dw.kastri-base-3.0.0.jar.

Please can I trouble you experts for some help?

Like your previous error:

My previous answer applies:

i.e. NOT dw.kastri-base-3.0.0.jar

Thanks! Put that in, and don’t get the error message, but it crashes out as soon as you try to run it, with no error messages at all.

Are you including the metadata entry in the manifest as per this part of the instructions?

Which manifest file please?

app\android64\debug:
androidlibrarymanifest.txt
androidmanifest.xml (betting on this one? - and if so, will there be an android32 one similarly?)
androidmanifest-merged.xml
manifestgenerationpropertylist.txt
manifestmergepropertylist.txt

app:
androidmanifesttemplate.xml

Sticking with loc\android64\debug\AndroidManifest.xml:

There is no entry appoication-meta-data, so I tried the only two meta-data entries:

(1)
Under the <application section, <services,

        <meta-data
            android:name="photopicker_activity:0:required"
            android:value="" />

<meta-data android:name="com.google.android.gms.version" android:value="12451000" />
    </service>

this made no difference, with the program crashing as soon as the “Start” button is pressed.

(2)
Then tried in the <activity section:

        <meta-data
            android:name="android.app.lib_name"
            android:value="Loc" />
<meta-data android:name="com.google.android.gms.version" android:value="12451000" />

Same problem.

What do I try next please?

This was the right one:

Yay! Getting somewhere! I had to delete the Android64 subdirectory before it all came together without errors, but it’s looking good.

Despite setting a few things:
begin
FFOpt.FastestInterval := 1000;
FFOpt.Interval := 1000;
FFopt.SmallestDisplacement := 0;

if FFusedLocation = nil then
FFusedLocation := TFusedLocation.Create(Self, True);
FFusedLocation.SetOptions(FFopt);
FFusedLocation.UseCallback;

FFusedLocation.Start;

I only get one location value - it is not giving me a report every second, which is what I am hoping for. How can I get this please?

The interval is for when the location actually changes, i.e. if the device is moving. If the device is not moving, does your app need to report the same location every 1000ms? If so, save the value, and use a timer.

The RequestLastKnownLocation seems to to the job fine, with a timer.

When the programme terminates, an error occurs.
If I leave this destructor in, I get a pointer error.
If I just put “exit” in before the “Stop”, I get an access violation accessing address 8
Neither of these is a disaster, as the programme terminates anyway, but it is odd and untidy.

destructor tLocMainForm.Destroy;
begin
Stop;
if FFusedLocation <> nil then FFusedLocation.Free;
inherited;
end;

Just to give you the rationale:
One of the aims of the programme will be to track paths. With the defaults, or with the intervals set to 1000 each and the minimum distance set to 0, it takes about 20 to 30 metres to get the next location update. A lot can happen in 30 metres! Hence my interest in getting 1 second updates.

Next problem:

Another oddity:
If you use Start, then LocationUpdatesChange occurs with AActive true.

If then you use Stop, you get no LocationUpdatesChange, and RequestLastKnownLocation continues to give the same last location details (makes sense).

If you then press Start, you get 2 LocationUpdatesChange, both with AActive false, and it remains stopped.
If you again press Start, get a LocationUpdatesChange with AActive true, and it runs ok.
(But if you put “if not FFusedLocation.IsActive then Start” this doesn’t work either. You have to wait and push the button again.)

and, finally ifor today:

It doesn’t work on Android 10. How can I get it to please?

Might help to have more complete code, for the recent issues you are having.

Please define “doesn’t work”. Regardless, if I have time this evening I’ll see if I can get a device with Android 10 on it to check against.

Source etc is on
https://59b7770ca3fb18e4e90d-52e2682744779750b5103bbecf998085.ssl.cf2.rackcdn.com/Loc.zip

On Android 10: still get the LocationUpdatesChange messages, saying it’s active, but no LocationReceived messages.

Even using the RequestLastKnownLocation still don’t get any LocationReceived.

It would not be working on any version of Android above version 6, since your code does not request the relevant runtime permissions. Add System.Permissions to the uses clause and change the code in ButtonStartClick to:

procedure tLocMainForm.ButtonStartClick(Sender: TObject);
begin
  PermissionsService.RequestPermissions(['android.permission.ACCESS_FINE_LOCATION'],
    procedure(const APermissions: TClassicStringDynArray; const AGrantResults: TClassicPermissionStatusDynArray)
    begin
      if AGrantResults[0] = TPermissionStatus.Granted then
        Start;
    end
  );
end;