在 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)