2010-11-08 11 views
11

De forma predeterminada, los archivos guardados en el almacenamiento interno son privados para su aplicación y otras aplicaciones no pueden acceder a ellos (ni tampoco el usuario).Android: no se puede adjuntar un archivo en el correo electrónico

Puedo ver el archivo "/ data/data/package_name/files/in file explore in DDMS, pero cuando adjunté el URI del archivo anterior usando imageUri en el correo electrónico, vi que el archivo adjunto es de 0kb. he utilizado la API de correo electrónico por defecto de Android.

puede alguien sugerir, cómo adjuntar un archivo en el correo electrónico que es privado para la aplicación?

aunque yo soy exitoso capaz de guardar el archivo en la tarjeta SD y adjuntar el archivo de la tarjeta SD, esto está funcionando bien.

Pero si la tarjeta SD no está disponible y s Avingiendo el archivo al almacenamiento interno, ¿cómo puedo adjuntarlos en el correo electrónico?

String FILENAME = "hello_file.txt"; 
String string = "hello world!";FileOutputStream fos = openFileOutput(FILENAME,  Context.MODE_PRIVATE); 
fos.write(string.getBytes()); 
fos.close(); 

File imageFile = getFileStreamPath(FILENAME); 
Uri imageUri = Uri.fromFile(imageFile); 

final Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND); 
emailIntent.setType("*/*"); 
emailIntent.putExtra(android.content.Intent.EXTRA_STREAM,imageUri); 

this.startActivityForResult(Intent.createChooser(emailIntent, "Send mail..."),SUB_ACTIVITY); 
+1

¿Alguna vez encontró una solución a este problema? – JehandadK

+0

Me enfrenté al problema similar. Desde la tarjeta SD que funciona bien ... Pero desde el almacenamiento interno no tuve éxito en esta funcionalidad. Quizás jugar con tipos MIME ayudará a continuar ... – Mike

+0

¿podría por favor elobrarlo? – pankaj

Respuesta

1

Trate de usar en lugar de Context.MODE_WORLD_READABLE Context.MODE_PRIVATE al guardar el archivo. Luego, otras aplicaciones tendrán acceso al archivo.

+0

@, ya lo había intentado con MODE_WORLD_WRITEABLE, pero no funciona. – pankaj

+0

@pankaj pero ¿has probado con MODE_WORLD_READABLE? –

6

Cuando intenta adjuntar archivos desde el almacenamiento interno, Gmail escribe un error en el registro:

aplicación
ERROR/Gmail(...): file:// attachment paths must point to file:///mnt/sdcard. 

E-mail que mostraría el archivo adjunto, incluso si no lo hizo físicamente existe.

En cuanto a un almacenamiento externo, la documentación dice que:

Cada dispositivo compatible con Android es compatible con una "memoria externa" compartida que se puede utilizar para guardar archivos. Puede ser un medio de almacenamiento extraíble (como una tarjeta SD) o un almacenamiento interno (no extraíble).

Eso significa que no tiene que preocuparse de que el dispositivo no tenga un almacenamiento externo. Aún así, el almacenamiento externo puede no estar disponible a veces. Consulte la http://developer.android.com/guide/topics/data/data-storage.html#filesExternal

+0

¡Gracias! No pude entender por qué estaba fallando y no pensé en cambiar los filtros en mi ventana de LogCat. –

1

también he tenido este problema utilizando archivos internos y aunque he utilizado openFileInput con MODE_WORLD_READABLE en /data/data//files/testFileName.txt y se utiliza la URI.parse con el extra "/" (véase a continuación), la prueba recibida enviada por correo electrónico todavía carece del archivo adjunto deseado. Lo siento, pero no hay respuesta, excepto tratar de usar archivos externos en la tarjeta SD, ¡que es mi próximo experimento!

Código:

File tmpFile = new File(context.getFilesDir(), mfileName); 
     Log.d(TAG, tmpFile.toString()); 
// This shows: /data/data/org.eddiem.adeveloper.flatfiletest/files/testFile.csv 
     //File tmpFile2 = new File(context.getFileStreamPath(mfileName), mfileName); 
     //Log.v(TAG, tmpFile2.toString()); 
// This also shows: /data/data/org.eddiem.adeveloper.flatfiletest/files/testFile.csv 

     //Uri uri = Uri.fromFile(new File(context.getFileStreamPath(mfileName), mfileName)); 
     Uri uri = Uri.parse("file://" + tmpFile.toString()); 
     //Uri uri = Uri.fromFile(new File(Environment.getExternalStorageDirectory(), 
     //        mfileName)); 
     Log.d(TAG, "Uri-path is: " + uri.getPath()); // or .toString() 

     Intent i = new Intent(android.content.Intent.ACTION_SEND); 
     i.setType("text/plain"); 
     i.putExtra(Intent.EXTRA_EMAIL, new String[]{"[email protected]"}); 
     i.putExtra(Intent.EXTRA_SUBJECT, "Test Email - with Attachment"); 
     i.putExtra(Intent.EXTRA_TEXT, "This is a test Email with an Attachment."); 
     i.putExtra(Intent.EXTRA_STREAM, uri); 
     //startActivity(Intent.createChooser(i, "Select application")); 
     startActivity(Intent.createChooser(i, "Send mail")); 
4

Con el fin de compartir un archivo privado es necesario utilizar un ContentProvider para proporcionar acceso a su archivo por otras aplicaciones. Aquí hay un gran ejemplo: Android: Attaching files from internal cache to Gmail.

Además, aunque el tutorial menciona que debe declarar su proveedor en el archivo de manifiesto de Android, no especifica que debe estar en <application>, así que asegúrese de que cuando declare que está dentro de <application> </application>.

3

Este código puede ayudarle a conseguir idea acerca de apego:

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 

    buttonSend = (Button) findViewById(R.id.buttonSend); 

    textTo = (EditText) findViewById(R.id.editTextTo); 
    textSubject = (EditText) findViewById(R.id.editTextSubject); 
    textMessage = (EditText) findViewById(R.id.editTextMessage); 

    buttonSend.setOnClickListener(new OnClickListener() { 
     @Override 
     public void onClick(View v) { 
      String to = textTo.getText().toString(); 
      String subject = textSubject.getText().toString(); 
      String message = textMessage.getText().toString(); 

      Intent i = new Intent(Intent.ACTION_SEND); 
      i.setType("plain/text"); 
      File data = null; 

      try { 
       Date dateVal = new Date(); 
       String filename = dateVal.toString(); 
       data = File.createTempFile("Report", ".csv"); 
       FileWriter out = (FileWriter) GenerateCsv.generateCsvFile(
               data, "Name,Data1"); 
       i.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(data)); 
       i.putExtra(Intent.EXTRA_EMAIL, new String[] { to }); 
       i.putExtra(Intent.EXTRA_SUBJECT, subject); 
       i.putExtra(Intent.EXTRA_TEXT, message); 
       startActivity(Intent.createChooser(i, "E-mail")); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 
    }); 
} 

public class GenerateCsv 
{ 
    public static FileWriter generateCsvFile(File sFileName,String fileContent) 
    { 
     FileWriter writer = null; 

     try { 
      writer = new FileWriter(sFileName); 
      writer.append(fileContent); 
      writer.flush(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } finally { 
      try { 
       writer.close(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 

     return writer; 
    } 
} 

El código anterior requiere de agregar el siguiente permiso a su archivo de manifiesto:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission> 
+0

Simple y claro –

5
Android: Attaching files from internal cache to Gmail 




package com.stephendnicholas.gmailattach; 

import java.io.File; 
import java.io.FileNotFoundException; 

import android.content.ContentProvider; 
import android.content.ContentValues; 
import android.content.UriMatcher; 
import android.database.Cursor; 
import android.net.Uri; 
import android.os.ParcelFileDescriptor; 
import android.util.Log; 

public class CachedFileProvider extends ContentProvider { 

    private static final String CLASS_NAME = "CachedFileProvider"; 

    // The authority is the symbolic name for the provider class 
    public static final String AUTHORITY = "com.stephendnicholas.gmailattach.provider"; 

    // UriMatcher used to match against incoming requests 
    private UriMatcher uriMatcher; 

    @Override 
    public boolean onCreate() { 
     uriMatcher = new UriMatcher(UriMatcher.NO_MATCH); 

     // Add a URI to the matcher which will match against the form 
     // 'content://com.stephendnicholas.gmailattach.provider/*' 
     // and return 1 in the case that the incoming Uri matches this pattern 
     uriMatcher.addURI(AUTHORITY, "*", 1); 

     return true; 
    } 

    @Override 
    public ParcelFileDescriptor openFile(Uri uri, String mode) 
      throws FileNotFoundException { 

     String LOG_TAG = CLASS_NAME + " - openFile"; 

     Log.v(LOG_TAG, 
       "Called with uri: '" + uri + "'." + uri.getLastPathSegment()); 

     // Check incoming Uri against the matcher 
     switch (uriMatcher.match(uri)) { 

     // If it returns 1 - then it matches the Uri defined in onCreate 
     case 1: 

      // The desired file name is specified by the last segment of the 
      // path 
      // E.g. 
      // 'content://com.stephendnicholas.gmailattach.provider/Test.txt' 
      // Take this and build the path to the file 
      String fileLocation = getContext().getCacheDir() + File.separator 
        + uri.getLastPathSegment(); 

      // Create & return a ParcelFileDescriptor pointing to the file 
      // Note: I don't care what mode they ask for - they're only getting 
      // read only 
      ParcelFileDescriptor pfd = ParcelFileDescriptor.open(new File( 
        fileLocation), ParcelFileDescriptor.MODE_READ_ONLY); 
      return pfd; 

      // Otherwise unrecognised Uri 
     default: 
      Log.v(LOG_TAG, "Unsupported uri: '" + uri + "'."); 
      throw new FileNotFoundException("Unsupported uri: " 
        + uri.toString()); 
     } 
    } 

    // ////////////////////////////////////////////////////////////// 
    // Not supported/used/required for this example 
    // ////////////////////////////////////////////////////////////// 

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




<provider android:name="CachedFileProvider" android:authorities="com.stephendnicholas 





public static void createCachedFile(Context context, String fileName, 
      String content) throws IOException { 

    File cacheFile = new File(context.getCacheDir() + File.separator 
       + fileName); 
    cacheFile.createNewFile(); 

    FileOutputStream fos = new FileOutputStream(cacheFile); 
    OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF8"); 
    PrintWriter pw = new PrintWriter(osw); 

    pw.println(content); 

    pw.flush(); 
    pw.close(); 
} 




public static Intent getSendEmailIntent(Context context, String email, 
      String subject, String body, String fileName) { 

    final Intent emailIntent = new Intent( 
       android.content.Intent.ACTION_SEND); 

    //Explicitly only use Gmail to send 
    emailIntent.setClassName("com.google.android.gm","com.google.android.gm.ComposeActivityGmail"); 

    emailIntent.setType("plain/text"); 

    //Add the recipients 
    emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, 
       new String[] { email }); 

    emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, subject); 

    emailIntent.putExtra(android.content.Intent.EXTRA_TEXT, body); 

    //Add the attachment by specifying a reference to our custom ContentProvider 
    //and the specific file of interest 
    emailIntent.putExtra( 
      Intent.EXTRA_STREAM, 
       Uri.parse("content://" + CachedFileProvider.AUTHORITY + "/" 
         + fileName)); 

    return emailIntent; 
} 

    enter code here 
+0

Exactamente lo que necesitaba, pero agregar la fuente sería agradable: http://stephendnicholas.com/archives/974. También lo encontré útil ya que es un poco más estructurado. – Compufreak

0

que estaba frente el mismo problema y el siguiente funcionó para mí.

Primero envíe la difusión para notificar al dispositivo que el archivo se ha creado/montado.

Por ejemplo:

sendBroadcast(new Intent(Intent.ACTION_MEDIA_MOUNTED,Uri.parse("file://"+storagePath))); 

Luego use el código para enviar el correo con archivo adjunto.

Intent email = new Intent(Intent.ACTION_SEND); 
email.putExtra(Intent.EXTRA_EMAIL, "Receiver Email Address"); 
email.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); 
email.putExtra(Intent.EXTRA_SUBJECT, "Subject"); 
email.putExtra(Intent.EXTRA_TEXT,"Email Text"); 

//Mime type of the attachment (or) u can use sendIntent.setType("*/*") 
//email.setType("text/plain"); 
email.setType("application/YourMimeType"); 

//Full Path to the attachment 
email.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://"+storagePath)); 
try 
{ 
    startActivity(Intent.createChooser(email, "Send Message...")); 
} 
catch (android.content.ActivityNotFoundException ex) 
{ 

} 
Cuestiones relacionadas