Создание и распространение простого текстового файла в Android 10 - PullRequest
1 голос
/ 21 апреля 2020

У меня были некоторые проблемы с созданием функции, которая записывает большой кусок необработанных данных в текстовый файл, а затем делится этим текстовым файлом для отправки по электронной почте / 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, говорящий «Невозможно добавить вложение». Кажется, что намерение срабатывает правильно, поэтому в моем коде нет исключений. Я предполагаю, что файл по-прежнему недоступен для других приложений.

Есть предложения?

Заранее спасибо.

1 Ответ

0 голосов
/ 21 апреля 2020

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

Вы должны потерпеть крах с FileUriExposedException на Android 7.0+, поэтому вы уже применили хак, чтобы обойти это. Просто сейчас, на Android 10+, этот хак имеет ограниченную ценность.

Итак, замените Uri.fromFile(file) на uri. Также включите addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) как часть вашей apply {} лямбды. И найдите, где в вашем коде вы конфигурируете StrictMode и попросите его жаловаться на FileUriExposedException, по крайней мере, на debug сборках.


Кроме того, ваш ввод / вывод испорчен.

            val file = File(requireContext().getExternalFilesDir(null), "export.xml")
            val outputStream =
                requireContext().openFileOutput("export.xml", Context.MODE_PRIVATE)

Ваш код предполагает, что openFileOutput() помещает его содержимое в местоположение, обозначенное getExternalFilesDir(), что неверно. Переключите последнюю строку на:

            val outputStream = FileOutputStream(file)
...