Создать и поделиться файлом из внутреннего хранилища

Моя цель - создать файл XML наinternal storage а затем отправить его через акцию Intent.

Я могу создать файл XML, используя этот код

FileOutputStream outputStream = context.openFileOutput(fileName, Context.MODE_WORLD_READABLE);
PrintStream printStream = new PrintStream(outputStream);
String xml = this.writeXml(); // get XML here
printStream.println(xml);
printStream.close();

Я застрял, пытаясь извлечь Uri в выходной файл, чтобы поделиться им. Сначала я попытался получить доступ к файлу, преобразовав файл в Uri

File outFile = context.getFileStreamPath(fileName);
return Uri.fromFile(outFile);

Это возвращаетfile:///data/data/com.my.package/files/myfile.xml но я не могу прикрепить это к электронному письму, загрузить и т. д.

Если я вручную проверяю длину файла, это правильно и показывает, что существует разумный размер файла.

Затем я создал поставщика контента и попытался сослаться на файл, и он не является действительным дескриптором файла.ContentProvider кажется, никогда не называется какой-либо точкой.

Uri uri = Uri.parse("content://" + CachedFileProvider.AUTHORITY + "/" + fileName);
return uri;

Это возвращаетcontent://com.my.package.provider/myfile.xml но я проверяю файл и его нулевую длину.

Как правильно получить доступ к файлам? Нужно ли создавать файл с поставщиком контента? Если так, то как?

Update

Вот код, которым я пользуюсь, чтобы поделиться. Если я выбираю Gmail, он отображается как вложение, но при отправке выдает ошибкуCouldn't show attachment и полученное письмо не имеет вложений.

public void onClick(View view) {
    Log.d(TAG, "onClick " + view.getId());

    switch (view.getId()) {
        case R.id.share_cancel:
            setResult(RESULT_CANCELED, getIntent());
            finish();
            break;

        case R.id.share_share:

            MyXml xml = new MyXml();
            Uri uri;
            try {
                uri = xml.writeXmlToFile(getApplicationContext(), "myfile.xml");
                //uri is  "file:///data/data/com.my.package/files/myfile.xml"
                Log.d(TAG, "Share URI: " + uri.toString() + " path: " + uri.getPath());

                File f = new File(uri.getPath());
                Log.d(TAG, "File length: " + f.length());
                // shows a valid file size

                Intent shareIntent = new Intent();
                shareIntent.setAction(Intent.ACTION_SEND);
                shareIntent.putExtra(Intent.EXTRA_STREAM, uri);
                shareIntent.setType("text/plain");
                startActivity(Intent.createChooser(shareIntent, "Share"));
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }

            break;
    }
}

Я заметил, что естьException бросили сюда изнутриcreateChooser(...), но я не могу понять, почему его выбросили.

E/ActivityThread(572): Activity com.android.internal.app.ChooserActivity has leaked IntentReceiver com.android.internal.app.ResolverActivity$1@4148d658 that was originally registered here. Are you missing a call to unregisterReceiver()?

Я исследовал эту ошибку и не могу найти ничего очевидного. Обе эти ссылки предполагают, что мне нужно отменить регистрацию получателя.

ChooserActivity has leaked IntentReceiver Why does Intent.createChooser() need a BroadcastReceiver and how to implement?

У меня есть приемник, но он предназначен дляAlarmManager это установлено в другом месте и не требует, чтобы приложение регистрировалось / отменяло регистрацию.

Code for openFile(...)

В случае, если это необходимо, вот создатель контента, который я создал.

public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
    String fileLocation = getContext().getCacheDir() + "/" + uri.getLastPathSegment();

    ParcelFileDescriptor pfd = ParcelFileDescriptor.open(new File(fileLocation), ParcelFileDescriptor.MODE_READ_ONLY);
    return pfd;
}

Ответы на вопрос(3)

Ваш ответ на вопрос