/**
  * 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.
  */
 public void checkViewable() {
   if (viewButton.getVisibility() == View.GONE) {
     // nothing to do
     return;
   }
   if (!viewButton.isEnabled()) {
     // nothing to do
     return;
   }
   try {
     Uri uri = AttachmentProvider.getAttachmentUriForViewing(mAccount, part.getAttachmentId());
     Intent intent = new Intent(Intent.ACTION_VIEW);
     intent.setData(uri);
     intent.addFlags(
         Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
     if (intent.resolveActivity(mContext.getPackageManager()) == null) {
       viewButton.setEnabled(false);
     }
     // currently we do not cache re result.
   } catch (Exception e) {
     Log.e(
         K9.LOG_TAG,
         "Cannot resolve activity to determine if we shall show the 'view'-button for an attachment",
         e);
   }
 }
 private Bitmap getPreviewIcon() {
   Bitmap icon = null;
   try {
     InputStream input =
         mContext
             .getContentResolver()
             .openInputStream(
                 AttachmentProvider.getAttachmentThumbnailUri(
                     mAccount, part.getAttachmentId(), 62, 62));
     icon = BitmapFactory.decodeStream(input);
     input.close();
   } catch (Exception e) {
     /*
      * We don't care what happened, we just return null for the preview icon.
      */
   }
   return icon;
 }
 /**
  * Writes the attachment onto the given path
  *
  * @param directory: the base dir where the file should be saved.
  */
 public void writeFile(File directory) {
   try {
     String filename = Utility.sanitizeFilename(name);
     File file = Utility.createUniqueFile(directory, filename);
     Uri uri = AttachmentProvider.getAttachmentUri(mAccount, part.getAttachmentId());
     InputStream in = mContext.getContentResolver().openInputStream(uri);
     OutputStream out = new FileOutputStream(file);
     IOUtils.copy(in, out);
     out.flush();
     out.close();
     in.close();
     attachmentSaved(file.toString());
     new MediaScannerNotifier(mContext, file);
   } catch (IOException ioe) {
     if (K9.DEBUG) {
       Log.e(K9.LOG_TAG, "Error saving attachment", ioe);
     }
     attachmentNotSaved();
   }
 }
  public void showFile() {
    Uri uri = AttachmentProvider.getAttachmentUriForViewing(mAccount, part.getAttachmentId());
    Intent intent = new Intent(Intent.ACTION_VIEW);
    // We explicitly set the ContentType in addition to the URI because some attachment viewers
    // (such as Polaris office 3.0.x) choke on documents without a mime type
    intent.setDataAndType(uri, contentType);
    intent.addFlags(
        Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);

    try {
      mContext.startActivity(intent);
    } catch (Exception e) {
      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();
    }
  }
  /**
   * Populates this view with information about the attachment.
   *
   * <p>This method also decides which attachments are displayed when the "show attachments" button
   * is pressed, and which attachments are only displayed after the "show more attachments" button
   * was pressed.<br>
   * Inline attachments with content ID and unnamed attachments fall into the second category.
   *
   * @param inputPart
   * @param message
   * @param account
   * @param controller
   * @param listener
   * @return {@code true} for a regular attachment. {@code false}, otherwise.
   * @throws MessagingException In case of an error
   */
  public boolean populateFromPart(
      Part inputPart,
      Message message,
      Account account,
      MessagingController controller,
      MessagingListener listener)
      throws MessagingException {
    boolean firstClassAttachment = true;
    part = (LocalAttachmentBodyPart) inputPart;

    contentType = MimeUtility.unfoldAndDecode(part.getContentType());
    String contentDisposition = MimeUtility.unfoldAndDecode(part.getDisposition());

    name = MimeUtility.getHeaderParameter(contentType, "name");
    if (name == null) {
      name = MimeUtility.getHeaderParameter(contentDisposition, "filename");
    }

    if (name == null) {
      firstClassAttachment = false;
      String extension = MimeUtility.getExtensionByMimeType(contentType);
      name = "noname" + ((extension != null) ? "." + extension : "");
    }

    // Inline parts with a content-id are almost certainly components of an HTML message
    // not attachments. Only show them if the user pressed the button to show more
    // attachments.
    if (contentDisposition != null
        && MimeUtility.getHeaderParameter(contentDisposition, null).matches("^(?i:inline)")
        && part.getHeader(MimeHeader.HEADER_CONTENT_ID) != null) {
      firstClassAttachment = false;
    }

    mAccount = account;
    mMessage = message;
    mController = controller;
    mListener = listener;

    String sizeParam = MimeUtility.getHeaderParameter(contentDisposition, "size");
    if (sizeParam != null) {
      try {
        size = Integer.parseInt(sizeParam);
      } catch (NumberFormatException e) {
        /* ignore */
      }
    }

    contentType = MimeUtility.getMimeTypeForViewing(part.getMimeType(), name);
    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))
        || (MimeUtility.mimeTypeMatches(contentType, K9.UNACCEPTABLE_ATTACHMENT_VIEW_TYPES))) {
      viewButton.setVisibility(View.GONE);
    }
    if ((!MimeUtility.mimeTypeMatches(contentType, K9.ACCEPTABLE_ATTACHMENT_DOWNLOAD_TYPES))
        || (MimeUtility.mimeTypeMatches(contentType, K9.UNACCEPTABLE_ATTACHMENT_DOWNLOAD_TYPES))) {
      downloadButton.setVisibility(View.GONE);
    }
    if (size > K9.MAX_ATTACHMENT_DOWNLOAD_SIZE) {
      viewButton.setVisibility(View.GONE);
      downloadButton.setVisibility(View.GONE);
    }

    viewButton.setOnClickListener(this);
    downloadButton.setOnClickListener(this);
    downloadButton.setOnLongClickListener(this);

    attachmentName.setText(name);
    attachmentInfo.setText(SizeFormatter.formatSize(mContext, size));
    Bitmap previewIcon = getPreviewIcon();
    if (previewIcon != null) {
      attachmentIcon.setImageBitmap(previewIcon);
    } else {
      attachmentIcon.setImageResource(R.drawable.attached_image_placeholder);
    }

    return firstClassAttachment;
  }