Intereting Posts
Как центрировать ImageView на панели инструментов? Для Instant Run требуется «Инструменты | Android | Включить интеграцию ADB ' Перезапустите службу, даже если приложение отключено и продолжает работать в фоновом режиме даже после закрытия приложения How? Как удалить код «+» и код страны с номера телефона? Использование родителей для использования ресурсов Ошибка INSTALL_PARSE_FAILED_NO_CERTIFICATES в Eclipse Установка приложения phonegap в эмулятор Android с помощью окон CLI Ошибка приложения Android – Дубликат id 0x7f04000f, тег null или родительский идентификатор 0x0 с другим фрагментом для com.google.android.gms.maps.SupportMapFragment Ресурсы $ NotFoundException в Android Неожиданное возобновление «имени пакета», хотя уже возобновлено в «имя пакета» Ошибка в Android Как изменить высоту списка просмотров прогмально ..? Как получить доступную высоту экрана минус панель навигации в HoneyComb? Android Studio Не удалось найти метод runProguard () для аргументов? Эффект сенсорного эффекта Android L на форме? Android studio 2.3: Не удалось инициализировать класс org.jetbrains.kotlin.android.actions.NewKotlinActivityAction

Электронная почта с внутреннего хранилища

В моем приложении я пишу файл во внутреннее хранилище, как описано в разработчике Android . Затем позже я хочу отправить по электронной почте файл, который я написал во внутреннем хранилище. Вот мой код и ошибка, которую я получаю, любая помощь будет оценена.

FileOutputStream fos = openFileOutput(xmlFilename, MODE_PRIVATE); fos.write(xml.getBytes()); fos.close(); Intent intent = new Intent(android.content.Intent.ACTION_SEND); intent.setType("text/plain"); ... Uri uri = Uri.fromFile(new File(xmlFilename)); intent.putExtra(android.content.Intent.EXTRA_STREAM, uri); startActivity(Intent.createChooser(intent, "Send eMail..")); 

И ошибка

File: // путь вложения должен указывать на файл: // mnt / sdcard. Игнорирование файла вложения: // …

Solutions Collecting From Web of "Электронная почта с внутреннего хранилища"

Я думаю, вы, возможно, обнаружили ошибку (или, по крайней мере, ненужное ограничение) в клиенте android Gmail. Я смог обойти это, но это наводит меня на слишком специфическую реализацию, и для этого потребуется немного больше работы:

Первая CommonsWare очень правильна в том, что нужно сделать мир файлов доступным для чтения:

 fos = openFileOutput(xmlFilename, MODE_WORLD_READABLE); 

Затем нам нужно работать над тем, как Gmail настаивает на пути / mnt / sdcard (или в реализации, эквивалентном?):

 Uri uri = Uri.fromFile(new File("/mnt/sdcard/../.."+getFilesDir()+"/"+xmlFilename)); 

По крайней мере, на моем модифицированном устройстве Gingerbread, это позволяет мне Gmail вложение из частного хранилища для себя и видеть содержимое с помощью кнопки предварительного просмотра, когда я его получаю. Но я не очень «хорош» в том, чтобы делать это, чтобы заставить его работать, и кто знает, что произойдет с другой версией Gmail или другим почтовым клиентом или телефоном, который монтирует внешнее хранилище в другом месте.

В последнее время я борется с этой проблемой, и я хотел бы поделиться решением, которое я нашел, используя FileProvider , из библиотеки поддержки. Его расширение Content Provider, которое решает эту проблему, без проблем, и это не слишком много работает.

Как поясняется в ссылке, для активации поставщика контента: в своем манифесте напишите:

 <application .... <provider android:name="android.support.v4.content.FileProvider" android:authorities="com.youdomain.yourapp.fileprovider" android:exported="false" android:grantUriPermissions="true"> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/file_paths" /> </provider> ... 

Метаданные должны указывать xml-файл в папке res / xml (я назвал его file_paths.xml):

 <?xml version="1.0" encoding="utf-8"?> <paths xmlns:android="http://schemas.android.com/apk/res/android"> <files-path path="" name="document"/> </paths> 

Путь пуст, когда вы используете папку с внутренними файлами, но если для более общего местоположения (теперь мы говорим о внутреннем пути хранения), вы должны использовать другие пути. Имя, которое вы пишете, будет использоваться для URL-адреса, который поставщик контента предоставит файлу.

И теперь вы можете создать новый, читаемый в мире URL-адрес, просто используя:

 Uri contentUri = FileProvider.getUriForFile(context, "com.yourdomain.yourapp.fileprovider", file); 

На любой файл из пути в метаданных res / xml / file_paths.xml.

И теперь просто используйте:

  Intent mailIntent = new Intent(Intent.ACTION_SEND); mailIntent.setType("message/rfc822"); mailIntent.putExtra(Intent.EXTRA_EMAIL, recipients); mailIntent.putExtra(Intent.EXTRA_SUBJECT, subject); mailIntent.putExtra(Intent.EXTRA_TEXT, body); mailIntent.putExtra(Intent.EXTRA_STREAM, contentUri); try { startActivity(Intent.createChooser(mailIntent, "Send email..")); } catch (android.content.ActivityNotFoundException ex) { Toast.makeText(this, R.string.Message_No_Email_Service, Toast.LENGTH_SHORT).show(); } 

Вам не нужно давать разрешение, вы делаете это автоматически, когда вы присоединяете url к файлу.

И вам не нужно делать свой файл MODE_WORLD_READABLE, этот режим теперь устарел, сделайте его MODE_PRIVATE, поставщик контента создаст новый URL-адрес для того же файла, доступного другим приложениям.

Я должен отметить, что я тестировал его только на эмуляторе с Gmail.

Крис Страттон предложил хорошее обходное решение. Однако он не работает на многих устройствах. Вы не должны указывать путь hardcode / mnt / sdcard. Вы лучше вычислите это:

 String sdCard = Environment.getExternalStorageDirectory().getAbsolutePath(); Uri uri = Uri.fromFile(new File(sdCard + new String(new char[sdCard.replaceAll("[^/]", "").length()]) .replace("\0", "/..") + getFilesDir() + "/" + xmlFilename)); 

Принимая во внимание рекомендации отсюда: http://developer.android.com/reference/android/content/Context.html#MODE_WORLD_READABLE , поскольку API 17 мы рекомендуем использовать ContentProviders и т. Д. Благодаря этому парню и его сообщению http: //stephendnicholas.com/archives/974 у нас есть решение:

 public class CachedFileProvider extends ContentProvider { public static final String AUTHORITY = "com.yourpackage.gmailattach.provider"; private UriMatcher uriMatcher; @Override public boolean onCreate() { uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); uriMatcher.addURI(AUTHORITY, "*", 1); return true; } @Override public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException { switch (uriMatcher.match(uri)) { case 1:// If it returns 1 - then it matches the Uri defined in onCreate String fileLocation = AppCore.context().getCacheDir() + File.separator + uri.getLastPathSegment(); ParcelFileDescriptor pfd = ParcelFileDescriptor.open(new File(fileLocation), ParcelFileDescriptor.MODE_READ_ONLY); return pfd; default:// Otherwise unrecognised Uri throw new FileNotFoundException("Unsupported uri: " + uri.toString()); } } @Override public int update(Uri uri, ContentValues contentvalues, String s, String[] as) { return 0; } @Override public int delete(Uri uri, String s, String[] as) { return 0; } @Override public Uri insert(Uri uri, ContentValues contentvalues) { return null; } @Override public String getType(Uri uri) { return null; } @Override public Cursor query(Uri uri, String[] projection, String s, String[] as1, String s1) { return null; } } 

Затем создайте файл во внутреннем кеше:

  File tempDir = getContext().getCacheDir(); File tempFile = File.createTempFile("your_file", ".txt", tempDir); fout = new FileOutputStream(tempFile); fout.write(bytes); fout.close(); 

Цель установки:

 ... emailIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("content://" + CachedFileProvider.AUTHORITY + "/" + tempFile.getName())); 

И зарегистрируйте поставщика контента в файле AndroidManifest:

 <provider android:name="CachedFileProvider" android:authorities="com.yourpackage.gmailattach.provider"></provider> 
 File.setReadable(true, false); 

Работал на меня.

Ошибка достаточно конкретна: вы должны использовать файл из внешнего хранилища для создания вложения.

Если вы собираетесь использовать внутреннее хранилище, попробуйте использовать точный путь хранения:

 Uri uri = Uri.fromFile(new File(context.getFilesDir() + File.separator + xmlFilename)); 

Или дополнительно изменять имя файла в отладчике и просто вызвать «новый файл (blah) .exists ()» в каждом файле, чтобы быстро узнать, какое точное имя является вашим файлом

Это также может быть реальной проблемой реализации устройства, характерной для вашего устройства. Вы пробовали использовать другие устройства / эмулятор?