am 8d5004a6
: Modernize the code to load message and body from DB.
Merge commit '8d5004a6eb28844c9d86a5e97a947043b693eee6' into eclair-plus-aosp * commit '8d5004a6eb28844c9d86a5e97a947043b693eee6': Modernize the code to load message and body from DB.
This commit is contained in:
commit
4de3f97290
@ -111,6 +111,9 @@
|
|||||||
<string name="status_loading_more_failed">Retry loading more messages</string>
|
<string name="status_loading_more_failed">Retry loading more messages</string>
|
||||||
<!-- Notification title in status bar -->
|
<!-- Notification title in status bar -->
|
||||||
<string name="notification_new_title">New email</string>
|
<string name="notification_new_title">New email</string>
|
||||||
|
<!-- Dialog text when we are unable to load the message for display -->
|
||||||
|
<string name="error_loading_message_body">Unexpected error while loading message text. Message
|
||||||
|
may be too large to view.</string>
|
||||||
|
|
||||||
<!-- Notification message in notifications window when one account has
|
<!-- Notification message in notifications window when one account has
|
||||||
one or more new messages; e.g, "279 unread (someone@google.com)". -->
|
one or more new messages; e.g, "279 unread (someone@google.com)". -->
|
||||||
|
@ -43,7 +43,6 @@ import android.database.ContentObserver;
|
|||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.BitmapFactory;
|
import android.graphics.BitmapFactory;
|
||||||
import android.graphics.Rect;
|
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.media.MediaScannerConnection;
|
import android.media.MediaScannerConnection;
|
||||||
import android.media.MediaScannerConnection.MediaScannerConnectionClient;
|
import android.media.MediaScannerConnection.MediaScannerConnectionClient;
|
||||||
@ -58,6 +57,7 @@ import android.provider.ContactsContract.FastTrack;
|
|||||||
import android.provider.ContactsContract.Presence;
|
import android.provider.ContactsContract.Presence;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.text.util.Regex;
|
import android.text.util.Regex;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
@ -160,6 +160,7 @@ public class MessageView extends Activity implements OnClickListener {
|
|||||||
private static final int MSG_ATTACHMENT_PROGRESS = 2;
|
private static final int MSG_ATTACHMENT_PROGRESS = 2;
|
||||||
private static final int MSG_LOAD_CONTENT_URI = 3;
|
private static final int MSG_LOAD_CONTENT_URI = 3;
|
||||||
private static final int MSG_SET_ATTACHMENTS_ENABLED = 4;
|
private static final int MSG_SET_ATTACHMENTS_ENABLED = 4;
|
||||||
|
private static final int MSG_LOAD_BODY_ERROR = 5;
|
||||||
private static final int MSG_NETWORK_ERROR = 6;
|
private static final int MSG_NETWORK_ERROR = 6;
|
||||||
private static final int MSG_FETCHING_ATTACHMENT = 10;
|
private static final int MSG_FETCHING_ATTACHMENT = 10;
|
||||||
private static final int MSG_VIEW_ATTACHMENT_ERROR = 12;
|
private static final int MSG_VIEW_ATTACHMENT_ERROR = 12;
|
||||||
@ -196,6 +197,10 @@ public class MessageView extends Activity implements OnClickListener {
|
|||||||
attachment.downloadButton.setEnabled(msg.arg1 == 1);
|
attachment.downloadButton.setEnabled(msg.arg1 == 1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case MSG_LOAD_BODY_ERROR:
|
||||||
|
Toast.makeText(MessageView.this,
|
||||||
|
R.string.error_loading_message_body, Toast.LENGTH_LONG).show();
|
||||||
|
break;
|
||||||
case MSG_NETWORK_ERROR:
|
case MSG_NETWORK_ERROR:
|
||||||
Toast.makeText(MessageView.this,
|
Toast.makeText(MessageView.this,
|
||||||
R.string.status_network_error, Toast.LENGTH_LONG).show();
|
R.string.status_network_error, Toast.LENGTH_LONG).show();
|
||||||
@ -247,6 +252,10 @@ public class MessageView extends Activity implements OnClickListener {
|
|||||||
sendMessage(msg);
|
sendMessage(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void loadBodyError() {
|
||||||
|
sendEmptyMessage(MSG_LOAD_BODY_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
public void networkError() {
|
public void networkError() {
|
||||||
sendEmptyMessage(MSG_NETWORK_ERROR);
|
sendEmptyMessage(MSG_NETWORK_ERROR);
|
||||||
}
|
}
|
||||||
@ -1013,11 +1022,8 @@ public class MessageView extends Activity implements OnClickListener {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Async task for loading a single message outside of the UI thread
|
* Async task for loading a single message outside of the UI thread
|
||||||
*
|
|
||||||
* TODO: start and stop progress indicator
|
|
||||||
* TODO: set up to listen for additional updates (cursor data changes)
|
|
||||||
*/
|
*/
|
||||||
private class LoadMessageTask extends AsyncTask<Void, Void, Cursor> {
|
private class LoadMessageTask extends AsyncTask<Void, Void, Message> {
|
||||||
|
|
||||||
private long mId;
|
private long mId;
|
||||||
private boolean mOkToFetch;
|
private boolean mOkToFetch;
|
||||||
@ -1031,37 +1037,25 @@ public class MessageView extends Activity implements OnClickListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Cursor doInBackground(Void... params) {
|
protected Message doInBackground(Void... params) {
|
||||||
return MessageView.this.managedQuery(
|
return Message.restoreMessageWithId(MessageView.this, mId);
|
||||||
Message.CONTENT_URI,
|
|
||||||
Message.CONTENT_PROJECTION,
|
|
||||||
Message.RECORD_ID + "=?",
|
|
||||||
new String[] {
|
|
||||||
String.valueOf(mId)
|
|
||||||
},
|
|
||||||
null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPostExecute(Cursor cursor) {
|
protected void onPostExecute(Message message) {
|
||||||
if (cursor.isClosed()) {
|
if (message == null) {
|
||||||
|
finish();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (cursor.moveToFirst()) {
|
reloadUiFromMessage(message, mOkToFetch);
|
||||||
reloadUiFromCursor(cursor, mOkToFetch);
|
|
||||||
} else {
|
|
||||||
// toast? why would this fail?
|
|
||||||
}
|
|
||||||
startPresenceCheck();
|
startPresenceCheck();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Async task for loading a single message body outside of the UI thread
|
* Async task for loading a single message body outside of the UI thread
|
||||||
*
|
|
||||||
* TODO: smarter loading of html vs. text
|
|
||||||
*/
|
*/
|
||||||
private class LoadBodyTask extends AsyncTask<Void, Void, Cursor> {
|
private class LoadBodyTask extends AsyncTask<Void, Void, String[]> {
|
||||||
|
|
||||||
private long mId;
|
private long mId;
|
||||||
|
|
||||||
@ -1073,30 +1067,29 @@ public class MessageView extends Activity implements OnClickListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Cursor doInBackground(Void... params) {
|
protected String[] doInBackground(Void... params) {
|
||||||
return MessageView.this.managedQuery(
|
try {
|
||||||
Body.CONTENT_URI,
|
String text = null;
|
||||||
BODY_CONTENT_PROJECTION,
|
String html = Body.restoreBodyHtmlWithMessageId(MessageView.this, mId);
|
||||||
Body.MESSAGE_KEY + "=?",
|
if (html == null) {
|
||||||
new String[] {
|
text = Body.restoreBodyTextWithMessageId(MessageView.this, mId);
|
||||||
String.valueOf(mId)
|
}
|
||||||
},
|
return new String[] { text, html };
|
||||||
null);
|
} catch (RuntimeException re) {
|
||||||
|
// This catches SQLiteException as well as other RTE's we've seen from the
|
||||||
|
// database calls, such as IllegalStateException
|
||||||
|
Log.d(Email.LOG_TAG, "Exception while loading message body: " + re.toString());
|
||||||
|
mHandler.loadBodyError();
|
||||||
|
return new String[] { null, null };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPostExecute(Cursor cursor) {
|
protected void onPostExecute(String[] results) {
|
||||||
if (cursor.isClosed()) {
|
if (results == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (cursor.moveToFirst()) {
|
reloadUiFromBody(results[0], results[1]); // text, html
|
||||||
reloadBodyFromCursor(cursor);
|
|
||||||
} else {
|
|
||||||
// toast? why would this fail?
|
|
||||||
reloadBodyFromCursor(null); // hack to force text for display
|
|
||||||
}
|
|
||||||
|
|
||||||
// At this point it's fair to mark the message as "read"
|
|
||||||
onMarkAsRead(true);
|
onMarkAsRead(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1143,14 +1136,13 @@ public class MessageView extends Activity implements OnClickListener {
|
|||||||
/**
|
/**
|
||||||
* Reload the UI from a provider cursor. This must only be called from the UI thread.
|
* Reload the UI from a provider cursor. This must only be called from the UI thread.
|
||||||
*
|
*
|
||||||
* @param cursor A cursor loaded from EmailStore.Message.
|
* @param message A copy of the message loaded from the database
|
||||||
* @param okToFetch If true, and message is not fully loaded, it's OK to fetch from
|
* @param okToFetch If true, and message is not fully loaded, it's OK to fetch from
|
||||||
* the network. Use false to prevent looping here.
|
* the network. Use false to prevent looping here.
|
||||||
*
|
*
|
||||||
* TODO: trigger presence check
|
* TODO: trigger presence check
|
||||||
*/
|
*/
|
||||||
private void reloadUiFromCursor(Cursor cursor, boolean okToFetch) {
|
private void reloadUiFromMessage(Message message, boolean okToFetch) {
|
||||||
Message message = new Message().restore(cursor);
|
|
||||||
mMessage = message;
|
mMessage = message;
|
||||||
mAccountId = message.mAccountKey;
|
mAccountId = message.mAccountKey;
|
||||||
if (mMailboxId == -1) {
|
if (mMailboxId == -1) {
|
||||||
@ -1193,40 +1185,26 @@ public class MessageView extends Activity implements OnClickListener {
|
|||||||
/**
|
/**
|
||||||
* Reload the body from the provider cursor. This must only be called from the UI thread.
|
* Reload the body from the provider cursor. This must only be called from the UI thread.
|
||||||
*
|
*
|
||||||
* @param cursor
|
* @param bodyText text part
|
||||||
|
* @param bodyHtml html part
|
||||||
*
|
*
|
||||||
* TODO deal with html vs text and many other issues
|
* TODO deal with html vs text and many other issues
|
||||||
*/
|
*/
|
||||||
private void reloadBodyFromCursor(Cursor cursor) {
|
private void reloadUiFromBody(String bodyText, String bodyHtml) {
|
||||||
|
String text = null;
|
||||||
mHtmlText = null;
|
mHtmlText = null;
|
||||||
boolean hasImages = false;
|
boolean hasImages = false;
|
||||||
|
|
||||||
// TODO Remove this hack that forces some text to test the code
|
if (bodyHtml == null) {
|
||||||
String html = null;
|
text = bodyText;
|
||||||
String text = null;
|
|
||||||
if (cursor != null) {
|
|
||||||
// First try HTML; we'll show that if it exists...
|
|
||||||
html = cursor.getString(BODY_CONTENT_COLUMN_HTML_CONTENT);
|
|
||||||
if (html == null) {
|
|
||||||
text = cursor.getString(BODY_CONTENT_COLUMN_TEXT_CONTENT);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (html == null) {
|
|
||||||
// This code is stolen from Listener.loadMessageForViewBodyAvailable
|
|
||||||
// And also escape special character, such as "<>&",
|
|
||||||
// to HTML escape sequence.
|
|
||||||
if (text == null) {
|
|
||||||
text = "";
|
|
||||||
}
|
|
||||||
text = EmailHtmlUtil.escapeCharacterToDisplay(text);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Linkify the plain text and convert it to HTML by replacing
|
* Convert the plain text to HTML
|
||||||
* \r?\n with <br> and adding a html/body wrapper.
|
|
||||||
*/
|
*/
|
||||||
StringBuffer sb = new StringBuffer("<html><body>");
|
StringBuffer sb = new StringBuffer("<html><body>");
|
||||||
if (text != null) {
|
if (text != null) {
|
||||||
|
// Escape any inadvertent HTML in the text message
|
||||||
|
text = EmailHtmlUtil.escapeCharacterToDisplay(text);
|
||||||
|
// Find any embedded URL's and linkify
|
||||||
Matcher m = Regex.WEB_URL_PATTERN.matcher(text);
|
Matcher m = Regex.WEB_URL_PATTERN.matcher(text);
|
||||||
while (m.find()) {
|
while (m.find()) {
|
||||||
int start = m.start();
|
int start = m.start();
|
||||||
@ -1260,8 +1238,8 @@ public class MessageView extends Activity implements OnClickListener {
|
|||||||
sb.append("</body></html>");
|
sb.append("</body></html>");
|
||||||
text = sb.toString();
|
text = sb.toString();
|
||||||
} else {
|
} else {
|
||||||
text = html;
|
text = bodyHtml;
|
||||||
mHtmlText = html;
|
mHtmlText = bodyHtml;
|
||||||
hasImages = IMG_TAG_START_REGEX.matcher(text).find();
|
hasImages = IMG_TAG_START_REGEX.matcher(text).find();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user