Correo electrónico del almacenamiento interno

En mi aplicación escribo un archivo en el almacenamiento interno como cubierto en el desarrollador android . Entonces más adelante deseo enviar por correo electrónico el archivo que escribí en el almacenaje interno. Aquí está mi código y el error que estoy recibiendo, cualquier ayuda será apreciada.

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..")); 

Y el error es

File: // debe señalar a file: // mnt / sdcard. Haciendo caso omiso del archivo adjunto: // …

7 Solutions collect form web for “Correo electrónico del almacenamiento interno”

Creo que puede haber encontrado un error (o al menos una limitación innecesaria) en el cliente android de Gmail. Pude trabajar en torno a ello, pero me parece muy específica de la aplicación, y necesitaría un poco más de trabajo para ser portátil:

First CommonsWare es muy correcto sobre la necesidad de hacer que el archivo sea legible en el mundo:

 fos = openFileOutput(xmlFilename, MODE_WORLD_READABLE); 

A continuación, debemos trabajar en torno a la insistencia de Gmail en la ruta / mnt / sdcard (o equivalente de implementación equivalente?):

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

Al menos en mi dispositivo de Gingerbread modificado, esto es dejarme un archivo adjunto de Gmail desde el almacenamiento privado a mí mismo, y ver el contenido con el botón de vista previa cuando lo recibo. Pero no me siento muy "bueno" por tener que hacer esto para que funcione, y quién sabe qué pasaría con otra versión de Gmail u otro cliente de correo electrónico o un teléfono que monta el almacenamiento externo en otro lugar.

He estado luchando con esta edición últimamente y quisiera compartir la solución que encontré, usando FileProvider , de la biblioteca de la ayuda. Su una extensión de proveedor de contenido que resolver este problema bien sin trabajo en torno, y no es demasiado trabajo.

Como se explica en el enlace, para activar el proveedor de contenido: en tu manifiesto, escribe:

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

Los metadatos deberían indicar un archivo xml en la carpeta res / xml (lo llamé 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> 

La ruta de acceso está vacía cuando se utiliza la carpeta de archivos internos, pero si para una ubicación más general (ahora estamos hablando de la ruta de almacenamiento interno) debe utilizar otras rutas. El nombre que escriba se utilizará para la url que el proveedor de contenido le dará al archivo.

Y ahora, puede generar una nueva url mundialmente legible simplemente usando:

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

En cualquier archivo de una ruta de acceso en los metadatos res / xml / file_paths.xml.

Y ahora solo usa:

  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(); } 

No es necesario dar un permiso, lo hace automáticamente cuando se adjunta la url al archivo.

Y no necesitas hacer tu archivo MODE_WORLD_READABLE, este modo ahora está obsoleto, hazlo MODE_PRIVATE, el proveedor de contenido crea una nueva url para el mismo archivo que es accesible por otras aplicaciones.

Debo tener en cuenta que sólo lo probé en un emulador con Gmail.

Chris Stratton propuso una buena solución. Sin embargo, falla en muchos dispositivos. Usted no debe hardcode / mnt / sdcard ruta. Es mejor calcularlo:

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

Teniendo en cuenta las recomendaciones de aquí: http://developer.android.com/reference/android/content/Context.html#MODE_WORLD_READABLE , ya que la API 17 nos anima a utilizar ContentProviders, etc Gracias a ese chico y su puesto http: //stephendnicholas.com/archives/974 tenemos una solución:

 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; } } 

Que crear archivo en caché interno:

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

Intención de configuración:

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

Y registrar Proveedor de contenido en el archivo AndroidManifest:

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

Trabajado para mí.

El error es bastante específico: se debe utilizar el archivo de almacenamiento externo para realizar un archivo adjunto.

Si va a utilizar almacenamiento interno, intente utilizar la ruta de almacenamiento exacta:

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

O, además, seguir cambiando el nombre de archivo en el depurador y acaba de llamar a "nuevo archivo (bla) .exists ()" en cada uno de los archivos para ver rápidamente qué nombre exacto es su archivo

También podría ser un problema real de implementación de dispositivo específico de su dispositivo. ¿Ha intentado utilizar otros dispositivos / emulador?

  • ¿Cómo enviar un correo electrónico simple mediante programación? (Existe una manera simple de hacerlo?)
  • Enviar correo electrónico automáticamente desde la aplicación de Android a través de Exchange Server
  • ANDROID: cliente de correo electrónico receptor e-mail id vacío en android-parse
  • ¿Existe un cliente de correo electrónico de código abierto de Android?
  • Android: Cómo obtener el nombre del paquete de clientes de correo electrónico nativo
  • ¿Cómo puedo enviar un correo electrónico de la aplicación android directamente sin mostrar el formulario de correo electrónico predeterminado del dispositivo?
  • ¿Cómo enviar contenido html con imagen a través de cliente de correo electrónico predeterminado de Android?
  • Error de E / S al usar correo, activación y archivos jar adicionales en android stdio
  • No puedo enviar correo desde Google Glass
  • Establecer dirección de correo destino en Firebase Invites
  • Envío de correo electrónico desde la aplicación Android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.