0

In my android app I have created a PDF that I would like the user to be able to send from my app through an email client. Right now the email client will show that the PDF is attached but is unable to send the attachment. Is this a permissions problem or something? Any suggestions?

EDIT stored to external by adding getExternalCacheDir() and problem persists

Email function

private void EmailDialog(){
        //create a dialog that prompts the user whether or not they want to send the PDF
        dialogBuilder = new AlertDialog.Builder(this);
        final TextView txtInput = new TextView(this);

        dialogBuilder.setTitle("Email Audit");
        dialogBuilder.setMessage("Do you want to email this audit?");
        dialogBuilder.setView(txtInput);
        dialogBuilder.setPositiveButton("Add", new DialogInterface.OnClickListener() {
            //allows user to send PDF over their email application choice
            @Override
            public void onClick(DialogInterface dialog, int which) {
                Intent i = new Intent(Intent.ACTION_SEND);
                i.setType("message/rfc822");
                PDF = new File(getExternalCacheDir() + PDFname);
                i.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(PDF));
                try {
                    startActivity(Intent.createChooser(i, "Send mail..."));
                } catch (android.content.ActivityNotFoundException ex) {
                    Toast.makeText(OldLocation.this, "There are no email clients installed.", Toast.LENGTH_SHORT).show();
                }
            }
        });
        dialogBuilder.setNegativeButton("Delete", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                RemoveDialog();
            }
        });

        AlertDialog emailDialog = dialogBuilder.create();
        emailDialog.show();
    }

PDF function

@TargetApi(Build.VERSION_CODES.KITKAT)
    private void createPDF(){


        // open a new document
        PrintAttributes pa = new PrintAttributes.Builder().setMediaSize(PrintAttributes.MediaSize.NA_LETTER).setMinMargins(PrintAttributes.Margins.NO_MARGINS).build();
        PrintedPdfDocument document = new PrintedPdfDocument(this, pa);

        // start a page
        PdfDocument.Page page = document.startPage(0);

        // draw something on the page
        View content = textView;
        content.draw(page.getCanvas());



        // finish the page
        document.finishPage(page);

        // add more pages

        // write the document content

        try {
            File PDFs = getExternalCacheDir();
            File file = new File(PDFs, companyInfo.getName() + ".pdf");
            file.createNewFile();
            FileOutputStream fos = new FileOutputStream(file);
            document.writeTo(fos);
            fos.close();

            //close the document
            document.close();
        } catch (Exception ex){

        }

        realm.beginTransaction();
        companyInfo = realm.where(CompanyInfo.class).findFirst();
        companyInfo.removeFromRealm();
        realm.commitTransaction();
    }
JJ Stamp
  • 121
  • 2
  • 13
  • Which email client is failing to send it? – adelphus Aug 13 '15 at 17:38
  • Gmail and google chrome can't save too – JJ Stamp Aug 13 '15 at 17:39
  • It could be the file location is rejected. [This question](http://stackoverflow.com/questions/2206397/android-intent-action-send-with-extra-stream-doesnt-attach-any-image-when-choo) had a similar problem which was resolved by transferring the file to a public area – adelphus Aug 13 '15 at 17:42

2 Answers2

1

Is this a permissions problem or something?

Yes. There are exactly zero apps on the face of the planet, other than yours, that can access your file, as it is on internal storage, private to your app.

Also, NEVER HARDCODE PATHS. Your /data/data/ stuff will fail on every Android 4.2+ device where the user is on a secondary account.

Any suggestions?

You can stick with internal storage, though you will need to use a FileProvider, perhaps with my LegacyCompatCursorWrapper, to serve the file. This sample app demonstrates this, albeit with ACTION_VIEW instead of ACTION_SEND.

Or, put the file on external storage.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • By adding to external that would make it so that if the app was deleted the files would still stay on the device, correct? – JJ Stamp Aug 13 '15 at 17:49
  • @JJStamp: Not necessarily. If you use `getExternalFilesDir()`, files in that directory will be removed on an uninstall, just like `getFilesDir()` does for internal storage. If, OTOH, you write elsewhere (e.g., `Environment.getExternalStoragePublicDirectory()`), those files will survive an uninstall. – CommonsWare Aug 13 '15 at 17:51
  • edited answer with the saved PDF to the external cache and the problem still occurs – JJ Stamp Aug 13 '15 at 18:09
  • @JJStamp: First, never use concatenation to build a path. Use `new File(getExternalCacheDir(), PDFname)`. Second, the MIME type for PDF is `application/pdf`, not `message/rfc822`. Otherwise, this should be OK, though I have never tried it with `getExternalCacheDir()`, only `getExternalFilesDir()`. – CommonsWare Aug 13 '15 at 18:12
0

I ran into an issue in addition to the permissions. I'd guess it has to do with Gmail lazy holding the Uri but not reading it until (sometimes many minutes) later. You'll notice the mail sits in the outbox sometimes.

It seems like if you delete the file before the email exits the outbox, the email gets sent w/o the attachment. I had to add a long delay on how long to wait before deleting the file

Jerry Sha
  • 3,931
  • 2
  • 23
  • 16