0

Before anything else, I have actually read through several threads regarding sending attachments on Android. That said, I haven't found a solution to my problem.

My app is relatively simple, user types numbers, they get saved to "values.csv" using openFileOutput(filename, Context.MODE_APPEND);.

Now, here's the code I'm using to attach the file to an email and send (I got it from one of the other file threads.)

 private void sendEmail(String email) {

    File file = getFileStreamPath(filename);
    Uri path = Uri.fromFile(file);
    Intent intent = new Intent(android.content.Intent.ACTION_SEND);
    intent.setType("application/octet-stream");
    intent.putExtra(android.content.Intent.EXTRA_SUBJECT, "Test");
    String to[] = { email };
    intent.putExtra(Intent.EXTRA_EMAIL, to);
    intent.putExtra(Intent.EXTRA_TEXT, "Testing...");
    intent.putExtra(Intent.EXTRA_STREAM, path);
    startActivityForResult(Intent.createChooser(intent, "Send mail..."),
            1222);
}

This opens my email client, which does everything right except attach the file, showing me a toast notification saying "file doesn't exist."

Am I missing something? I've already added the permissions for reading and writing to external storage, by the way.

Any and all help would be much appreciated.

EDIT: I can use the File Explorer module in DDMS and navigate to /data/data/com.example.myapp/files/, where my values.csv is located, and copy it to my computer, so the file DOES exist. Must be a problem with my code.

iVikD
  • 296
  • 7
  • 21
  • I'm afraid the mail app cannot read your file, have you tried to change the mode in the openFileOutput to MODE_WORLD_READABLE? – Niko Adrianus Yuwono Oct 22 '14 at 02:56
  • Well it says that it was deprecated in API 17, but it seems to work, now Mail can read it and send it. However, by changing it to MODE_WORLD_READABLE, It's lost the APPEND quality, which is pretty important... Is there any way to keep both? – iVikD Oct 22 '14 at 03:01
  • 1
    Yeah actually it's not a good move because a security hole, but it lead me to an answer, please wait I will write an answer for you :) – Niko Adrianus Yuwono Oct 22 '14 at 03:02
  • Append and world readable should not be exclusive, but some mail clients won't take an attachment from another app's internal storage even if it is readable to them (unless you trick them). So it's best to either use external storage, or the modern "android way" with a content provider. – Chris Stratton Oct 22 '14 at 03:41

2 Answers2

3

So another way to attach the email except using MODE_WORLD_READABLE is using ContentProvider. There is a nice tutorial to do this in here

but I will explain it to you shortly too and then you can read that tutorial after that.

So first you need to create a ContentProvider that provides access to the files from the application’s internal cache.

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

and then write a temporary file

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

And then pass it to the email Intent

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

and don't forget to add this to the manifest

<provider android:name="CachedFileProvider" android:grantUriPermissions="true"
android:authorities="yourpackage.provider"></provider>
Niko Adrianus Yuwono
  • 11,012
  • 8
  • 42
  • 64
2

I see the answers and of course the question. You asked how you can send a file from android, but in your code example you are talking about sending by email.

Those are two different things at all...

For sending by email you already have answers so I will not enter it at all. For sending files from android is something else:

  1. you can create a socket connection to your server and send it. you have of course to write both client and server side. An example can be found here : Sending file over socket...

  2. you can use an ftp server and upload it to there. you can use any server. example : It's using apache ftp client library (open source)

  3. you can use a http request and make it a post (this method is preferred only for small files) example : Sending file with POST over HTTP

  4. you can also use dropbox api or amazon s3 sdk's so you don't care about any connections issues and retries and so on and at the end you have a link to the file and pass over the link.

    a. DropBox API : documentation

    b. Amazon S3 SDK API : documentation

    c. Google Drive API : documentation The advantages in working with Google Drive.

    1. Is working excelent on Android
    2. Authentication is much easier.
    3. The "used space" is on user account.

regards

Community
  • 1
  • 1
danysz
  • 580
  • 3
  • 11
  • Nice Explanation. Can u provide some Sample code for this?? "Attach Audio file and send to some other user of my App" – LittleGirl Nov 03 '14 at 19:31