2010-11-08 5 views
11

Standardmäßig sind Dateien, die im internen Speicher gespeichert sind, für Ihre Anwendung privat und andere Anwendungen können nicht auf sie zugreifen (auch nicht für den Benutzer).Android - keine Datei in E-Mail anhängen

Ich kann die Datei "/ data/data/package_name/files/in datei explore in DDMS sehen, aber wenn ich die obige Datei-URI mit imageUri in E-Mail angehängt habe, dann sah ich, dass die angehängte Datei 0kb ist. ich habe die Standard-E-Mail-APIs von Android verwendet.

Kann mir jemand vorschlagen, wie eine Datei in E-Mail anhängen, die auf die Anwendung ist privat?

obwohl ich erfolgreich bin in der Lage, die Datei in SD-Karte zu speichern Wenn die SD-Karte nicht verfügbar ist und s Wie kann ich die Datei an den internen Speicher anhängen?

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

Haben Sie jemals eine Lösung für dieses Problem gefunden? – JehandadK

+0

Ich sah mich dem ähnlichen Problem gegenüber. Von SD-Karte geht das prima ... Aber aus dem internen Speicher ist mir diese Funktionalität nicht gelungen. Vielleicht hilft das Spielen mit MIME-Typen weiterzumachen. – Mike

+0

Könnten Sie bitte elobrate? – pankaj

Antwort

1

Versuchen Context.MODE_WORLD_READABLE statt Context.MODE_PRIVATE zu verwenden, wenn Sie die Datei speichern. Dann haben andere Apps Zugriff auf die Datei.

+0

@, ich hatte bereits mit MODE_WORLD_WRITEABLE versucht, aber es funktioniert nicht. – pankaj

+0

@pankaj aber hast du es mit MODE_WORLD_READABLE versucht? –

6

Wenn Sie versuchen, Datei aus dem internen Speicher zu befestigen, schreibt GMail einen Fehler in das Protokoll:

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

E-Mail-Anwendung würde zeigt Ihnen die angehängte Datei, auch wenn es existiert nicht physisch tut.

Wie für einen externen Speicher, sagt Dokumentation, dass:

Jedes Android-kompatibeles Gerät einen gemeinsamen „externen Speicher“ unterstützt, die Sie speichern Dateien verwenden können. Dies kann ein Wechselspeichermedium (z. B. eine SD-Karte) oder ein interner (nicht entfernbarer) Speicher sein.

Das bedeutet, Sie müssen sich keine Sorgen machen, dass das Gerät überhaupt keinen externen Speicher hat. Trotzdem kann externer Speicher manchmal nicht verfügbar sein. Siehe http://developer.android.com/guide/topics/data/data-storage.html#filesExternal

+0

Danke! Ich konnte nicht herausfinden, warum es scheiterte und ich dachte nicht daran, die Filter in meinem LogCat-Fenster zu ändern. –

1

Ich habe auch dieses Problem mit internen Dateien erlebt und obwohl ich openFileInput mit MODE_WORLD_READABLE auf /data/data//files/testFileName.txt und verwendet, um die URI.parse mit dem Extra „/“ verwendet habe (siehe unten), fehlt dem empfangenen Test per E-Mail immer noch der gewünschte Anhang. Es tut mir leid, aber es gibt keine Antwort, außer versuchen, externe Dateien auf der SD-Karte zu verwenden - das ist mein nächstes Experiment!

Code:

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

Um eine private Datei, die Sie einen Contentprovider verwenden müssen, teilen Zugriff auf Dateien von anderen Anwendungen zur Verfügung zu stellen. Hier ist ein großartiges Beispiel: Android: Attaching files from internal cache to Gmail.

Auch wenn das Tutorial erwähnt, dass Sie Ihren Anbieter in der Android-Manifestdatei deklarieren müssen, gibt es nicht an, dass es in <application> enthalten sein sollte, also stellen Sie sicher, dass wenn Sie es innerhalb <application> </application> deklarieren.

3

Dieser Kodex können Sie Idee über Bindung erhalten helfen:

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

Der obige Code erfordert, dass Sie die folgende Berechtigung auf Ihre Manifest-Datei hinzufügen:

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

Einfach und klar –

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

Genau was ich brauchte, aber die Quelle hinzufügen wäre nett: http://stephendnicholas.com/archives/974. Ich fand es auch nützlich, da es etwas strukturierter ist. – Compufreak

0

Ich war mit Blick auf Das gleiche Problem und das gleiche Ergebnis haben für mich funktioniert.

Senden Sie zuerst Broadcast, um dem Gerät mitzuteilen, dass die Datei erstellt/bereitgestellt wurde.

Zum Beispiel:

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

Dann Code verwenden Mail mit Anhang zu senden.

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) 
{ 

}