【问题标题】:Creating & sharing a simple text file in Android 10在 Android 10 中创建和共享一个简单的文本文件
【发布时间】:2020-04-21 20:59:14
【问题描述】:

我在创建一个将大量原始数据写入文本文件,然后共享该文本文件以通过电子邮件/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>

文件路径.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 说“无法添加附件”。意图似乎正确触发,因此我的代码中没有发生异常。我的猜测是由于某种原因,其他应用程序仍然无法访问该文件。

有什么建议吗?

提前致谢。

【问题讨论】:

    标签: android android-intent privacy android-10.0 file-sharing


    【解决方案1】:

    Uri 指向: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)
    

    【讨论】:

    • 感谢您的评论,但不幸的是我仍然得到相同的结果。我不知道我正在实施任何黑客攻击,所以你有一个链接到如何正确地实现它而不得到 FileUriExposedException 吗?
    • @TimvandeWal:“我仍然得到相同的结果”——你还没有真正详细解释结果是什么。 FileProvider 应该可以正常工作。有关使用 ACTION_SEND 的示例,请参阅 this codeUri 已准备好 here
    • @TimvandeWal:有关FileUriExposedException 的更多信息,请参阅this,当在Intent 中使用Uri.fromFile() 值时,您应该在Android 7.0+ 上使用。
    • 我更新了我的原始帖子,描述了我所看到的内容,并在我的 Intent 中添加了一个操作,这增加了我的共享选项,但没有解决文件问题。跨度>
    • @TimvandeWal:我发现了另一个错误 - 请参阅我更新的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-09
    • 2011-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多