En mi aplicación que escribir un archivo en el almacenamiento interno como amparada en los desarrolladores de android. Más tarde, en deseo por correo electrónico el archivo que me escribió en el almacenamiento 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

archivo://archivo adjunto ruta de acceso debe apuntar a file://mnt/sdcard. Ignorando archivo adjunto://…

InformationsquelleAutor Mr Jackson | 2011-05-20

7 Comentarios

  1. 24

    Creo que puede haber encontrado un bug (o, al menos, innecesario limitación) en el cliente de Gmail para android. Yo era capaz de trabajar alrededor de ella, pero me parece demasiado aplicación específica, y necesitaría un poco más de trabajo para ser portátil:

    Primera CommonsWare es muy correcta acerca de la necesidad de hacer que el archivo de lectura pública:

    fos = openFileOutput(xmlFilename, MODE_WORLD_READABLE);

    A continuación, tenemos que trabajar alrededor de Gmail insistencia en la ruta /mnt/sdcard (o aplicación específica equivalente?) ruta de acceso:

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

    Al menos en mi modificado de pan de Jengibre dispositivo, esto es, dejar que me Gmail un archivo adjunto de almacenamiento privado a mí mismo, y ver el contenido usando el botón de vista previa cuando la reciba. Pero no me siento muy «buena» 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 se monta el almacenamiento externo en otros lugares.

    • Gran solución. Solucionado mi problema. Gracias.
    • Por favor, tenga en cuenta que este es un hack directamente superar un determinado impar expectativa por parte de los autores de un determinado programa de destino. Hoy en día, se debe dar consideración a buscar en el Proveedor de Contenidos y métodos similares como se discutió en las otras respuestas que son más característicamente «Android» en el estilo y, ojalá, más general en la utilidad.
  2. 11

    He estado luchando con este problema últimamente y me gustaría compartir la solución que he encontrado, utilizando FileProvider, con el apoyo de la biblioteca. su una extensión de Proveedor de Contenido que resolver este problema sin solución, y no es demasiado-mucho trabajo.

    Como se explica en el enlace para activar el proveedor de contenido:
    en su 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>
        ...

    la meta de datos debe indicar un archivo xml en res/xml de la carpeta (lo he denominado 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 está vacía cuando se utiliza el interior de la carpeta de archivos, pero si para obtener la ubicación general (estamos hablando de la interna de la ruta de almacenamiento) debe utilizar otros caminos. el nombre que escriba será utilizado para la url a la que el proveedor de contenido con dar al archivo.

    y ahora, usted puede generar un nuevo mundo url legible simplemente mediante el uso de:

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

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

    y ahora sólo tiene que utilizar:

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

    usted no necesita dar un permiso, usted es automáticamente al colocar la dirección url para el archivo.

    y no es necesario para hacer que su archivo MODE_WORLD_READABLE, este modo está ahora en desuso, hacer MODE_PRIVATE, el proveedor de contenido crea una nueva url para el mismo archivo, que es accesible por otras aplicaciones.

    Debo señalar que sólo lo he probado en un emulador con Gmail.

    • Parece que funciona muy bien. La mayoría de los elegang solución que he visto de este (muy molesto) problema que he encontrado hasta ahora.
  3. 7

    Chris Stratton propuesta de solución. Sin embargo, se produce un error en un montón de dispositivos. Usted no debe codificar /mnt/sdcard camino. Que mejor se calcula:

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

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

    De crear el archivo en caché Interna:

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

    Instalación De Intención:

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

    Y registro de proveedor de Contenido en el AndroidManifest de archivo:

    <provider android:name="CachedFileProvider" android:authorities="com.yourpackage.gmailattach.provider"></provider>
    • No te olvides de añadir android:grantUriPermissions="true" para el proveedor.
    • Funcionaba de maravilla, gracias!
  5. 5
    File.setReadable(true, false);

    trabajó para mí.

    • Yo era capaz de enviar un archivo de almacenamiento interno de uso de Gmail con un FileProvider tan largo como el Archivo objeto que creó el URI conjunto legible
    • Trabajó para mí con Gmail, pero no con otras apps de correo en Android (como el Buzón de correo). Creo que el proveedor de contenido solución de lejos.ser de abajo es la más «correcta» enfoque.
    • Los Proveedores de contenido son, de hecho, el la intención de solución en la arquitectura de Android para exponer un archivo privada.
  6. 1

    El error es lo suficientemente específico: usted debe utilizar el archivo de de almacenamiento externo con el fin de hacer un archivo adjunto.

    • O cambiar MODE_PRIVATE a MODE_WORLD_READABLE. Desde que no escribo en el programa de correo electrónico, no puede leer sus archivos privados.
    • Gracias por tu respuesta. Puedo leer eso, pero yo desarrollar una aplicación para un teléfono sin almacenamiento externo ya que el celular se ha incorporado de almacenamiento de 32 gb.
    • A continuación, utilice @CommonsWare comentario: MODE_WORLD_READABLE puede salvar.
    • no puede hacer eso, el Archivo() constructor de no manejar el permiso. y el FileReader() no es compatible con la Uri.fromFile().
    • Dejar de disparar respuestas de su vientre y no con la cabeza. Cambiar el permiso no afecta a la ruta de acceso. por favor, consulte el error! Estoy buscando una manera directa el camino correcto. O una forma alternativa de lograr lo que se han retratado!
    • Jackson: «un teléfono sin almacenamiento externo ya que el celular se ha incorporado de almacenamiento de 32 gb» — tu dispositivo cuenta con almacenamiento externo. «Almacenamiento externo» no significa «tarjeta SD», que significa «accesible desde un PC anfitrión». «el Archivo() constructor de no manejar el permiso» — no, si seguimos las instrucciones sencillas en las primeras palabras de mi comentario anterior («O cambiar MODE_PRIVATE a MODE_WORLD_READABLE«).
    • Yo lo hice. Todavía no hay ninguna buena.
    • incluso triedget Uri uri = Uri.fromFile(FileStreamPath(xmlFilename)) pero todavía no es bueno.

  7. 1

    Si usted va a utilizar el almacenamiento interno, pruebe a utilizar exactamente la misma ruta de almacenamiento:

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

    o además de seguir cambiando el nombre del archivo en el depurador y sólo llamar «nuevo Archivo(bla).existe()» en cada uno de los archivos para ver rápidamente qué nombre exacto es el archivo

    también podría ser un dispositivo real problema de aplicación específico para su dispositivo. has probado con otros dispositivos/emulador?

Dejar respuesta

Please enter your comment!
Please enter your name here