在我的 Android 应用程序中,一些日志按日期写入文件(例如,写入文件
20.06.2024.txt
),能够收集 zip
存档中的所有文件并通过应用程序共享/通过电子邮件发送。存档文件附在信件上,在所有设备上都没有任何问题,除了经过测试的 6 台设备之一 - Xiaomi。在此设备上,我在日志中看到错误:
Writing exception to parcel
java.lang.SecurityException: Permission Denial: reading androidx.core.content.FileProvider uri content://com.own.vpn.provider/files/logs/VPN_logs.zip from pid=6231, uid=1000 requires the provider to be exported , or grantUriPermission()
我的提供商在清单中定义:
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_provider_paths" />
</provider>
文件提供者路径
<?xml version="1.0" encoding="utf-8"?>
<paths>
<files-path name="files" path="/" />
</paths>
分享意向的方法
override fun goToFileSharing(logFile: File, shareWith: ShareWith) {
// i get correct uri: content://com.own.vpn.provider/files/logs/VPN_logs.zip
val fileUri: Uri = FileProvider.getUriForFile(
context,
"${BuildConfig.APPLICATION_ID}$AUTHORITY_EXTENSION", // AUTHORITY_EXTENSION = ".provider"
logFile
)
val fileType = if (logFile.extension == LOG_FILE_EXTENSION_TXT)
FILE_TYPE_TXT
else
FILE_TYPE_ZIP
openApplicationChooser(fileUri, fileType)
}
private fun openApplicationChooser(fileUri: Uri, fileType: String) {
val intent = Intent(Intent.ACTION_SEND).apply {
// E-mail attachment
setDataAndType(fileUri, fileType)
putExtra(Intent.EXTRA_STREAM, fileUri)
}
// Applications chooser
val shareIntent = Intent.createChooser(
intent,
null
).apply { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) }
startActivity(context, shareIntent, null)
}
UPD 打开选择器时出现的第一个错误。当我选择任何应用程序(例如 gmail)时 - 我收到另一个错误:
Failed to find provider info for com.own.vpn.provider
。但在其他设备上一切正常...
错误是由于小米处理URI权限的方式导致的
尝试下面的代码:
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="logs" path="logs/"/>
</paths>
goToFileSharing
:override fun goToFileSharing(logFile: File, shareWith: ShareWith) {
val fileUri: Uri = FileProvider.getUriForFile(
context,
"${BuildConfig.APPLICATION_ID}$AUTHORITY_EXTENSION", // AUTHORITY_EXTENSION = ".provider"
logFile
)
val fileType = if (logFile.extension == LOG_FILE_EXTENSION_TXT)
FILE_TYPE_TXT
else
FILE_TYPE_ZIP
openApplicationChooser(fileUri, fileType)
}
private fun openApplicationChooser(fileUri: Uri, fileType: String) {
val intent = Intent(Intent.ACTION_SEND).apply {
// E-mail attachment
setDataAndType(fileUri, fileType)
putExtra(Intent.EXTRA_STREAM, fileUri)
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
// Applications chooser
val shareIntent = Intent.createChooser(
intent,
null
).apply { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) }
startActivity(context, shareIntent, null)
}
注意:确保 MIUI 优化不会干扰您的应用程序的行为。