2011-01-06 11:56:20 -05:00
|
|
|
package com.fsck.k9.view;
|
|
|
|
|
|
|
|
import android.content.Context;
|
|
|
|
import android.content.Intent;
|
|
|
|
import android.graphics.Bitmap;
|
|
|
|
import android.graphics.BitmapFactory;
|
|
|
|
import android.net.Uri;
|
|
|
|
import android.os.Environment;
|
|
|
|
import android.util.AttributeSet;
|
|
|
|
import android.util.Log;
|
|
|
|
import android.view.View;
|
|
|
|
import android.widget.*;
|
|
|
|
import com.fsck.k9.Account;
|
|
|
|
import com.fsck.k9.K9;
|
|
|
|
import com.fsck.k9.R;
|
|
|
|
import com.fsck.k9.controller.MessagingController;
|
|
|
|
import com.fsck.k9.controller.MessagingListener;
|
|
|
|
import com.fsck.k9.helper.MediaScannerNotifier;
|
|
|
|
import com.fsck.k9.helper.SizeFormatter;
|
|
|
|
import com.fsck.k9.helper.Utility;
|
|
|
|
import com.fsck.k9.mail.Message;
|
|
|
|
import com.fsck.k9.mail.Part;
|
|
|
|
import com.fsck.k9.mail.internet.MimeUtility;
|
|
|
|
import com.fsck.k9.mail.store.LocalStore.LocalAttachmentBodyPart;
|
|
|
|
import com.fsck.k9.provider.AttachmentProvider;
|
|
|
|
import org.apache.commons.io.IOUtils;
|
|
|
|
|
|
|
|
import java.io.*;
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
public class AttachmentView extends FrameLayout {
|
2011-01-06 11:56:20 -05:00
|
|
|
|
|
|
|
private Context mContext;
|
|
|
|
public Button viewButton;
|
|
|
|
public Button downloadButton;
|
|
|
|
public LocalAttachmentBodyPart part;
|
|
|
|
private Message mMessage;
|
|
|
|
private Account mAccount;
|
|
|
|
private MessagingController mController;
|
|
|
|
private MessagingListener mListener;
|
|
|
|
public String name;
|
|
|
|
public String contentType;
|
|
|
|
public long size;
|
|
|
|
public ImageView iconView;
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
public AttachmentView(Context context, AttributeSet attrs, int defStyle) {
|
2011-01-06 11:56:20 -05:00
|
|
|
super(context, attrs, defStyle);
|
|
|
|
mContext = context;
|
|
|
|
}
|
2011-02-06 17:09:48 -05:00
|
|
|
public AttachmentView(Context context, AttributeSet attrs) {
|
2011-01-06 11:56:20 -05:00
|
|
|
super(context, attrs);
|
|
|
|
mContext = context;
|
|
|
|
}
|
2011-02-06 17:09:48 -05:00
|
|
|
public AttachmentView(Context context) {
|
2011-01-06 11:56:20 -05:00
|
|
|
super(context);
|
|
|
|
mContext = context;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
public boolean populateFromPart(Part inputPart, Message message, Account account, MessagingController controller, MessagingListener listener) {
|
|
|
|
try {
|
2011-01-06 11:56:20 -05:00
|
|
|
part = (LocalAttachmentBodyPart) inputPart;
|
|
|
|
|
|
|
|
contentType = MimeUtility.unfoldAndDecode(part.getContentType());
|
|
|
|
String contentDisposition = MimeUtility.unfoldAndDecode(part.getDisposition());
|
|
|
|
|
|
|
|
name = MimeUtility.getHeaderParameter(contentType, "name");
|
2011-02-06 17:09:48 -05:00
|
|
|
if (name == null) {
|
2011-01-06 11:56:20 -05:00
|
|
|
name = MimeUtility.getHeaderParameter(contentDisposition, "filename");
|
|
|
|
}
|
2011-02-06 17:09:48 -05:00
|
|
|
if (name == null) {
|
2011-01-06 11:56:20 -05:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
mAccount = account;
|
|
|
|
mMessage = message;
|
|
|
|
mController = controller;
|
|
|
|
mListener = listener;
|
|
|
|
|
|
|
|
size = Integer.parseInt(MimeUtility.getHeaderParameter(contentDisposition, "size"));
|
2011-03-24 19:37:53 -04:00
|
|
|
contentType = MimeUtility.getMimeTypeForViewing(part.getMimeType(), name);
|
2011-01-06 11:56:20 -05:00
|
|
|
TextView attachmentName = (TextView) findViewById(R.id.attachment_name);
|
|
|
|
TextView attachmentInfo = (TextView) findViewById(R.id.attachment_info);
|
|
|
|
ImageView attachmentIcon = (ImageView) findViewById(R.id.attachment_icon);
|
|
|
|
viewButton = (Button) findViewById(R.id.view);
|
|
|
|
downloadButton = (Button) findViewById(R.id.download);
|
|
|
|
if ((!MimeUtility.mimeTypeMatches(contentType, K9.ACCEPTABLE_ATTACHMENT_VIEW_TYPES))
|
2011-02-06 17:09:48 -05:00
|
|
|
|| (MimeUtility.mimeTypeMatches(contentType, K9.UNACCEPTABLE_ATTACHMENT_VIEW_TYPES))) {
|
2011-01-06 11:56:20 -05:00
|
|
|
viewButton.setVisibility(View.GONE);
|
2011-01-17 19:04:11 -05:00
|
|
|
}
|
2011-01-06 11:56:20 -05:00
|
|
|
if ((!MimeUtility.mimeTypeMatches(contentType, K9.ACCEPTABLE_ATTACHMENT_DOWNLOAD_TYPES))
|
2011-02-06 17:09:48 -05:00
|
|
|
|| (MimeUtility.mimeTypeMatches(contentType, K9.UNACCEPTABLE_ATTACHMENT_DOWNLOAD_TYPES))) {
|
2011-01-06 11:56:20 -05:00
|
|
|
downloadButton.setVisibility(View.GONE);
|
|
|
|
}
|
2011-02-06 17:09:48 -05:00
|
|
|
if (size > K9.MAX_ATTACHMENT_DOWNLOAD_SIZE) {
|
2011-01-06 11:56:20 -05:00
|
|
|
viewButton.setVisibility(View.GONE);
|
|
|
|
downloadButton.setVisibility(View.GONE);
|
|
|
|
}
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
viewButton.setOnClickListener(new OnClickListener() {
|
2011-01-06 11:56:20 -05:00
|
|
|
@Override
|
2011-02-06 17:09:48 -05:00
|
|
|
public void onClick(View v) {
|
2011-01-06 11:56:20 -05:00
|
|
|
onViewButtonClicked();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
downloadButton.setOnClickListener(new OnClickListener() {
|
2011-01-06 11:56:20 -05:00
|
|
|
@Override
|
2011-02-06 17:09:48 -05:00
|
|
|
public void onClick(View v) {
|
2011-01-06 11:56:20 -05:00
|
|
|
onSaveButtonClicked();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
attachmentName.setText(name);
|
|
|
|
attachmentInfo.setText(SizeFormatter.formatSize(mContext, size));
|
|
|
|
Bitmap previewIcon = getPreviewIcon();
|
2011-02-06 17:09:48 -05:00
|
|
|
if (previewIcon != null) {
|
2011-01-06 11:56:20 -05:00
|
|
|
attachmentIcon.setImageBitmap(previewIcon);
|
2011-02-06 17:09:48 -05:00
|
|
|
} else {
|
2011-01-06 11:56:20 -05:00
|
|
|
attachmentIcon.setImageResource(R.drawable.attached_image_placeholder);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
catch (Exception e) {
|
|
|
|
Log.e(K9.LOG_TAG, "error ", e);
|
2011-01-06 11:56:20 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
private Bitmap getPreviewIcon() {
|
|
|
|
try {
|
2011-01-06 11:56:20 -05:00
|
|
|
return BitmapFactory.decodeStream(
|
|
|
|
mContext.getContentResolver().openInputStream(
|
|
|
|
AttachmentProvider.getAttachmentThumbnailUri(mAccount,
|
|
|
|
part.getAttachmentId(),
|
|
|
|
62,
|
|
|
|
62)));
|
2011-02-06 17:09:48 -05:00
|
|
|
} catch (Exception e) {
|
2011-01-06 11:56:20 -05:00
|
|
|
/*
|
|
|
|
* We don't care what happened, we just return null for the preview icon.
|
|
|
|
*/
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
private void onViewButtonClicked() {
|
|
|
|
if (mMessage != null) {
|
|
|
|
mController.loadAttachment(mAccount, mMessage, part, new Object[] { false, this }, mListener);
|
2011-01-06 11:56:20 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
private void onSaveButtonClicked() {
|
2011-01-06 11:56:37 -05:00
|
|
|
saveFile();
|
2011-01-06 11:56:20 -05:00
|
|
|
}
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
public void writeFile() {
|
|
|
|
try {
|
2011-01-06 11:56:20 -05:00
|
|
|
File file = Utility.createUniqueFile(Environment.getExternalStorageDirectory(), name);
|
2011-02-06 17:09:48 -05:00
|
|
|
Uri uri = AttachmentProvider.getAttachmentUri(mAccount, part.getAttachmentId());
|
2011-01-06 11:56:20 -05:00
|
|
|
InputStream in = mContext.getContentResolver().openInputStream(uri);
|
|
|
|
OutputStream out = new FileOutputStream(file);
|
|
|
|
IOUtils.copy(in, out);
|
|
|
|
out.flush();
|
|
|
|
out.close();
|
|
|
|
in.close();
|
|
|
|
attachmentSaved(file.getName());
|
|
|
|
new MediaScannerNotifier(mContext, file);
|
2011-02-06 17:09:48 -05:00
|
|
|
} catch (IOException ioe) {
|
2011-01-06 11:56:20 -05:00
|
|
|
attachmentNotSaved();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
public void saveFile() {
|
|
|
|
if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
|
2011-01-06 11:56:37 -05:00
|
|
|
/*
|
|
|
|
* Abort early if there's no place to save the attachment. We don't want to spend
|
|
|
|
* the time downloading it and then abort.
|
|
|
|
*/
|
|
|
|
Toast.makeText(mContext,
|
|
|
|
mContext.getString(R.string.message_view_status_attachment_not_saved),
|
|
|
|
Toast.LENGTH_SHORT).show();
|
|
|
|
return;
|
|
|
|
}
|
2011-02-06 17:09:48 -05:00
|
|
|
if (mMessage != null) {
|
|
|
|
mController.loadAttachment(mAccount, mMessage, part, new Object[] {true, this}, mListener);
|
2011-01-06 11:56:37 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
public void showFile() {
|
2011-03-24 18:36:59 -04:00
|
|
|
Uri uri = AttachmentProvider.getAttachmentUriForViewing(mAccount, part.getAttachmentId());
|
2011-01-06 11:56:20 -05:00
|
|
|
Intent intent = new Intent(Intent.ACTION_VIEW);
|
|
|
|
intent.setData(uri);
|
|
|
|
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
2011-02-06 17:09:48 -05:00
|
|
|
try {
|
2011-01-06 11:56:20 -05:00
|
|
|
mContext.startActivity(intent);
|
2011-02-06 17:09:48 -05:00
|
|
|
} catch (Exception e) {
|
2011-01-06 11:56:20 -05:00
|
|
|
Log.e(K9.LOG_TAG, "Could not display attachment of type " + contentType, e);
|
|
|
|
Toast toast = Toast.makeText(mContext, mContext.getString(R.string.message_view_no_viewer, contentType), Toast.LENGTH_LONG);
|
|
|
|
toast.show();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-01-17 05:41:48 -05:00
|
|
|
/**
|
|
|
|
* Check the {@link PackageManager} if the phone has an application
|
|
|
|
* installed to view this type of attachment.
|
|
|
|
* If not, {@link #viewButton} is disabled.
|
|
|
|
* This should be done in any place where
|
|
|
|
* attachment.viewButton.setEnabled(enabled); is called.
|
|
|
|
* This method is safe to be called from the UI-thread.
|
|
|
|
*/
|
2011-02-06 17:09:48 -05:00
|
|
|
public void checkViewable() {
|
|
|
|
if (viewButton.getVisibility() == View.GONE) {
|
2011-01-17 19:04:11 -05:00
|
|
|
// nothing to do
|
|
|
|
return;
|
|
|
|
}
|
2011-02-06 17:09:48 -05:00
|
|
|
if (!viewButton.isEnabled()) {
|
2011-01-17 19:04:11 -05:00
|
|
|
// nothing to do
|
|
|
|
return;
|
|
|
|
}
|
2011-02-06 17:09:48 -05:00
|
|
|
try {
|
2011-03-24 18:36:59 -04:00
|
|
|
Uri uri = AttachmentProvider.getAttachmentUriForViewing(mAccount, part.getAttachmentId());
|
2011-01-17 19:04:11 -05:00
|
|
|
Intent intent = new Intent(Intent.ACTION_VIEW);
|
|
|
|
intent.setData(uri);
|
|
|
|
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
2011-02-06 17:09:48 -05:00
|
|
|
if (intent.resolveActivity(mContext.getPackageManager()) == null) {
|
2011-01-17 19:04:11 -05:00
|
|
|
viewButton.setEnabled(false);
|
|
|
|
}
|
|
|
|
// currently we do not cache re result.
|
2011-02-06 17:09:48 -05:00
|
|
|
} catch (Exception e) {
|
2011-01-17 19:04:11 -05:00
|
|
|
Log.e(K9.LOG_TAG, "Cannot resolve activity to determine if we shall show the 'view'-button for an attachment", e);
|
|
|
|
}
|
|
|
|
}
|
2011-01-17 05:41:48 -05:00
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
public void attachmentSaved(final String filename) {
|
2011-01-06 11:56:20 -05:00
|
|
|
Toast.makeText(mContext, String.format(
|
|
|
|
mContext.getString(R.string.message_view_status_attachment_saved), filename),
|
|
|
|
Toast.LENGTH_LONG).show();
|
|
|
|
}
|
|
|
|
|
2011-02-06 17:09:48 -05:00
|
|
|
public void attachmentNotSaved() {
|
2011-01-06 11:56:20 -05:00
|
|
|
Toast.makeText(mContext,
|
|
|
|
mContext.getString(R.string.message_view_status_attachment_not_saved),
|
|
|
|
Toast.LENGTH_LONG).show();
|
|
|
|
}
|
|
|
|
}
|