Message.java revision bec5115726f24733a0a1577caaf05fb6e9ef9c6f
1/** 2 * Copyright (c) 2012, Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.mail.providers; 18 19import android.content.AsyncQueryHandler; 20import android.content.ContentValues; 21import android.database.Cursor; 22import android.net.Uri; 23import android.os.Parcel; 24import android.os.Parcelable; 25import android.text.TextUtils; 26 27import com.android.mail.browse.ConversationCursor; 28import com.android.mail.providers.UIProvider.ConversationColumns; 29import com.android.mail.providers.UIProvider.MessageColumns; 30import com.android.mail.ui.ConversationViewFragment.MessageCursor; 31import com.android.mail.utils.Utils; 32 33 34public class Message implements Parcelable { 35 public long id; 36 public long serverId; 37 public Uri uri; 38 public String conversationUri; 39 public String subject; 40 public String snippet; 41 public String from; 42 public String to; 43 public String cc; 44 public String bcc; 45 public String replyTo; 46 public long dateReceivedMs; 47 public String bodyHtml; 48 public String bodyText; 49 public boolean embedsExternalResources; 50 public String refMessageId; 51 public int draftType; 52 public boolean appendRefMessageContent; 53 public boolean hasAttachments; 54 public Uri attachmentListUri; 55 public long messageFlags; 56 public String joinedAttachmentInfos; 57 public String saveUri; 58 public String sendUri; 59 public boolean alwaysShowImages; 60 public boolean read; 61 public boolean starred; 62 public int quotedTextOffset; 63 64 private String[] mToAddresses = null; 65 private String[] mCcAddresses = null; 66 private String[] mBccAddresses = null; 67 private String[] mReplyToAddresses = null; 68 69 // While viewing a list of messages, points to the MessageCursor that contains it 70 private transient MessageCursor mMessageCursor = null; 71 72 @Override 73 public int describeContents() { 74 return 0; 75 } 76 77 @Override 78 public boolean equals(Object o) { 79 if (o == null || !(o instanceof Message)) { 80 return false; 81 } 82 final Uri otherUri = ((Message) o).uri; 83 if (uri == null) { 84 return (otherUri == null); 85 } 86 return uri.equals(otherUri); 87 } 88 89 @Override 90 public int hashCode() { 91 return uri == null ? 0 : uri.hashCode(); 92 } 93 94 @Override 95 public void writeToParcel(Parcel dest, int flags) { 96 dest.writeLong(id); 97 dest.writeLong(serverId); 98 dest.writeParcelable(uri, 0); 99 dest.writeString(conversationUri); 100 dest.writeString(subject); 101 dest.writeString(snippet); 102 dest.writeString(from); 103 dest.writeString(to); 104 dest.writeString(cc); 105 dest.writeString(bcc); 106 dest.writeString(replyTo); 107 dest.writeLong(dateReceivedMs); 108 dest.writeString(bodyHtml); 109 dest.writeString(bodyText); 110 dest.writeInt(embedsExternalResources ? 1 : 0); 111 dest.writeString(refMessageId); 112 dest.writeInt(draftType); 113 dest.writeInt(appendRefMessageContent ? 1 : 0); 114 dest.writeInt(hasAttachments ? 1 : 0); 115 dest.writeParcelable(attachmentListUri, 0); 116 dest.writeLong(messageFlags); 117 dest.writeString(joinedAttachmentInfos); 118 dest.writeString(saveUri); 119 dest.writeString(sendUri); 120 dest.writeInt(alwaysShowImages ? 1 : 0); 121 dest.writeInt(quotedTextOffset); 122 } 123 124 private Message(Parcel in) { 125 id = in.readLong(); 126 serverId = in.readLong(); 127 uri = in.readParcelable(null); 128 conversationUri = in.readString(); 129 subject = in.readString(); 130 snippet = in.readString(); 131 from = in.readString(); 132 to = in.readString(); 133 cc = in.readString(); 134 bcc = in.readString(); 135 replyTo = in.readString(); 136 dateReceivedMs = in.readLong(); 137 bodyHtml = in.readString(); 138 bodyText = in.readString(); 139 embedsExternalResources = in.readInt() != 0; 140 refMessageId = in.readString(); 141 draftType = in.readInt(); 142 appendRefMessageContent = in.readInt() != 0; 143 hasAttachments = in.readInt() != 0; 144 attachmentListUri = in.readParcelable(null); 145 messageFlags = in.readLong(); 146 joinedAttachmentInfos = in.readString(); 147 saveUri = in.readString(); 148 sendUri = in.readString(); 149 alwaysShowImages = in.readInt() != 0; 150 quotedTextOffset = in.readInt(); 151 } 152 153 public Message() { 154 155 } 156 157 @Override 158 public String toString() { 159 return "[message id=" + id + "]"; 160 } 161 162 public static final Creator<Message> CREATOR = new Creator<Message>() { 163 164 @Override 165 public Message createFromParcel(Parcel source) { 166 return new Message(source); 167 } 168 169 @Override 170 public Message[] newArray(int size) { 171 return new Message[size]; 172 } 173 174 }; 175 176 public Message(MessageCursor cursor) { 177 this((Cursor)cursor); 178 // Only set message cursor if appropriate 179 mMessageCursor = cursor; 180 } 181 182 public Message(Cursor cursor) { 183 if (cursor != null) { 184 id = cursor.getLong(UIProvider.MESSAGE_ID_COLUMN); 185 serverId = cursor.getLong(UIProvider.MESSAGE_SERVER_ID_COLUMN); 186 String message = cursor.getString(UIProvider.MESSAGE_URI_COLUMN); 187 uri = !TextUtils.isEmpty(message) ? Uri.parse(message) : null; 188 conversationUri = cursor.getString(UIProvider.MESSAGE_CONVERSATION_URI_COLUMN); 189 subject = cursor.getString(UIProvider.MESSAGE_SUBJECT_COLUMN); 190 snippet = cursor.getString(UIProvider.MESSAGE_SNIPPET_COLUMN); 191 from = cursor.getString(UIProvider.MESSAGE_FROM_COLUMN); 192 to = cursor.getString(UIProvider.MESSAGE_TO_COLUMN); 193 cc = cursor.getString(UIProvider.MESSAGE_CC_COLUMN); 194 bcc = cursor.getString(UIProvider.MESSAGE_BCC_COLUMN); 195 replyTo = cursor.getString(UIProvider.MESSAGE_REPLY_TO_COLUMN); 196 dateReceivedMs = cursor.getLong(UIProvider.MESSAGE_DATE_RECEIVED_MS_COLUMN); 197 bodyHtml = cursor.getString(UIProvider.MESSAGE_BODY_HTML_COLUMN); 198 bodyText = cursor.getString(UIProvider.MESSAGE_BODY_TEXT_COLUMN); 199 embedsExternalResources = cursor 200 .getInt(UIProvider.MESSAGE_EMBEDS_EXTERNAL_RESOURCES_COLUMN) != 0; 201 refMessageId = cursor.getString(UIProvider.MESSAGE_REF_MESSAGE_ID_COLUMN); 202 draftType = cursor.getInt(UIProvider.MESSAGE_DRAFT_TYPE_COLUMN); 203 appendRefMessageContent = cursor 204 .getInt(UIProvider.MESSAGE_APPEND_REF_MESSAGE_CONTENT_COLUMN) != 0; 205 hasAttachments = cursor.getInt(UIProvider.MESSAGE_HAS_ATTACHMENTS_COLUMN) != 0; 206 final String attachmentsUri = cursor 207 .getString(UIProvider.MESSAGE_ATTACHMENT_LIST_URI_COLUMN); 208 attachmentListUri = hasAttachments && !TextUtils.isEmpty(attachmentsUri) ? Uri 209 .parse(attachmentsUri) : null; 210 messageFlags = cursor.getLong(UIProvider.MESSAGE_FLAGS_COLUMN); 211 joinedAttachmentInfos = cursor 212 .getString(UIProvider.MESSAGE_JOINED_ATTACHMENT_INFOS_COLUMN); 213 saveUri = cursor 214 .getString(UIProvider.MESSAGE_SAVE_URI_COLUMN); 215 sendUri = cursor 216 .getString(UIProvider.MESSAGE_SEND_URI_COLUMN); 217 alwaysShowImages = cursor.getInt(UIProvider.MESSAGE_ALWAYS_SHOW_IMAGES_COLUMN) != 0; 218 read = cursor.getInt(UIProvider.MESSAGE_READ_COLUMN) != 0; 219 starred = cursor.getInt(UIProvider.MESSAGE_STARRED_COLUMN) != 0; 220 quotedTextOffset = cursor.getInt(UIProvider.QUOTED_TEXT_OFFSET_COLUMN); 221 } 222 } 223 224 public synchronized String[] getToAddresses() { 225 if (mToAddresses == null) { 226 mToAddresses = Utils.splitCommaSeparatedString(to); 227 } 228 return mToAddresses; 229 } 230 231 public synchronized String[] getCcAddresses() { 232 if (mCcAddresses == null) { 233 mCcAddresses = Utils.splitCommaSeparatedString(cc); 234 } 235 return mCcAddresses; 236 } 237 238 public synchronized String[] getBccAddresses() { 239 if (mBccAddresses == null) { 240 mBccAddresses = Utils.splitCommaSeparatedString(bcc); 241 } 242 return mBccAddresses; 243 } 244 245 public synchronized String[] getReplyToAddresses() { 246 if (mReplyToAddresses == null) { 247 mReplyToAddresses = Utils.splitCommaSeparatedString(replyTo); 248 } 249 return mReplyToAddresses; 250 } 251 252 /** 253 * Returns whether a "Show Pictures" button should initially appear for this message. If the 254 * button is shown, the message must also block all non-local images in the body. Inversely, if 255 * the button is not shown, the message must show all images within (or else the user would be 256 * stuck with no images and no way to reveal them). 257 * 258 * @return true if a "Show Pictures" button should appear. 259 */ 260 public boolean shouldShowImagePrompt() { 261 return embedsExternalResources && !alwaysShowImages; 262 } 263 264 /** 265 * Helper method to command a provider to mark all messages from this sender with the 266 * {@link MessageColumns#ALWAYS_SHOW_IMAGES} flag set. 267 * 268 * @param handler a caller-provided handler to run the query on 269 * @param token (optional) token to identify the command to the handler 270 * @param cookie (optional) cookie to pass to the handler 271 */ 272 public void markAlwaysShowImages(AsyncQueryHandler handler, int token, Object cookie) { 273 final ContentValues values = new ContentValues(1); 274 values.put(UIProvider.MessageColumns.ALWAYS_SHOW_IMAGES, 1); 275 276 handler.startUpdate(token, cookie, uri, values, null, null); 277 } 278 279 /** 280 * Helper method to command a provider to star/unstar this message. 281 * 282 * @param starred whether to star or unstar the message 283 * @param handler a caller-provided handler to run the query on 284 * @param token (optional) token to identify the command to the handler 285 * @param cookie (optional) cookie to pass to the handler 286 */ 287 public void star(boolean starred, AsyncQueryHandler handler, int token, Object cookie) { 288 this.starred = starred; 289 boolean conversationStarred = starred; 290 // If we're unstarring, we need to find out if the conversation is still starred 291 if (mMessageCursor != null && !starred) { 292 conversationStarred = mMessageCursor.isConversationStarred(); 293 } 294 // Update the conversation cursor so that changes are reflected simultaneously 295 ConversationCursor.setConversationColumn(conversationUri, ConversationColumns.STARRED, 296 conversationStarred); 297 final ContentValues values = new ContentValues(1); 298 values.put(UIProvider.MessageColumns.STARRED, starred ? 1 : 0); 299 300 handler.startUpdate(token, cookie, uri, values, null, null); 301 } 302 303} 304