使用Delphi开发安卓应用无法打开本地PDF文件求解决方案
解决方案
问题根源
Android 7.0(API 24)及以上系统禁止外部应用直接访问file://格式的本地文件URI,必须通过系统提供的FileProvider组件生成content://格式的共享URI,同时正确授予临时读权限,才能让第三方PDF阅读器正常加载本地文件。
前置配置
- 打开Delphi项目的项目选项->应用程序->权限列表,确保启用对应版本权限:
- 安卓12及以下:
READ_EXTERNAL_STORAGE - 安卓13及以上:
READ_MEDIA_DOCUMENTS
- 安卓12及以下:
- 打开项目选项->应用程序->授权列表(Entitlement List),启用
Secure File Sharing选项,Delphi会自动在安卓清单文件中注册FileProvider,默认授权名为{你的应用包名}.fileprovider
兼容在线+本地PDF的实现代码
uses Androidapi.JNI.GraphicsContentViewText, Androidapi.JNI.Net, Androidapi.JNI.JavaTypes, Androidapi.Helpers, Androidapi.JNI.Provider, System.IOUtils; procedure OpenPDF(InpStrPDFPath: string); var LIntent: JIntent; LUri: Jnet_Uri; LFile: JFile; LAuthority: JString; begin LIntent := TJIntent.JavaClass.init(TJIntent.JavaClass.ACTION_VIEW); // 判断是在线PDF还是本地PDF if InpStrPDFPath.StartsWith('http://') or InpStrPDFPath.StartsWith('https://') then begin // 在线PDF直接用原有逻辑处理 LUri := StrToJURI(InpStrPDFPath); LIntent.SetDataAndType(LUri, StringToJString('application/pdf')); end else begin // 本地PDF先校验文件是否存在 if not TFile.Exists(InpStrPDFPath) then Exit; LFile := TJFile.JavaClass.init(StringToJString(InpStrPDFPath)); // 替换为你项目实际的安卓包名,格式为「包名.fileprovider」 LAuthority := StringToJString('com.your.package.name.fileprovider'); // 用FileProvider生成合规的content格式URI LUri := TJFileProvider.JavaClass.getUriForFile(TAndroidHelper.Context, LAuthority, LFile); LIntent.SetDataAndType(LUri, StringToJString('application/pdf')); // 授予第三方应用临时读权限 LIntent.setFlags(TJIntent.JavaClass.FLAG_GRANT_READ_URI_PERMISSION); end; TAndroidHelper.Activity.startActivity(LIntent); end;
注意事项
- 代码中
com.your.package.name需要替换为你项目实际设置的安卓应用包名,包名可在项目选项->应用程序->包名中查看 - 如果PDF文件存放在应用自身的私有目录(比如
TPath.GetDocumentsPath返回的路径),不需要申请存储权限,只要FileProvider配置正确即可正常共享 - 不要手动将本地文件路径拼接成
file://开头的字符串传入方法,直接传入系统返回的绝对路径即可
内容的提问来源于stack exchange,提问作者MyNameIsDeveloper
相关产品推荐
相关产品推荐

