-->

Unloaded attachment isn't marked for download

2019-08-24 01:33发布

问题:

I am writing phone contacts to a file and exporting it through Email intent Action. Export works fine when i write the file to SD card.But when i write the file to phone memory of the emulator i get the mail without attachment. My Log displays "Unloaded attachment isn't marked for download".

Below is my code

        file = new File(ctx.getFilesDir().getAbsolutePath(),"file.txt");

        if (file.exists()) {
            file.delete();

        }
        writer = new BufferedWriter(new FileWriter(file));
        for (int i = 0; i < names.size(); i++) {
            writer.write(names.get(i) + "," + phnno.get(i) + "\r\n");
        }

        writer.flush();
        writer.close();

This is my Email Intent

                                Uri u1 = null;
                                u1 = Uri.fromFile(file);
                                System.out.println("u1 of URI"+u1); //u1 in logcat is "file:///data/data/com.android.contactxport/files/file.txt"


                                Intent sendIntent = new Intent(
                                        Intent.ACTION_SEND);
                                sendIntent.putExtra(Intent.EXTRA_SUBJECT,
                                        "Mail from ContactXPort App");
                                sendIntent
                                        .putExtra(Intent.EXTRA_STREAM, u1);
                                sendIntent.setType("text/html");
                                startActivity(sendIntent);

EDIT: The documnetation about unloaded attachment says

/**
 * Check whether the message with a given id has unloaded attachments.  If the message is
 * a forwarded message, we look instead at the messages's source for the attachments.  If the
 * message or forward source can't be found, we return false
 * @param context the caller's context
 * @param messageId the id of the message
 * @return whether or not the message has unloaded attachments
 */
public static boolean hasUnloadedAttachments(Context context, long messageId) {
    Message msg = Message.restoreMessageWithId(context, messageId);
    if (msg == null) return false;
    Attachment[] atts = Attachment.restoreAttachmentsWithMessageId(context, messageId);
    for (Attachment att: atts) {
        if (!attachmentExists(context, att)) {
            // If the attachment doesn't exist and isn't marked for download, we're in trouble
            // since the outbound message will be stuck indefinitely in the Outbox.  Instead,
            // we'll just delete the attachment and continue; this is far better than the
            // alternative.  In theory, this situation shouldn't be possible.
            if ((att.mFlags & (Attachment.FLAG_DOWNLOAD_FORWARD |
                    Attachment.FLAG_DOWNLOAD_USER_REQUEST)) == 0) {
                Log.d(Logging.LOG_TAG, "Unloaded attachment isn't marked for download: " +
                        att.mFileName + ", #" + att.mId);
                Attachment.delete(context, Attachment.CONTENT_URI, att.mId);
            } else if (att.mContentUri != null) {
                // In this case, the attachment file is gone from the cache; let's clear the
                // contentUri; this should be a very unusual case
                ContentValues cv = new ContentValues();
                cv.putNull(AttachmentColumns.CONTENT_URI);
                Attachment.update(context, Attachment.CONTENT_URI, att.mId, cv);
            }
            return true;
        }
    }
    return false;
}

Which i understand is the path is the issue here.But the path is fyn when i printed it in log.

Any help is much appreciated. Thanks in advance.

回答1:

This is what the documentation says about internal storage:

By default, files saved to the internal storage are private to your application and other applications cannot access them (nor can the user).

So i am now trying to use the native android Email App feature of attaching file in my Application.

or i can use other back-end development technique to attach file with the contents i want to export.



回答2:

From my recent experience, using Intent.EXTRA_STREAM with external file Uri -- be it located at getExternalCacheDir (), getExternalFilesDir (), or Environment.getExternalStorageDirectory () -- will effectively work with a number of email client app (probably: I only tested GMail, Evernote, and native Email client)... But notably: excepted via native Email App...

The test I have done yesterday involved native Email App against an MS Exchange corporate email account, and I received the "Unloaded attachment isn't marked for download: " debug message. The email message first looked correctly crafted, with attachment (even with attachment file size shown!), but email was sent without its attachment.

No such behaviour using GMail client: everything is fine. I would like to see attachment file size in GMail before sending it, but file is sent along with email message. On its side, Evernote creates an editable note with attachment file as an embedded object.

When I look at the reference source code you posted, I think Android native Email app developpers made slightly incorrect assumptions about attachment file. They simply didn't provide for an attachment coming from Intent.EXTRA_STREAM... Which is odd, since attachment is shown with message before sending, so it might simply just not be saved upon email creation in native email app database, or else attachment is incorrectly flagged/unflagged in the process.

I know this doesn't answer the question per se, but as for sending attachent via native Email app (so much for I can tell in Android ICS), I guess we are stuck!



回答3:

I have found that for native email app to accept the attachment you need to call Intent.setType as well as using the ACTION_SEND as opposed to ACTION_SENDTO.

Here is how I ultimately constructed my intent to get email attachment to work in both gmail and native apps:

Intent intent  = new Intent(Intent.ACTION_SEND); // SENDTO does not work for native email app
        intent.setData(Uri.fromParts("mailto",to, null));
        intent.putExtra(Intent.EXTRA_EMAIL, new String[] { to });
        intent.putExtra(Intent.EXTRA_SUBJECT, subject);
        intent.putExtra(Intent.EXTRA_TEXT, body);
        intent.setType("message/email");
        if (attachmentInCacheDir != null) {
            intent.putExtra(Intent.EXTRA_STREAM, Uri.parse("content://" + getAuthority(context) + "/" + attachmentInCacheDir.getName()));
        }
        context.startActivityForResult(Intent.createChooser(intent, "Send Email"), 1000);

As you can see I also am using a content provider for file access to avoid copying files to external storage. This was a whole new can of worms as the native app calls 'query' on your provider to ask for file size. If size is zero, then it wont attach. Gmail is much more lenient.