Создать и поделиться файлом из внутреннего хранилища
Моя цель - создать файл 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;
}