at3s 4 Posted February 20 (edited) I have a screen with the: LocationSensor: TLocationSensor; And code: procedure Tfrm.FormCreate(Sender: TObject); begin LocationSensor.Active := True; end; procedure Tfrm.FormClose(Sender: TObject; var Action: TCloseAction); begin LocationSensor.Active := False; Action := TCloseAction.caFree; end; procedure ShowLocation(); var mapPosition: TMapCoordinate; begin frm := Tfrm.Create(Application); try mapPosition := TMapCoordinate.Create(frm.LocationSensor.Sensor.Latitude, frm.LocationSensor.Sensor.Longitude); ShowMessage(FloatToStr(frm.LocationSensor.Sensor.Latitude) + ' | ' + FloatToStr(frm.LocationSensor.Sensor.Longitude)); finally frm.Show; frm.BringToFront; end; end; When I call ShowLocation(); in Android 12, it returns 'NaN | NaN' first time, after that each calling returns correct coordinates. Is it a known issue or did I miss something? Edited February 20 by at3s Share this post Link to post
Rollo62 539 Posted February 20 Have you performed a PermissionRequest before? Share this post Link to post
at3s 4 Posted February 20 44 minutes ago, Rollo62 said: Have you performed a PermissionRequest before? Yes, and a location finding works fine at the second and next times. When I did a trick with the repeat ... until + ShowMessage - after few times it found a location. But when I commented ShowMessage, it stopped to work at first execution. Weird behaviour. Share this post Link to post
at3s 4 Posted February 20 Ok. Somehow fixed using OnLocationChanged event. Share this post Link to post
Rollo62 539 Posted February 21 (edited) Yes, the location is called asynchronously. I also would not stress the system directly in FormCreate, with the activation of Location, where it is still loading and initializating. Better to do that at a later time, maybe FormShow, or even better, manually controlled on demand by your own code only. I'm not sure if you asked for PermissionRequest correctly, because I cannot see something similar like this in your code. The result should be in mainUI thread, but to ensure that this is true you can use ForceQueue, to protect this against mysterious situations. I know that Android systems might forgive many of such issues in debug mode, but clearly is at high risk to fail in release and PlayStore. 12 hours ago, at3s said: Yes, procedure Tfrm.FormShow(Sender: TObject); begin DoLocationActivate; end; procedure Tfrm.DoLocationActivate; begin TPermissionsService.DefaultService.RequestPermissions( [LPermissionLocationF, LPermissionLocationC] // PermissionResult , procedure ( const APermissions: TClassicStringDynArray; const AGrantResults: TClassicPermissionStatusDynArray ) begin if ( ( Length( AGrantResults ) <> 2 ) or ( ( AGrantResults[0] <> TPermissionStatus.Granted ) ) or ( ( AGrantResults[1] <> TPermissionStatus.Granted ) ) ) then begin exit; //user doesnt grant access end; TThread.ForceQueue( // this should not be necessary, but just to ensure that Active := True is really called in the main thread only procedure begin LocationSensor.Active := True; end ); end ); end; Edited February 21 by Rollo62 1 Share this post Link to post
at3s 4 Posted February 21 11 hours ago, Rollo62 said: Yes, the location is called asynchronously. I also would not stress the system directly in FormCreate, with the activation of Location, where it is still loading and initializating. Better to do that at a later time, maybe FormShow, or even better, manually controlled on demand by your own code only. I'm not sure if you asked for PermissionRequest correctly, because I cannot see something similar like this in your code. The result should be in mainUI thread, but to ensure that this is true you can use ForceQueue, to protect this against mysterious situations. I know that Android systems might forgive many of such issues in debug mode, but clearly is at high risk to fail in release and PlayStore. procedure Tfrm.FormShow(Sender: TObject); begin DoLocationActivate; end; procedure Tfrm.DoLocationActivate; begin TPermissionsService.DefaultService.RequestPermissions( [LPermissionLocationF, LPermissionLocationC] // PermissionResult , procedure ( const APermissions: TClassicStringDynArray; const AGrantResults: TClassicPermissionStatusDynArray ) begin if ( ( Length( AGrantResults ) <> 2 ) or ( ( AGrantResults[0] <> TPermissionStatus.Granted ) ) or ( ( AGrantResults[1] <> TPermissionStatus.Granted ) ) ) then begin exit; //user doesnt grant access end; TThread.ForceQueue( // this should not be necessary, but just to ensure that Active := True is really called in the main thread only procedure begin LocationSensor.Active := True; end ); end ); end; Yes, there is PermissionRequest in the code, but I did not provide it here. It executes before a screen showing. Your code works fine and it's more elegant and correct than my trick with the OnLocationChanged event, thanks for an answer. Share this post Link to post
Rollo62 539 Posted February 22 13 hours ago, at3s said: Yes, there is PermissionRequest in the code, but I did not provide it here. It executes before a screen showing. Yes, but if you touch the Location already in FormCreate, then the permission request comes later, and this will be problematic. That was my point. Share this post Link to post
at3s 4 Posted February 22 21 minutes ago, Rollo62 said: Yes, but if you touch the Location already in FormCreate, then the permission request comes later, and this will be problematic. That was my point. Thank you for your respond. Permission request is before screen create procedure calling, so it's ok, thanks again. Share this post Link to post