Delphi 10.3 FMX应用TLocationSensor激活时崩溃问题求助
Delphi 10.3 FMX TLocationSensor启用精确定位时崩溃问题排查
环境信息
- Delphi版本:10.3
- Android API版本:28
- 测试设备:三星Galaxy A52S 5G
测试场景与现象
- 无位置权限:应用正常运行,
TLocationSensor未激活 - 授予「始终允许」权限但关闭精确定位:应用正常运行,
TLocationSensor未激活 - 授予「始终允许」权限且启用精确定位:应用崩溃,但
TLocationSensor处于激活状态
原始代码
unit Unit1; interface uses System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Controls.Presentation, FMX.StdCtrls, System.Sensors, System.Sensors.Components; type TForm1 = class(TForm) LocationSensor1: TLocationSensor; private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.fmx}
问题原因
- Delphi 10.3对Android API28的位置服务适配存在缺陷,
TLocationSensor在获取精确定位时,未正确处理原生位置服务回调中的异常或空值,触发崩溃。 - 三星Galaxy A52S 5G的位置服务实现与标准Android存在差异,进一步放大了适配问题。
- API28开始对「始终允许」的位置权限要求更严格,缺少
ACCESS_BACKGROUND_LOCATION权限声明可能加剧异常。
解决方案
1. 延迟激活传感器并添加异常捕获
不要在设计时设置Active := True,改为运行时先检查权限,再手动激活,同时捕获可能的异常。
2. 补充必要权限
在AndroidManifest.xml中添加ACCESS_BACKGROUND_LOCATION权限(API28及以上版本,「始终允许」权限需要此声明)。
3. 升级Delphi版本(可选)
条件允许的话,升级到Delphi 10.4及以上版本,这些版本修复了大量Android位置服务的适配问题。
修改后的示例代码
unit Unit1; interface uses System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Controls.Presentation, FMX.StdCtrls, System.Sensors, System.Sensors.Components, Androidapi.Helpers, Androidapi.JNI.Os; type TForm1 = class(TForm) LocationSensor1: TLocationSensor; procedure FormCreate(Sender: TObject); procedure LocationSensor1LocationChanged(Sender: TObject; const OldLocation, NewLocation: TLocationCoord2D); private function CheckLocationPermissions: Boolean; public { Public declarations } end; var Form1: TForm1; implementation {$R *.fmx} procedure TForm1.FormCreate(Sender: TObject); begin if CheckLocationPermissions then begin try LocationSensor1.Active := True; except on E: Exception do ShowMessage('激活位置传感器失败:' + E.Message); end; end; end; function TForm1.CheckLocationPermissions: Boolean; var FineLocPerm, BackgroundLocPerm: string; begin FineLocPerm := JStringToString(TJManifest_permission.JavaClass.ACCESS_FINE_LOCATION); BackgroundLocPerm := JStringToString(TJManifest_permission.JavaClass.ACCESS_BACKGROUND_LOCATION); Result := (TAndroidHelper.Context.checkSelfPermission(StringToJString(FineLocPerm)) = TJPackageManager.JavaClass.PERMISSION_GRANTED) and (TAndroidHelper.Context.checkSelfPermission(StringToJString(BackgroundLocPerm)) = TJPackageManager.JavaClass.PERMISSION_GRANTED); end; procedure TForm1.LocationSensor1LocationChanged(Sender: TObject; const OldLocation, NewLocation: TLocationCoord2D); begin try // 处理位置更新逻辑 ShowMessage(Format('当前位置:纬度%.4f,经度%.4f', [NewLocation.Latitude, NewLocation.Longitude])); except on E: Exception do ShowMessage('处理位置数据失败:' + E.Message); end; end; end.
补充AndroidManifest.xml权限
在项目的AndroidManifest.xml中添加以下权限声明:
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" />
内容的提问来源于stack exchange,提问作者KissGe
相关产品推荐
相关产品推荐

