summaryrefslogtreecommitdiffstats
path: root/src/com/android
diff options
context:
space:
mode:
authorAndrew Sapperstein <asapperstein@google.com>2013-10-09 18:31:50 -0700
committerAndrew Sapperstein <asapperstein@google.com>2013-10-11 10:06:20 -0700
commit562c5ba7235948cf1d20a9afa40e67cd62f43cf7 (patch)
treea9f4b987f3fc76a7681850065659be35f2782af9 /src/com/android
parent926825ba228b25307cb23a6c384f24fc3637d627 (diff)
downloadandroid_packages_apps_UnifiedEmail-562c5ba7235948cf1d20a9afa40e67cd62f43cf7.tar.gz
android_packages_apps_UnifiedEmail-562c5ba7235948cf1d20a9afa40e67cd62f43cf7.tar.bz2
android_packages_apps_UnifiedEmail-562c5ba7235948cf1d20a9afa40e67cd62f43cf7.zip
Print single message and offscreen webview.
b/10712542. Also supports Eml printing and secure printing (though that's email only and has some buggy rendering). Also fixes the no subject crash. b/11136365 Change-Id: Ie5f6e7d7e1762c115df3169b6e62dc439545f08c
Diffstat (limited to 'src/com/android')
-rw-r--r--src/com/android/mail/browse/EmlMessageViewFragment.java14
-rw-r--r--src/com/android/mail/browse/EmlViewerActivity.java1
-rw-r--r--src/com/android/mail/browse/MessageHeaderView.java22
-rw-r--r--src/com/android/mail/print/HtmlPrintTemplates.java10
-rw-r--r--src/com/android/mail/print/PrintUtils.java (renamed from src/com/android/mail/print/Printer.java)118
-rw-r--r--src/com/android/mail/ui/AbstractConversationViewFragment.java6
-rw-r--r--src/com/android/mail/ui/ConversationViewFragment.java19
-rw-r--r--src/com/android/mail/ui/SecureConversationViewController.java10
-rw-r--r--src/com/android/mail/ui/SecureConversationViewFragment.java2
9 files changed, 153 insertions, 49 deletions
diff --git a/src/com/android/mail/browse/EmlMessageViewFragment.java b/src/com/android/mail/browse/EmlMessageViewFragment.java
index c0f7f9b30..ad2223200 100644
--- a/src/com/android/mail/browse/EmlMessageViewFragment.java
+++ b/src/com/android/mail/browse/EmlMessageViewFragment.java
@@ -28,6 +28,7 @@ import android.os.Bundle;
import android.os.Handler;
import android.provider.OpenableColumns;
import android.view.LayoutInflater;
+import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebView;
@@ -149,6 +150,7 @@ public class EmlMessageViewFragment extends Fragment
mWebViewClient = new EmlWebViewClient(null);
mViewController = new SecureConversationViewController(this);
+ setHasOptionsMenu(true);
getActivity().getActionBar().setTitle(R.string.attached_message);
}
@@ -165,6 +167,18 @@ public class EmlMessageViewFragment extends Fragment
mViewController.onActivityCreated(savedInstanceState);
}
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ final int itemId = item.getItemId();
+ if (itemId == R.id.print_message) {
+ mViewController.printMessage();
+ } else {
+ return super.onOptionsItemSelected(item);
+ }
+
+ return true;
+ }
+
// Start SecureConversationViewControllerCallbacks
@Override
diff --git a/src/com/android/mail/browse/EmlViewerActivity.java b/src/com/android/mail/browse/EmlViewerActivity.java
index cc631c634..f40b3ef23 100644
--- a/src/com/android/mail/browse/EmlViewerActivity.java
+++ b/src/com/android/mail/browse/EmlViewerActivity.java
@@ -134,7 +134,6 @@ public class EmlViewerActivity extends Activity implements FeedbackEnabledActivi
final int itemId = item.getItemId();
if (itemId == android.R.id.home) {
finish();
- return true;
} else if (itemId == R.id.settings) {
Utils.showSettings(this, mAccount);
} else if (itemId == R.id.help_info_menu_item) {
diff --git a/src/com/android/mail/browse/MessageHeaderView.java b/src/com/android/mail/browse/MessageHeaderView.java
index 677be9db2..ce24bf592 100644
--- a/src/com/android/mail/browse/MessageHeaderView.java
+++ b/src/com/android/mail/browse/MessageHeaderView.java
@@ -55,12 +55,14 @@ import com.android.mail.compose.ComposeActivity;
import com.android.mail.perf.Timer;
import com.android.mail.photomanager.LetterTileProvider;
import com.android.mail.preferences.AccountPreferences;
+import com.android.mail.print.PrintUtils;
import com.android.mail.providers.Account;
import com.android.mail.providers.Address;
import com.android.mail.providers.Conversation;
import com.android.mail.providers.Folder;
import com.android.mail.providers.Message;
import com.android.mail.providers.UIProvider;
+import com.android.mail.ui.AbstractConversationViewFragment;
import com.android.mail.ui.ImageCanvas;
import com.android.mail.utils.LogTag;
import com.android.mail.utils.LogUtils;
@@ -869,14 +871,16 @@ public class MessageHeaderView extends LinearLayout implements OnClickListener,
ComposeActivity.replyAll(getContext(), getAccount(), mMessage);
} else if (id == R.id.forward) {
ComposeActivity.forward(getContext(), getAccount(), mMessage);
+ } else if (id == R.id.print_message) {
+ printMessage();
} else if (id == R.id.report_rendering_problem) {
final String text = getContext().getString(R.string.report_rendering_problem_desc);
ComposeActivity.reportRenderingFeedback(getContext(), getAccount(), mMessage,
- text + "\n\n" + mCallbacks.getMessageTransforms(mMessage));
+ text + "\n\n" + mCallbacks.getMessageTransforms(mMessage));
} else if (id == R.id.report_rendering_improvement) {
final String text = getContext().getString(R.string.report_rendering_improvement_desc);
ComposeActivity.reportRenderingFeedback(getContext(), getAccount(), mMessage,
- text + "\n\n" + mCallbacks.getMessageTransforms(mMessage));
+ text + "\n\n" + mCallbacks.getMessageTransforms(mMessage));
} else if (id == R.id.star) {
final boolean newValue = !v.isSelected();
v.setSelected(newValue);
@@ -917,8 +921,20 @@ public class MessageHeaderView extends LinearLayout implements OnClickListener,
return handled;
}
+ private void printMessage() {
+ // Secure conversation view does not use a conversation view adapter
+ // so it's safe to test for existence as a signal to use javascript or not.
+ final boolean useJavascript = mMessageHeaderItem.getAdapter() != null;
+ final Account account = mAccountController.getAccount();
+ final Conversation conversation = mMessage.getConversation();
+ final String baseUri =
+ AbstractConversationViewFragment.buildBaseUri(account, conversation);
+ PrintUtils.printMessage(getContext(), mMessage, conversation.subject,
+ mAddressCache, conversation.getBaseUri(baseUri), useJavascript);
+ }
+
/**
- * Set to true if the user should not be able to perfrom message actions
+ * Set to true if the user should not be able to perform message actions
* on the message such as reply/reply all/forward/star/etc.
*
* Default is false.
diff --git a/src/com/android/mail/print/HtmlPrintTemplates.java b/src/com/android/mail/print/HtmlPrintTemplates.java
index 27dfba352..cf0399ca9 100644
--- a/src/com/android/mail/print/HtmlPrintTemplates.java
+++ b/src/com/android/mail/print/HtmlPrintTemplates.java
@@ -19,6 +19,7 @@ package com.android.mail.print;
import android.content.Context;
import android.content.res.Resources;
+import android.text.TextUtils;
import com.android.mail.R;
import com.android.mail.ui.AbstractHtmlTemplates;
@@ -51,8 +52,7 @@ public class HtmlPrintTemplates extends AbstractHtmlTemplates {
* until {@link #endPrintConversation()} or {@link #endPrintConversationNoJavascript()}
* is called.
*/
- public void startPrintConversation(String accountName, String accountAddress,
- String subject, int numMessages) {
+ public void startPrintConversation(String subject, int numMessages) {
if (mInProgress) {
throw new IllegalStateException("Should not call startPrintConversation twice");
}
@@ -62,9 +62,11 @@ public class HtmlPrintTemplates extends AbstractHtmlTemplates {
final Resources res = mContext.getResources();
final String numMessageString = res.getQuantityString(
R.plurals.num_messages, numMessages, numMessages);
+
+ final String printedSubject = TextUtils.isEmpty(subject)
+ ? res.getString(R.string.no_subject) : subject;
append(mConversationUpper, mContext.getString(R.string.app_name),
- accountName == null ? "" : accountName,
- accountAddress, subject, numMessageString);
+ printedSubject, numMessageString);
mInProgress = true;
}
diff --git a/src/com/android/mail/print/Printer.java b/src/com/android/mail/print/PrintUtils.java
index 0a3cd49c0..082bc5786 100644
--- a/src/com/android/mail/print/Printer.java
+++ b/src/com/android/mail/print/PrintUtils.java
@@ -19,16 +19,20 @@ package com.android.mail.print;
import android.content.Context;
import android.content.res.Resources;
+import android.print.PrintAttributes;
+import android.print.PrintManager;
import android.text.TextUtils;
+import android.webkit.WebSettings;
+import android.webkit.WebView;
import com.android.mail.FormattedDateBuilder;
import com.android.mail.R;
-import com.android.mail.browse.ConversationMessage;
import com.android.mail.browse.MessageCursor;
-import com.android.mail.providers.Account;
+
import com.android.mail.providers.Address;
import com.android.mail.providers.Attachment;
import com.android.mail.providers.Conversation;
+import com.android.mail.providers.Message;
import com.android.mail.providers.UIProvider;
import com.android.mail.utils.AttachmentUtils;
import com.android.mail.utils.Utils;
@@ -37,17 +41,63 @@ import java.util.List;
import java.util.Map;
/**
- * Static class that provides a {@link #print} function to build a print html document.
+ * Utility class that provides utility functions to print
+ * either a conversation or message.
*/
-public class Printer {
+public class PrintUtils {
private static final String DIV_START = "<div>";
private static final String REPLY_TO_DIV_START = "<div class=\"replyto\">";
private static final String DIV_END = "</div>";
/**
+ * Prints an entire conversation.
+ */
+ public static void printConversation(Context context,
+ MessageCursor cursor, Map<String, Address> addressCache,
+ String baseUri, boolean useJavascript) {
+ final String convHtml = buildConversationHtml(context, cursor,
+ addressCache, useJavascript);
+ printHtml(context, convHtml, baseUri, cursor.getConversation().subject, useJavascript);
+ }
+
+ /**
+ * Prints one message.
+ */
+ public static void printMessage(Context context, Message message, String subject,
+ Map<String, Address> addressCache, String baseUri, boolean useJavascript) {
+ final String msgHtml = buildMessageHtml(context, message,
+ subject, addressCache, useJavascript);
+ printHtml(context, msgHtml, baseUri, subject, useJavascript);
+ }
+
+ /**
+ * Prints the html provided using the framework printing APIs.
+ *
+ * Sets up a webview to perform the printing work.
+ */
+ private static void printHtml(Context context, String html,
+ String baseUri, String subject, boolean useJavascript) {
+ final WebView webView = new WebView(context);
+ final WebSettings settings = webView.getSettings();
+ settings.setBlockNetworkImage(false);
+ settings.setJavaScriptEnabled(useJavascript);
+ webView.loadDataWithBaseURL(baseUri, html,
+ "text/html", "utf-8", null);
+ final PrintManager printManager =
+ (PrintManager) context.getSystemService(Context.PRINT_SERVICE);
+
+ final String printJobName = TextUtils.isEmpty(subject)
+ ? context.getString(R.string.app_name)
+ : context.getString(R.string.print_job_name, subject);
+ printManager.print(printJobName,
+ webView.createPrintDocumentAdapter(),
+ new PrintAttributes.Builder().build());
+ }
+
+ /**
* Builds an html document that is suitable for printing and returns it as a {@link String}.
*/
- public static String print(Context context, Account account,
+ private static String buildConversationHtml(Context context,
MessageCursor cursor, Map<String, Address> addressCache, boolean useJavascript) {
final HtmlPrintTemplates templates = new HtmlPrintTemplates(context);
final FormattedDateBuilder dateBuilder = new FormattedDateBuilder(context);
@@ -56,25 +106,34 @@ public class Printer {
throw new IllegalStateException("trying to print without a conversation");
}
- // TODO - remove account name(not account.name which is email address) or get it somehow
final Conversation conversation = cursor.getConversation();
- templates.startPrintConversation("", account.name,
- conversation.subject, conversation.getNumMessages());
+ templates.startPrintConversation(conversation.subject, conversation.getNumMessages());
// for each message in the conversation, add message html
final Resources res = context.getResources();
do {
- final ConversationMessage message = cursor.getMessage();
- final Address fromAddress = Utils.getAddress(addressCache, message.getFrom());
- final long when = message.dateReceivedMs;
- final String date = res.getString(R.string.date_message_received_print,
- dateBuilder.formatLongDayAndDate(when), dateBuilder.formatLongTime(when));
+ final Message message = cursor.getMessage();
+ appendSingleMessageHtml(context, res, message, addressCache, templates, dateBuilder);
+ } while (cursor.moveToNext());
+
+ // only include JavaScript if specifically requested
+ return useJavascript ?
+ templates.endPrintConversation() : templates.endPrintConversationNoJavascript();
+ }
+ /**
+ * Builds an html document suitable for printing and returns it as a {@link String}.
+ */
+ private static String buildMessageHtml(Context context, Message message,
+ String subject, Map<String, Address> addressCache, boolean useJavascript) {
+ final HtmlPrintTemplates templates = new HtmlPrintTemplates(context);
+ final FormattedDateBuilder dateBuilder = new FormattedDateBuilder(context);
- templates.appendMessage(fromAddress.getName(), fromAddress.getAddress(), date,
- renderRecipients(res, addressCache, message), message.getBodyAsHtml(),
- renderAttachments(context, res, message));
- } while (cursor.moveToNext());
+ templates.startPrintConversation(subject, 1 /* numMessages */);
+
+ // add message html
+ final Resources res = context.getResources();
+ appendSingleMessageHtml(context, res, message, addressCache, templates, dateBuilder);
// only include JavaScript if specifically requested
return useJavascript ?
@@ -82,11 +141,29 @@ public class Printer {
}
/**
+ * Adds the html for a single message to the
+ * {@link HtmlPrintTemplates} provided.
+ */
+ private static void appendSingleMessageHtml(Context context, Resources res,
+ Message message, Map<String, Address> addressCache,
+ HtmlPrintTemplates templates, FormattedDateBuilder dateBuilder) {
+ final Address fromAddress = Utils.getAddress(addressCache, message.getFrom());
+ final long when = message.dateReceivedMs;
+ final String date = res.getString(R.string.date_message_received_print,
+ dateBuilder.formatLongDayAndDate(when), dateBuilder.formatLongTime(when));
+
+
+ templates.appendMessage(fromAddress.getName(), fromAddress.getAddress(), date,
+ renderRecipients(res, addressCache, message), message.getBodyAsHtml(),
+ renderAttachments(context, res, message));
+ }
+
+ /**
* Builds html for the message header. Specifically, the (optional) lists of
* reply-to, to, cc, and bcc.
*/
- private static String renderRecipients(Resources res, Map<String, Address> addressCache,
- ConversationMessage message) {
+ private static String renderRecipients(Resources res,
+ Map<String, Address> addressCache, Message message) {
final StringBuilder recipients = new StringBuilder();
// reply-to
@@ -163,7 +240,7 @@ public class Printer {
* Builds and returns html for a message's attachments.
*/
private static String renderAttachments(
- Context context, Resources resources, ConversationMessage message) {
+ Context context, Resources resources, Message message) {
if (!message.hasAttachments) {
return "";
}
@@ -186,7 +263,6 @@ public class Printer {
sb.append("<tr><td><table cellspacing=\"0\" cellpadding=\"0\"><tr>");
// TODO - thumbnail previews of images
-
sb.append("<td><img width=\"16\" height=\"16\" src=\"file:///android_asset/images/")
.append(getIconFilename(attachment.getContentType()))
.append("\"></td><td width=\"7\"></td><td><b>")
diff --git a/src/com/android/mail/ui/AbstractConversationViewFragment.java b/src/com/android/mail/ui/AbstractConversationViewFragment.java
index fc5218fc1..3e481906f 100644
--- a/src/com/android/mail/ui/AbstractConversationViewFragment.java
+++ b/src/com/android/mail/ui/AbstractConversationViewFragment.java
@@ -221,9 +221,13 @@ public abstract class AbstractConversationViewFragment extends Fragment implemen
* (such as one that does not rely on account and/or conversation.
*/
protected void setBaseUri() {
+ mBaseUri = buildBaseUri(mAccount, mConversation);
+ }
+
+ public static String buildBaseUri(Account account, Conversation conversation) {
// Since the uri specified in the conversation base uri may not be unique, we specify a
// base uri that us guaranteed to be unique for this conversation.
- mBaseUri = "x-thread://" + mAccount.getEmailAddress().hashCode() + "/" + mConversation.id;
+ return "x-thread://" + account.getEmailAddress().hashCode() + "/" + conversation.id;
}
@Override
diff --git a/src/com/android/mail/ui/ConversationViewFragment.java b/src/com/android/mail/ui/ConversationViewFragment.java
index 63ade3979..e42b6e602 100644
--- a/src/com/android/mail/ui/ConversationViewFragment.java
+++ b/src/com/android/mail/ui/ConversationViewFragment.java
@@ -27,9 +27,6 @@ import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.SystemClock;
-import android.print.PrintAttributes;
-import android.print.PrintJob;
-import android.print.PrintManager;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.ScaleGestureDetector;
@@ -67,7 +64,7 @@ import com.android.mail.browse.SuperCollapsedBlock;
import com.android.mail.browse.WebViewContextMenu;
import com.android.mail.content.ObjectCursor;
import com.android.mail.preferences.AccountPreferences;
-import com.android.mail.print.Printer;
+import com.android.mail.print.PrintUtils;
import com.android.mail.providers.Account;
import com.android.mail.providers.Address;
import com.android.mail.providers.Conversation;
@@ -1580,17 +1577,7 @@ public class ConversationViewFragment extends AbstractConversationViewFragment i
}
protected void printConversation() {
- // TODO - offscreen webview stuff so that we don't clobber
- final String convHtml =
- Printer.print(getContext(), mAccount, getMessageCursor(),
- mAddressCache, true /* userJavascript */);
- mWebView.getSettings().setBlockNetworkImage(false);
- mWebView.loadDataWithBaseURL(
- mConversation.getBaseUri(mBaseUri), convHtml, "text/html", "utf-8", null);
- final PrintManager printManager =
- (PrintManager) getContext().getSystemService(Context.PRINT_SERVICE);
- printManager.print(mConversation.subject,
- mWebView.createPrintDocumentAdapter(),
- new PrintAttributes.Builder().build());
+ PrintUtils.printConversation(getContext(), getMessageCursor(), mAddressCache,
+ mConversation.getBaseUri(mBaseUri), true /* useJavascript */);
}
}
diff --git a/src/com/android/mail/ui/SecureConversationViewController.java b/src/com/android/mail/ui/SecureConversationViewController.java
index 19a57e362..c65ea5a2f 100644
--- a/src/com/android/mail/ui/SecureConversationViewController.java
+++ b/src/com/android/mail/ui/SecureConversationViewController.java
@@ -37,6 +37,8 @@ import com.android.mail.browse.MessageFooterView;
import com.android.mail.browse.MessageHeaderView;
import com.android.mail.browse.MessageScrollView;
import com.android.mail.browse.MessageWebView;
+import com.android.mail.print.PrintUtils;
+import com.android.mail.providers.Conversation;
import com.android.mail.providers.Message;
import com.android.mail.utils.ConversationViewUtils;
@@ -185,8 +187,12 @@ public class SecureConversationViewController implements
mConversationHeaderView.setSubject(subject);
}
- public void printConversation() {
- // TODO - implement this
+ public void printMessage() {
+ final Conversation conversation = mMessage.getConversation();
+ PrintUtils.printMessage(mCallbacks.getContext(), mMessage,
+ conversation != null ? conversation.subject : mMessage.subject,
+ mCallbacks.getAddressCache(), mCallbacks.getBaseUri(), false /* useJavascript */);
+
}
// Start MessageHeaderViewCallbacks implementations
diff --git a/src/com/android/mail/ui/SecureConversationViewFragment.java b/src/com/android/mail/ui/SecureConversationViewFragment.java
index 9ee32e46c..051940c47 100644
--- a/src/com/android/mail/ui/SecureConversationViewFragment.java
+++ b/src/com/android/mail/ui/SecureConversationViewFragment.java
@@ -267,6 +267,6 @@ public class SecureConversationViewFragment extends AbstractConversationViewFrag
}
protected void printConversation() {
- mViewController.printConversation();
+ mViewController.printMessage();
}
}