Прикрепление файла из внутренней памяти к электронной почте

В подобных темах здесь нет ответов, которые помогли... Я хочу создать сообщение электронной почты с прикрепленным файлом, файл находится во внутренней памяти. Вот код:

Intent i = new Intent(Intent.ACTION_SEND);
    i.setType("text/plain");
    i.putExtra(Intent.EXTRA_EMAIL  , new String[]{email});
    i.putExtra(Intent.EXTRA_SUBJECT, "Smart Weight Tracker");
    i.putExtra(Intent.EXTRA_TEXT   , "CSV file is in attachment");

    Uri uri;
    if(useExternal){
        uri = Uri.fromFile(new File(this.getExternalFilesDir(null),fname));
    }
    else{
        File f = new File(this.getFilesDir(),fname);
        f.setReadable(true, false);
        f.setWritable(true, false);
        uri = Uri.fromFile(f);
    }

    i.putExtra(Intent.EXTRA_STREAM, uri);

    try {
        startActivity(Intent.createChooser(i, "Send mail..."));
    } catch (android.content.ActivityNotFoundException ex) {
        Toast.makeText(MainActivity.this, "There are no email clients installed.", Toast.LENGTH_SHORT).show();
    }

Он отлично работает с внешним хранилищем, но у меня нет подключения при использовании внутреннего хранилища. Я проверил - файл открывается (его длина в моем приложении, показывающая Toast - в порядке,> 0).

Я пишу это так:

  OutputStreamWriter out =
                new OutputStreamWriter(con.openFileOutput(fname, Context.MODE_WORLD_READABLE));

В логарифме я вижу

I/Gmail   (28480): >>>>> Attachment uri: file:///data/data/Android.MyApp/files     /31.10.2011.csv
I/Gmail   (28480): >>>>>           type: text/plain
I/Gmail   (28480): >>>>>           name: 31.10.2011.csv
I/Gmail   (28480): >>>>>           size: 0

Size == 0!

Есть идеи?


person Maep    schedule 31.10.2011    source источник


Ответы (3)


Привет, Попробуйте использовать контент-провайдеров.

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

........ Android: прикрепление файлов из внутреннего кеша к 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.gmailattach.provider">

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

http://stephendnicholas.com/archives/974#comment-342

person Raj008    schedule 15.01.2013
comment
ОП не запрашивал конкретное решение для GMail. - person class stacker; 27.11.2013
comment
Кто-нибудь еще просматривает это семь лет спустя - оно все еще работает, и оно не обязательно должно быть специфичным для Gmail, если вы оставляете класс вне намерения (на самом деле, вы должны - я думаю, они что-то изменили в этом имени класса ; не будет работать с этим набором). Кроме того, убедитесь, что вы установили флаг намерения с помощью emailIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) и убедитесь, что у вашего ‹провайдера› установлено значение android:grantUriPermissions=true, иначе ничего не произойдет. - person NickGlowsinDark; 12.02.2020

Uri fileUri = Uri.fromFile(new File(context.getCacheDir()+ "/"+ fileName));                                           

Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
emailIntent.setType("text/plain");
emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT,
                    "Test Subject");
emailIntent.putExtra(android.content.Intent.EXTRA_TEXT,
                    "go on read the emails");
emailIntent.putExtra(Intent.EXTRA_STREAM, fileUri);

startActivity(emailIntent);

Пожалуйста, попробуйте этот код. Надеюсь, это поможет.

person Kannan Suresh    schedule 31.10.2011
comment
Спасибо... но результат тот же. Размер 0 в logcat, нет файла во вложении - person Maep; 31.10.2011

Я часами следил за кодом stephendnicholas, думая, что мне ДОЛЖЕН записать свои файлы во внутреннюю память, потому что на моем устройстве нет SD-карты.

Создание моего «внутреннего» файла, подобного этому, отлично сработало для меня:

File file = new File(getExternalFilesDir(null), filename); // :)

Это позволило избежать ограничений Gmail во время вложения.

До этого я создавал свой файловый объект следующим образом:

File file = new File(this.getFilesDir(), filename); //will not attach

Но если ваш файл буквально из внутреннего хранилища, то поставщики контента stephendnicholas и т. Д. Работают, если у вас есть сумасшедшие навыки Android.

person Dylan Kapp    schedule 01.05.2016