如何在Delphi 11.3中调用Android 13默认地图应用?
Android 13下Delphi 11.3导航Intent失效(Receiver not found)问题解决
问题描述
在Delphi 11.3开发的Android应用中,通过Intent调用默认地图应用(Google Maps、Waze等)导航到指定经纬度的代码,在旧版Android和Delphi中正常运行,但在Android 13下点击导航按钮时持续显示“Receiver not found”提示。当前AndroidManifest.xml已配置以下位置权限:
android:targetSdkVersion="32" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" />导航按钮点击事件代码如下:
procedure TMainForm.NavigateBtnClick(Sender: TObject); var {$IFDEF ANDROID} Intent: JIntent; //Declares the intent object {$ENDIF} LGoogleMapsURL: String; begin // Populate a string to send to Mapping app LGoogleMapsURL:= 'google.navigation:q=37.422219,-122.08364&mode=d'; {$IFDEF MSWINDOWS} WebBrowser1.Navigate(LGoogleMapsURL); {$ENDIF} {$IFDEF ANDROID} Intent := TJIntent.Create; Intent.setData(StrToJURI(LGoogleMapsURL)); Intent.setAction(TJIntent.JavaClass.ACTION_VIEW); Intent.putExtra(TJIntent.JavaClass.EXTRA_TEXT, StringToJString(LGoogleMapsURL)); if MainActivity.getPackageManager.queryIntentActivities(Intent, TJPackageManager.JavaClass.MATCH_DEFAULT_ONLY).size > 0 then begin MainActivity.startActivity(Intent); end else ShowMessage('Receiver not found'); {$ENDIF} end;请问该代码在Android 13中是否已失效,或是存在遗漏配置?
问题原因及修复方案
核心原因
Android 13对Intent的匹配逻辑更严格,当前代码存在两个关键问题:
- 仅使用Google Maps专属的
google.navigation:URI,无法被Waze等其他地图应用识别,导致queryIntentActivities找不到匹配项; - 冗余添加了
EXTRA_TEXT参数,干扰Intent的匹配逻辑。
修复步骤
1. 改用通用geo: URI协议(推荐)
使用Android标准的地理URI协议,兼容绝大多数地图应用:
procedure TMainForm.NavigateBtnClick(Sender: TObject); var {$IFDEF ANDROID} Intent: JIntent; {$ENDIF} LGeoURL: String; begin // 标准geo协议格式:geo:纬度,经度?q=纬度,经度(目的地标签)&mode=导航模式(d=驾车/w=步行/b=骑行) LGeoURL := 'geo:37.422219,-122.08364?q=37.422219,-122.08364&mode=d'; {$IFDEF MSWINDOWS} WebBrowser1.Navigate(LGeoURL); {$ENDIF} {$IFDEF ANDROID} // 直接通过构造函数初始化Intent,简化代码 Intent := TJIntent.Create(TJIntent.JavaClass.ACTION_VIEW, StrToJURI(LGeoURL)); if MainActivity.getPackageManager.queryIntentActivities(Intent, TJPackageManager.JavaClass.MATCH_DEFAULT_ONLY).size > 0 then MainActivity.startActivity(Intent) else ShowMessage('未找到支持导航的应用'); {$ENDIF} end;
2. 保留Google Maps专属URI并兼容其他应用
如果需要优先支持Google Maps,可保留google.navigation: URI,同时添加geo: URI作为降级方案:
procedure TMainForm.NavigateBtnClick(Sender: TObject); var {$IFDEF ANDROID} Intent: JIntent; {$ENDIF} LGoogleMapsURL, LGeoURL: String; begin LGoogleMapsURL := 'google.navigation:q=37.422219,-122.08364&mode=d'; LGeoURL := 'geo:37.422219,-122.08364?q=37.422219,-122.08364&mode=d'; {$IFDEF MSWINDOWS} WebBrowser1.Navigate(LGoogleMapsURL); {$ENDIF} {$IFDEF ANDROID} Intent := TJIntent.Create(TJIntent.JavaClass.ACTION_VIEW, StrToJURI(LGoogleMapsURL)); if MainActivity.getPackageManager.queryIntentActivities(Intent, TJPackageManager.JavaClass.MATCH_DEFAULT_ONLY).size > 0 then MainActivity.startActivity(Intent) else begin // 降级使用通用geo协议 Intent := TJIntent.Create(TJIntent.JavaClass.ACTION_VIEW, StrToJURI(LGeoURL)); if MainActivity.getPackageManager.queryIntentActivities(Intent, TJPackageManager.JavaClass.MATCH_DEFAULT_ONLY).size > 0 then MainActivity.startActivity(Intent) else ShowMessage('未找到支持导航的应用'); end; {$ENDIF} end;
3. 确保运行时位置权限已授权
Android 13及以上版本中,位置权限需运行时申请,即使Manifest中已声明。可在导航前添加权限检查:
procedure TMainForm.NavigateBtnClick(Sender: TObject); var {$IFDEF ANDROID} Intent: JIntent; {$ENDIF} LGeoURL: String; begin {$IFDEF ANDROID} // 检查位置权限 if not PermissionsService.IsPermissionGranted(ACCESS_FINE_LOCATION) then begin PermissionsService.RequestPermissions([ACCESS_FINE_LOCATION], procedure(const APermissions: TArray<string>; const AGrantResults: TArray<TPermissionStatus>) begin if AGrantResults[0] = TPermissionStatus.Granted then NavigateBtnClick(Sender) // 权限通过后重新执行导航逻辑 else ShowMessage('需要位置权限以完成导航'); end); Exit; end; {$ENDIF} LGeoURL := 'geo:37.422219,-122.08364?q=37.422219,-122.08364&mode=d'; {$IFDEF MSWINDOWS} WebBrowser1.Navigate(LGeoURL); {$ENDIF} {$IFDEF ANDROID} Intent := TJIntent.Create(TJIntent.JavaClass.ACTION_VIEW, StrToJURI(LGeoURL)); if MainActivity.getPackageManager.queryIntentActivities(Intent, TJPackageManager.JavaClass.MATCH_DEFAULT_ONLY).size > 0 then MainActivity.startActivity(Intent) else ShowMessage('未找到支持导航的应用'); {$ENDIF} end;
4. 可选:升级Target SDK版本
当前targetSdkVersion为32,升级到33(Android 13)可更好适配系统行为,无需额外权限声明,但此调整不是解决该问题的核心。
内容的提问来源于stack exchange,提问作者Hackbrew
相关产品推荐
相关产品推荐

