如何在Android 11上用Delphi 10.4分享二进制文件(SQLite数据库)
Android 11下Delphi分享SQLite文件失败的解决方案
你的问题核心在于Android 11(API 30+)的Scoped Storage权限限制,其他应用无法直接通过文件路径Uri(file://)访问你的应用存储目录下的文件,即使是你创建的共享目录。之前Android 10的代码逻辑在Android 11下失效,必须改用FileProvider来生成带临时访问权限的内容Uri,具体步骤如下:
1. 配置FileProvider
1.1 修改AndroidManifest.xml
在项目的AndroidManifest.xml中添加FileProvider配置,注意替换com.yourpackage.name为你的应用包名:
<provider android:name="androidx.core.content.FileProvider" android:authorities="com.yourpackage.name.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider>
1.2 创建文件路径配置文件
创建res/xml/file_paths.xml文件(需添加到Delphi项目的Deployment列表,部署路径设为res\xml),根据你的文件存储位置选择对应配置:
- 如果文件在应用外部私有目录(即
ExternalPath下的myapp):
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-files-path name="myapp_files" path="myapp/" /> </paths>
- 如果文件在公共文档目录(如
Documents/myapp):
<?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <external-path name="public_myapp" path="Documents/myapp/" /> </paths>
2. 修改Delphi分享代码
替换原有的Uri生成逻辑,改用FileProvider生成内容Uri,并添加临时访问权限:
var Database : String; intent : JIntent; FileObj : JFile; fileuri : JParcelable; Authority : string; begin Database := TPath.Combine(ExternalPath, 'file.db'); // 或对应公共目录路径 intent := TJIntent.Create; intent.setAction(TJIntent.JavaClass.ACTION_SEND); // 使用更精确的SQLite MIME类型,替代*/* intent.setType(StringToJString('application/x-sqlite3')); intent.putExtra(TJIntent.JavaClass.EXTRA_TEXT, StringToJString('Important data')); // 构建FileProvider的authority(与AndroidManifest中配置一致) Authority := JStringToString(SharedActivity.getPackageName) + '.fileprovider'; FileObj := TJFile.JavaClass.init(StringToJString(Database)); // 通过FileProvider生成带权限的Uri fileuri := JParcelable(TJFileProvider.JavaClass.getUriForFile(SharedActivity, StringToJString(Authority), FileObj)); intent.putExtra(TJIntent.JavaClass.EXTRA_STREAM, fileuri); // 给接收应用添加临时读取权限 intent.addFlags(TJIntent.JavaClass.FLAG_GRANT_READ_URI_PERMISSION); SharedActivity.startActivity(TJIntent.JavaClass.createChooser(intent, StrToJCharSequence('Share with'))); end;
关键说明
- Scoped Storage限制:Android 11禁止跨应用直接访问
file://类型的Uri,必须通过FileProvider这类ContentProvider机制提供临时访问权限。 - MIME类型优化:使用
application/x-sqlite3替代*/*,能让接收应用(如Telegram、邮件客户端)更准确识别文件类型,避免处理异常。 - 权限临时授予:
FLAG_GRANT_READ_URI_PERMISSION确保接收应用在本次分享过程中能读取该文件,无需永久权限。
内容的提问来源于stack exchange,提问作者alvaroc
相关产品推荐
相关产品推荐

