在 Android 10 中创建和共享一个简单的文本文件
Creating & sharing a simple text file in Android 10
我在创建将大量原始数据写入文本文件然后共享该文本文件以供 email/whatsapp 发送的函数时遇到了一些问题。自 Android 10 起,由于隐私原因,无法再使用 Environment.getExternalStorageDir()
。现在看来我的文件对其他应用程序不可见,因此无法被它们打开。我的代码如下:
负责导出的片段:
CoroutineScope(Dispatchers.IO).launch {
withContext(Dispatchers.IO) {
val data: String = retrieveData() ?: return@withContext
val file = File(requireContext().getExternalFilesDir(null), "export.xml")
val outputStream =
requireContext().openFileOutput("export.xml", Context.MODE_PRIVATE)
outputStream.write(data.toByteArray())
outputStream.close()
val uri = FileProvider.getUriForFile(requireContext(),BuildConfig.APPLICATION_ID, file)
val shareIntent = Intent().apply {
type = "text/plain"
action = Intent.ACTION_SEND
putExtra(Intent.EXTRA_STREAM, uri)
putExtra(Intent.EXTRA_SUBJECT, getString(R.string.share_file_subject))
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
startActivity(
Intent.createChooser(
shareIntent,
getString(R.string.share_file_subject)
)
)
}
}
清单中:
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" />
</provider>
filepaths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-files-path
name="files"
path="/" />
</paths>
使用 Android Studio 文件资源管理器时,我可以看到创建的文件内容正确。 Uri 指向:content://myApplicationId/files/export.xml
并且该文件位于我设备上的 data/data/myApplicationId/files
但我似乎无法弄清楚如何让其他应用程序可以打开它。
当使用例如 gmail 应用程序打开它时,它会创建一个新概念并填充主题,但我从 gmail 应用程序中得到一个 Toast,上面写着 'Unable to add attachment'。意图似乎正确触发,因此我的代码中没有发生异常。我的猜测是由于某种原因其他应用程序仍然无法访问该文件。
有什么建议吗?
提前致谢。
The Uri points to: content://myApplicationId/files/export.xml
但你没有使用那个 Uri
。您正在使用 Uri.fromFile()
:
val shareIntent = Intent().apply {
type = "text/plain"
putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file))
putExtra(Intent.EXTRA_SUBJECT, getString(R.string.share_file_subject))
您应该在 Android 7.0+ 上因 FileUriExposedException
崩溃,所以您已经应用了 hack 来解决这个问题。只是现在,在 Android 10+ 上,该 hack 的价值有限。
因此,将 Uri.fromFile(file)
替换为 uri
。此外,将 addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
作为 apply {}
lambda 的一部分包含在内。并找到您在代码中配置 StrictMode
的位置,并让它抱怨 FileUriExposedException
,至少在 debug
构建中。
另外,你的I/O乱七八糟。
val file = File(requireContext().getExternalFilesDir(null), "export.xml")
val outputStream =
requireContext().openFileOutput("export.xml", Context.MODE_PRIVATE)
您的代码假定 openFileOutput()
将其内容放在 getExternalFilesDir()
标识的位置,这是不正确的。将后一行切换为:
val outputStream = FileOutputStream(file)
我在创建将大量原始数据写入文本文件然后共享该文本文件以供 email/whatsapp 发送的函数时遇到了一些问题。自 Android 10 起,由于隐私原因,无法再使用 Environment.getExternalStorageDir()
。现在看来我的文件对其他应用程序不可见,因此无法被它们打开。我的代码如下:
负责导出的片段:
CoroutineScope(Dispatchers.IO).launch {
withContext(Dispatchers.IO) {
val data: String = retrieveData() ?: return@withContext
val file = File(requireContext().getExternalFilesDir(null), "export.xml")
val outputStream =
requireContext().openFileOutput("export.xml", Context.MODE_PRIVATE)
outputStream.write(data.toByteArray())
outputStream.close()
val uri = FileProvider.getUriForFile(requireContext(),BuildConfig.APPLICATION_ID, file)
val shareIntent = Intent().apply {
type = "text/plain"
action = Intent.ACTION_SEND
putExtra(Intent.EXTRA_STREAM, uri)
putExtra(Intent.EXTRA_SUBJECT, getString(R.string.share_file_subject))
addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
startActivity(
Intent.createChooser(
shareIntent,
getString(R.string.share_file_subject)
)
)
}
}
清单中:
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="${applicationId}"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/filepaths" />
</provider>
filepaths.xml
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-files-path
name="files"
path="/" />
</paths>
使用 Android Studio 文件资源管理器时,我可以看到创建的文件内容正确。 Uri 指向:content://myApplicationId/files/export.xml
并且该文件位于我设备上的 data/data/myApplicationId/files
但我似乎无法弄清楚如何让其他应用程序可以打开它。
当使用例如 gmail 应用程序打开它时,它会创建一个新概念并填充主题,但我从 gmail 应用程序中得到一个 Toast,上面写着 'Unable to add attachment'。意图似乎正确触发,因此我的代码中没有发生异常。我的猜测是由于某种原因其他应用程序仍然无法访问该文件。
有什么建议吗?
提前致谢。
The Uri points to: content://myApplicationId/files/export.xml
但你没有使用那个 Uri
。您正在使用 Uri.fromFile()
:
val shareIntent = Intent().apply {
type = "text/plain"
putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file))
putExtra(Intent.EXTRA_SUBJECT, getString(R.string.share_file_subject))
您应该在 Android 7.0+ 上因 FileUriExposedException
崩溃,所以您已经应用了 hack 来解决这个问题。只是现在,在 Android 10+ 上,该 hack 的价值有限。
因此,将 Uri.fromFile(file)
替换为 uri
。此外,将 addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION)
作为 apply {}
lambda 的一部分包含在内。并找到您在代码中配置 StrictMode
的位置,并让它抱怨 FileUriExposedException
,至少在 debug
构建中。
另外,你的I/O乱七八糟。
val file = File(requireContext().getExternalFilesDir(null), "export.xml")
val outputStream =
requireContext().openFileOutput("export.xml", Context.MODE_PRIVATE)
您的代码假定 openFileOutput()
将其内容放在 getExternalFilesDir()
标识的位置,这是不正确的。将后一行切换为:
val outputStream = FileOutputStream(file)