Can't find location stuff

I am switching a location-using programme from LocationListener to FusedLocationProvider.

The uses list is:
Androidapi.JNI.Location, Androidapi.JNIBridge, Androidapi.JNI.JavaTypes,
Androidapi.JNI.Os, FMX.Helpers.Android, AndroidAPI.Looper,
Androidapi.Helpers, Androidapi.JNI.GraphicsContentViewText,

I have pulled down from Kastri dw-fusedlocation-3.0.0.jar, which I have tried using
Project/Add To Project, and putting it in the library stuff under Android64 on the top
right hand side of the screen.

However, with all of that, I get errors where Delphi cannot find things:

tFusedLocationCallback = class(tJavaLocal, JLocationCallback)
(jLocationCallback is undefined)

   FLocationClient: JFusedLocationProviderClient;

(so is jFusedLocationProviderClient)

Please can anyone tell me how to get this right?

Chester Wilson

There’s no example included in Kastri?

If you’re compiling for both Android 32-bit and Android 64-bit, you should add it to Libraries under Android 32-bit. The compiler will “find” it in both cases.

It’s not in the Delphi RTL, however it is in DW.Androidapi.JNI.Location.pas in Kastri (API folder)

There is no import for that in either. dw-fusedlocation-3.0.0.jar does however use the Java class (FusedLocationProviderClient).

I’d recommend this demo over the one Ian posted.

Yeah, stupid Ian… :zany_face:

Thanks, Dave. I have spent the last 2 hours pulling down 33 files from Kastri required for the demo, and after pulling them down and adding them to both the demo project and the demo service project, I get the error:

Checking project dependencies…
Compiling ABLSticky.dproj (Debug, Android64)
brcc32 command line for “ABLSticky.vrc”
c:\program files (x86)\embarcadero\studio\23.0\bin\cgrc.exe -c65001 “ABLSticky.vrc” -foABLSticky.res
dccaarm64 command line for “ABLSticky.dpr”
c:\program files (x86)\embarcadero\studio\23.0\bin\dccaarm64.exe -$O- -$R+ -$Q+ --no-config -M -Q -TX.so
-AGenerics.Collections=System.Generics.Collections;Generics.Defaults=System.Generics.Defaults -DDEBUG;;FRAMEWORK_FMX -E.\Android64\Debug
-I"c:\program files (x86)\embarcadero\studio\23.0\lib\Android64\debug";…\API;…\Core;…\Features\Location;“c:\program files
(x86)\embarcadero\studio\23.0\lib\Android64\Release”;C:\Users\Public\Documents\Embarcadero\Studio\23.0\Dcp\Android64
-LEC:\Users\Public\Documents\Embarcadero\Studio\23.0\Bpl\Android64 -LNC:\Users\Public\Documents\Embarcadero\Studio\23.0\Dcp\Android64
-NU.\Android64\Debug -NSSystem;Xml;Data;Datasnap;Web;Soap; -O…\API;…\Core;…\Features\Location;“c:\program files
(x86)\embarcadero\studio\23.0\lib\Android64\Release”;C:\Users\Public\Documents\Embarcadero\Studio\23.0\Dcp\Android64 -R…\API;…\Core;
…\Features\Location;“c:\program files (x86)\embarcadero\studio\23.0\lib\Android64\Release”;
C:\Users\Public\Documents\Embarcadero\Studio\23.0\Dcp\Android64 -U"c:\program files (x86)\embarcadero\studio\23.0\lib\Android64\debug";…\API;
…\Core;…\Features\Location;“c:\program files (x86)\embarcadero\studio\23.0\lib\Android64\Release”;
C:\Users\Public\Documents\Embarcadero\Studio\23.0\Dcp\Android64
–compiler-rt:C:\Users\Public\Documents\Embarcadero\Studio\23.0\CatalogRepository\AndroidSDK-2525-23.0.55362.2017\ndk\27.1.12297006\toolchains\llvm\prebuilt\windows-x86_64\lib\clang\18\lib\linux\libclang_rt.builtins-aarch64-android.a
–libpath:C:\Users\Public\Documents\Embarcadero\Studio\23.0\CatalogRepository\AndroidSDK-2525-23.0.55362.2017\ndk\27.1.12297006\toolchains\llvm\prebuilt\windows-x86_64\sysroot\usr\lib\aarch64-linux-android\23;
C:\Users\Public\Documents\Embarcadero\Studio\23.0\CatalogRepository\AndroidSDK-2525-23.0.55362.2017\ndk\27.1.12297006\toolchains\llvm\prebuilt\windows-x86_64\sysroot\usr\lib\aarch64-linux-android
–linker:C:\Users\Public\Documents\Embarcadero\Studio\23.0\CatalogRepository\AndroidSDK-2525-23.0.55362.2017\ndk\27.1.12297006\toolchains\llvm\prebuilt\windows-x86_64\bin\ld.lld.exe
-V -VN -NO.\Android64\Debug ABLSticky.dpr
[DCC Hint] Unit1.pas(66): H2443 Inline function ‘StringToJString’ has not been expanded because unit ‘Androidapi.JNI.JavaTypes’ is not specified in USES list
[DCC Hint] Unit1.pas(71): H2443 Inline function ‘StringToJString’ has not been expanded because unit ‘Androidapi.JNI.JavaTypes’ is not specified in USES list
[DCC Hint] Unit1.pas(71): H2443 Inline function ‘JStringToString’ has not been expanded because unit ‘Androidapi.JNI.JavaTypes’ is not specified in USES list
Success
Elapsed time: 00:00:04.3
Deploy
paclient command line
c:\program files (x86)\embarcadero\studio\23.0\bin\paclient.exe -u8 --Clean=“.\Android64\Debug\ABLSticky,C:\delphi\PeteA\ABL
Sticky\ABLSticky.@emb.tmp
[MSBuild Error] The “CreateAndroidManifestFile” task failed unexpectedly.
System.IO.DirectoryNotFoundException: Could not find a part of the path ‘C:\delphi\PeteA\ABL Sticky\Service\Android\Debug\ABLStickyService.jar’.
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)
at System.IO.StreamReader..ctor(String path, Encoding encoding, Boolean detectEncodingFromByteOrderMarks, Int32 bufferSize, Boolean checkHost)
at System.IO.StreamReader..ctor(String path)
at Borland.Build.Tasks.Shared.CreateAndroidManifestFile.GetAndroidService(String JarFile)
at Borland.Build.Tasks.Shared.CreateAndroidManifestFile.WriteServicesStr()
at Borland.Build.Tasks.Shared.CreateAndroidManifestFile.genManifestFile()
at Borland.Build.Tasks.Shared.CreateAndroidManifestFile.Execute()
at Microsoft.Build.BuildEngine.TaskEngine.ExecuteInstantiatedTask(EngineProxy engineProxy, ItemBucket bucket, TaskExecutionMode howToExecuteTask, ITask task, Boolean& taskResult)
Failed
Elapsed time: 00:00:00.3

Where do I go from here please?

Chester.

No. (Not that I could find)

It appears you are just loading the project, rather than the group

I have taken the service module, and am trying to beat it into submission as a very basic programme.
A couple of things are still a problem.

In the service module, JLocation says that it is in DW.Androidapi.JNI.Location. However,
including that in the project still does not define it, and changing the reference to
DW.Androidapi.JNI.Location.jLocation does not help either.

Similarly with trying to get the priority:
TJLocationRequest.JavaClass.PRIORITY_HIGH_ACCURACY prangs out at the “JavaClass”, even with
DW.Androidapi.JNI.Location.TJLocationRequest.JavaClass.PRIORITY_HIGH_ACCURACY specified.

Here’s the code:

unit ExperimentalLocationMainUnit;

interface

uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Memo.Types,
FMX.ScrollBox, FMX.Memo, FMX.Controls.Presentation, FMX.StdCtrls,
DW.Androidapi.JNI.Os, DW.Androidapi.JNI.Location, DW.FusedLocation.Android;

type
TExperimentalLocationMainForm = class(TForm)
ButtonStart: TButton;
ButtonStop: TButton;
Memo1: TMemo;
procedure FormCreate(Sender: TObject);
procedure ButtonStartClick(Sender: TObject);
procedure ButtonStopClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
procedure LocationReceived(const ALocation: JLocation);
procedure LocationUpdatesChange(const AIsActive: Boolean);
end;

var
ExperimentalLocationMainForm: TExperimentalLocationMainForm;
FFusedLocation: IFusedLocation;
FusedLocationOptions : tFusedLocationOptions;
tempint1, tempint2, tempint3, tempint4 : integer;

implementation

{$R *.fmx}

uses
DW.Androidapi.JNI.App;

procedure TExperimentalLocationMainForm.LocationReceived(const ALocation: JLocation);
begin
Memo1.Lines.Add('Latitude ’ + Format(‘Latitude: %d12.7, Longitude: %d12.7, Accuracy : %d5.2’,
ALocation.Latitude, Alocation.Longitude, Alocation.Accuracy));
end;

procedure TExperimentalLocationMainForm.LocationUpdatesChange(const AIsActive: Boolean);
begin
tempint1 := 1;
end;

procedure TExperimentalLocationMainForm.ButtonStartClick(Sender: TObject);
begin
FusedLocationOptions.Interval := 1000;
FusedLocationOptions.Priority := TJLocationRequest.JavaClass.PRIORITY_HIGH_ACCURACY;
FFusedLocation.SetOptions(FusedLocationOptions);

FFusedLocation.Start;

end;

procedure TExperimentalLocationMainForm.ButtonStopClick(Sender: TObject);
begin
FFusedLocation.Stop;
end;

procedure TExperimentalLocationMainForm.FormCreate(Sender: TObject);
begin
FFusedLocation := TFusedLocation.Create(Self, True);

end;

end.

Actually, JLocation is in Androidapi.JNI.Location (i.e. the Delphi RTL)

It works OK here. Are you sure you have the API folder of Kastri in the IDE library or project search path?

If I type in “uses Androidapi.JNI.Location,” it prangs on the “Location”. (using Delphi 12.3). I took the libraries back to the default ones, but no help.

How do I get my grubby paws on the API folder of Kastri? I have only ever been able to get files one at a time from Kastri - a tedious process!

Not sure why that might be. It’s definitely an RTL unit in 12.3. I assume the target platform set to an Android one?

I strongly recommend using a Git client. Otherwise, you can download the entire source using the green Code button on this page, and selecting Download zip.

Well, I have done a complete uninstal and reinstal (but this time Delphi 13) on both the laptop and the desktop. The errors as mentioned above seem to have cleared - but wait! there’s more. While I managed to get a java

C:\Program Files\Eclipse Adoptium\jdk-21.0.7.6-hotspot replacing the Delphi 12.3

C:\Program Files\Eclipse Adoptium\jdk-170.9.9-hotspot

on deploying a programme I get

C:\Program Files\Eclipse Adoptium\jdk-170.9.9-hotspot\lib\bin\jave.exe not found.

I cannot find how to change the JDK path - the SDK options for java are not helpful.

Unfortunately, the Java settings for the Android SDK are not terribly clear about their effect. Changing the locations for keytool.exe and jarsigner.exe should update what the IDE uses for the JDK path

I got into Tools/Manage Features, removed SDK/NDK and Java, got out, deleted all their subdirecories, and put them back in. It now works! Well, no compile errors, anyway.

Now for the program again. I have no idea what an “iFusedLocationOwner”, so just defined one, as IFLO : iFusedLocationOwner;.

Now it prangs on TFusedLocation.Create(IFLO, True), saying that it cannot find tFusedLocationClientDelegate in DW.FusedLocation.Android.

Here’s the code:

unit ExperimentalLocationMainUnit;

interface

uses Androidapi.JNI.Location,
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Memo.Types,
FMX.ScrollBox, FMX.Memo, FMX.Controls.Presentation, FMX.StdCtrls,
DW.Androidapi.JNI.Os, DW.Androidapi.JNI.Location, DW.FusedLocation.Android;

type
TExperimentalLocationMainForm = class(TForm)
ButtonStart: TButton;
ButtonStop: TButton;
Memo1: TMemo;
procedure ButtonStartClick(Sender: TObject);
procedure ButtonStopClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
procedure LocationReceived(const ALocation: JLocation);
procedure LocationUpdatesChange(const AIsActive: Boolean);
end;

var
ExperimentalLocationMainForm: TExperimentalLocationMainForm;
FFusedLocation: IFusedLocation;
FusedLocationOptions : tFusedLocationOptions;
tempint1, tempint2, tempint3, tempint4 : integer;

IFLO : iFusedLocationOwner;

implementation

{$R *.fmx}

uses
DW.Androidapi.JNI.App;

procedure TExperimentalLocationMainForm.LocationReceived(const ALocation: JLocation);
begin
Memo1.Lines.Add('Latitude ’ + Format(‘Latitude: %d12.7, Longitude: %d12.7, Accuracy : %d5.2’,
[ALocation.getLatitude, Alocation.getLongitude, Alocation.getAccuracy]));
end;

procedure TExperimentalLocationMainForm.LocationUpdatesChange(const AIsActive: Boolean);
begin
tempint1 := 1;
end;

procedure TExperimentalLocationMainForm.ButtonStartClick(Sender: TObject);
begin
if FFusedLocation = nil then FFusedLocation := TFusedLocation.Create(IFLO, True);

FusedLocationOptions.Interval := 1000;
FusedLocationOptions.Priority := TJLocationRequest.JavaClass.PRIORITY_HIGH_ACCURACY;
FFusedLocation.SetOptions(FusedLocationOptions);

FFusedLocation.Start;

end;

procedure TExperimentalLocationMainForm.ButtonStopClick(Sender: TObject);
begin
FFusedLocation.Stop;
end;

end.

It might help if you look at ABLS.ServiceModule.pas in the demo, specifically, that TServiceModule implements IFusedLocationOwner, and the code where FFusedLocation is created.

Getting somewhere, Dave.  No compilation errors, and I have tried to understand the stuff in the service module.  Unfortunately I am now getting

First chance exception at $00000075F85356D8. Exception class EJNIFatal with message 'Java type com/delphiworlds/kastri/DWFusedLocationClientDelegate could not be found'. Process ExperimentalLocation.apk (4783)

Source code is
unit ExperimentalLocationMainUnit;

interface

uses   Androidapi.JNI.Location, System.Android.Service, DW.ServiceManager.Android,
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Memo.Types,
  FMX.ScrollBox, FMX.Memo, FMX.Controls.Presentation, FMX.StdCtrls,
  DW.Androidapi.JNI.Os, DW.Androidapi.JNI.Location, DW.FusedLocation.Android;

type
   tServiceModule = class(tAndroidService, iFusedLocationOwner)
      fFusedLocation : iFusedLocation;
      procedure SetUpStuff;
      procedure LocationUpdatesChange(const aIsActive: boolean);
      procedure LocationReceived(const aLocation : jLocation);
   end;


type
  TExperimentalLocationMainForm = class(TForm)
    ButtonStart: TButton;
    ButtonStop: TButton;
    Memo1: TMemo;
    procedure ButtonStartClick(Sender: TObject);
    procedure ButtonStopClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    procedure LocationReceived(const ALocation: JLocation);
    procedure LocationUpdatesChange(const AIsActive: Boolean);
  end;

var
   ExperimentalLocationMainForm: TExperimentalLocationMainForm;

   SM : tServiceModule;

   FusedLocationOptions : tFusedLocationOptions;
   tempint1, tempint2, tempint3, tempint4 : integer;

implementation

{$R *.fmx}

uses
  DW.Androidapi.JNI.App;



procedure tServiceModule.SetUpStuff;
begin
   if SM.FFusedLocation = nil then
      SM.FFusedLocation := TFusedLocation.Create(Self, True);

   FusedLocationOptions.Interval := 1000;
   FusedLocationOptions.Priority := TJLocationRequest.JavaClass.PRIORITY_HIGH_ACCURACY;
   SM.FFusedLocation.SetOptions(FusedLocationOptions);


end;


procedure tServiceModule.LocationReceived(const ALocation: JLocation);
begin
   LocationReceived(aLocation);
end;

procedure tServiceModule.LocationUpdatesChange(const AIsActive: Boolean);
begin
    LocationUpdatesChange(aIsActive);
end;



procedure TExperimentalLocationMainForm.LocationReceived(const ALocation: JLocation);
begin
   Memo1.Lines.Add('Latitude ' + Format('Latitude: %d12.7,   Longitude: %d12.7, Accuracy : %d5.2',
      [aLocation.getLatitude, aLocation.getLongitude, alocation.getAccuracy]));
end;

procedure TExperimentalLocationMainForm.LocationUpdatesChange(const AIsActive: Boolean);
begin
   tempint1 := 1;
end;


procedure TExperimentalLocationMainForm.ButtonStartClick(Sender: TObject);
begin
   SM.SetUpStuff;

   SM.FFusedLocation.Start;
end;

procedure TExperimentalLocationMainForm.ButtonStopClick(Sender: TObject);
begin
   SM.FFusedLocation.Stop;
end;



end.

That would mean that dw-fused-location-3.0.0.jar is not properly added to the project. See this section of the readme.

Still struggling, Dave.

I took the Kastri library (with the big green button), and
put all the .pas and .jar files into one subdirectory so I
can add them more easily.  I put the dw-fusedlocation-3.0.0.jar
and dw-kastri-base-3.0.0.jar into the android32 library list,
and unfortunately still get

Project ExperimentalLocation.apk raised exception class
EAccessViolation with message 'Access violation at address
00000075F9a8D158 accessing address 150'

As I had added a pointer p := SM, and it died on this,
I thought that maybe the declaration SM : tServiceModule was 
insufficient, so put SM := tServiceModule.Create(form)

It prangs on this Create, with the message
Resouce tServiceModule not found.

I had removed all the ServiceManager stuff as I am not
trying to run this as a service, just as a subrouutine
in a bigger programme.  Does it require that even without
being a service?