Моя цель — создать XML-файл во внутреннем хранилище, а затем отправить его через общий ресурс 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, но я проверяю файл, и он имеет нулевую длину.
Как правильно получить доступ к файлам? Нужно ли создавать файл с поставщиком контента? Если да, то как?
Обновить
Вот код, которым я делюсь. Если я выбираю Gmail, оно отображается как вложение, но когда я отправляю, оно выдает ошибку Не удалось показать вложение, а в полученном электронном письме нет вложения.
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;
}
}
Я заметил, что внутри createChooser(...) здесь выбрасывается Exception
, но я не могу понять, почему это выбрасывается.
E/ActivityThread(572): действие com.android.internal.app.ChooserActivity привело к утечке IntentReceiver com.android.internal.app.ResolverActivity$1@4148d658, который изначально был зарегистрирован здесь. Вы пропустили вызов unregisterReceiver()?
Я исследовал эту ошибку и не могу найти ничего очевидного. Обе эти ссылки предполагают, что мне нужно отменить регистрацию приемника.
- ChooserActivity слил IntentReceiver
- Почему Intent.createChooser() нужен BroadcastReceiver и как реализовать?
У меня есть настройка приемника, но она предназначена для AlarmManager
, который установлен в другом месте и не требует регистрации/отмены регистрации приложения.
Код для 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;
}