Message.java revision 47aa9c991b33c722a6ba1946fc02e0aba17bc1c9
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.provider.BaseColumns; 26import android.text.TextUtils; 27 28import com.android.mail.providers.UIProvider.MessageColumns; 29import com.android.mail.utils.Utils; 30 31import java.util.Collections; 32import java.util.List; 33 34 35public class Message implements Parcelable { 36 /** 37 * @see BaseColumns#_ID 38 */ 39 public long id; 40 /** 41 * @see UIProvider.MessageColumns#SERVER_ID 42 */ 43 public long serverId; 44 /** 45 * @see UIProvider.MessageColumns#URI 46 */ 47 public Uri uri; 48 /** 49 * @see UIProvider.MessageColumns#CONVERSATION_ID 50 */ 51 public Uri conversationUri; 52 /** 53 * @see UIProvider.MessageColumns#SUBJECT 54 */ 55 public String subject; 56 /** 57 * @see UIProvider.MessageColumns#SNIPPET 58 */ 59 public String snippet; 60 /** 61 * @see UIProvider.MessageColumns#FROM 62 */ 63 public String from; 64 /** 65 * @see UIProvider.MessageColumns#TO 66 */ 67 public String to; 68 /** 69 * @see UIProvider.MessageColumns#CC 70 */ 71 public String cc; 72 /** 73 * @see UIProvider.MessageColumns#BCC 74 */ 75 public String bcc; 76 /** 77 * @see UIProvider.MessageColumns#REPLY_TO 78 */ 79 public String replyTo; 80 /** 81 * @see UIProvider.MessageColumns#DATE_RECEIVED_MS 82 */ 83 public long dateReceivedMs; 84 /** 85 * @see UIProvider.MessageColumns#BODY_HTML 86 */ 87 public String bodyHtml; 88 /** 89 * @see UIProvider.MessageColumns#BODY_TEXT 90 */ 91 public String bodyText; 92 /** 93 * @see UIProvider.MessageColumns#EMBEDS_EXTERNAL_RESOURCES 94 */ 95 public boolean embedsExternalResources; 96 /** 97 * @see UIProvider.MessageColumns#REF_MESSAGE_ID 98 */ 99 public String refMessageId; 100 /** 101 * @see UIProvider.MessageColumns#DRAFT_TYPE 102 */ 103 public int draftType; 104 /** 105 * @see UIProvider.MessageColumns#APPEND_REF_MESSAGE_CONTENT 106 */ 107 public boolean appendRefMessageContent; 108 /** 109 * @see UIProvider.MessageColumns#HAS_ATTACHMENTS 110 */ 111 public boolean hasAttachments; 112 /** 113 * @see UIProvider.MessageColumns#ATTACHMENT_LIST_URI 114 */ 115 public Uri attachmentListUri; 116 /** 117 * @see UIProvider.MessageColumns#MESSAGE_FLAGS 118 */ 119 public long messageFlags; 120 /** 121 * @see UIProvider.MessageColumns#SAVE_MESSAGE_URI 122 */ 123 public String saveUri; 124 /** 125 * @see UIProvider.MessageColumns#SEND_MESSAGE_URI 126 */ 127 public String sendUri; 128 /** 129 * @see UIProvider.MessageColumns#ALWAYS_SHOW_IMAGES 130 */ 131 public boolean alwaysShowImages; 132 /** 133 * @see UIProvider.MessageColumns#READ 134 */ 135 public boolean read; 136 /** 137 * @see UIProvider.MessageColumns#STARRED 138 */ 139 public boolean starred; 140 /** 141 * @see UIProvider.MessageColumns#QUOTE_START_POS 142 */ 143 public int quotedTextOffset; 144 /** 145 * @see UIProvider.MessageColumns#ATTACHMENTS 146 */ 147 public String attachmentsJson; 148 /** 149 * @see UIProvider.MessageColumns#MESSAGE_ACCOUNT_URI 150 */ 151 public Uri accountUri; 152 /** 153 * @see UIProvider.MessageColumns#EVENT_INTENT_URI 154 */ 155 public Uri eventIntentUri; 156 /** 157 * @see UIProvider.MessageColumns#SPAM_WARNING_STRING 158 */ 159 public String spamWarningString; 160 /** 161 * @see UIProvider.MessageColumns#SPAM_WARNING_LEVEL 162 */ 163 public int spamWarningLevel; 164 /** 165 * @see UIProvider.MessageColumns#SPAM_WARNING_LINK_TYPE 166 */ 167 public int spamLinkType; 168 /** 169 * @see UIProvider.MessageColumns#VIA_DOMAIN 170 */ 171 public String viaDomain; 172 /** 173 * @see UIProvider.MessageColumns#IS_SENDING 174 */ 175 public boolean isSending; 176 177 private transient String[] mFromAddresses = null; 178 private transient String[] mToAddresses = null; 179 private transient String[] mCcAddresses = null; 180 private transient String[] mBccAddresses = null; 181 private transient String[] mReplyToAddresses = null; 182 183 private transient List<Attachment> mAttachments = null; 184 185 @Override 186 public int describeContents() { 187 return 0; 188 } 189 190 @Override 191 public boolean equals(Object o) { 192 if (o == null || !(o instanceof Message)) { 193 return false; 194 } 195 final Uri otherUri = ((Message) o).uri; 196 if (uri == null) { 197 return (otherUri == null); 198 } 199 return uri.equals(otherUri); 200 } 201 202 @Override 203 public int hashCode() { 204 return uri == null ? 0 : uri.hashCode(); 205 } 206 207 @Override 208 public void writeToParcel(Parcel dest, int flags) { 209 dest.writeLong(id); 210 dest.writeLong(serverId); 211 dest.writeParcelable(uri, 0); 212 dest.writeParcelable(conversationUri, 0); 213 dest.writeString(subject); 214 dest.writeString(snippet); 215 dest.writeString(from); 216 dest.writeString(to); 217 dest.writeString(cc); 218 dest.writeString(bcc); 219 dest.writeString(replyTo); 220 dest.writeLong(dateReceivedMs); 221 dest.writeString(bodyHtml); 222 dest.writeString(bodyText); 223 dest.writeInt(embedsExternalResources ? 1 : 0); 224 dest.writeString(refMessageId); 225 dest.writeInt(draftType); 226 dest.writeInt(appendRefMessageContent ? 1 : 0); 227 dest.writeInt(hasAttachments ? 1 : 0); 228 dest.writeParcelable(attachmentListUri, 0); 229 dest.writeLong(messageFlags); 230 dest.writeString(saveUri); 231 dest.writeString(sendUri); 232 dest.writeInt(alwaysShowImages ? 1 : 0); 233 dest.writeInt(quotedTextOffset); 234 dest.writeString(attachmentsJson); 235 dest.writeParcelable(accountUri, 0); 236 dest.writeParcelable(eventIntentUri, 0); 237 dest.writeString(spamWarningString); 238 dest.writeInt(spamWarningLevel); 239 dest.writeInt(spamLinkType); 240 dest.writeString(viaDomain); 241 dest.writeInt(isSending ? 1 : 0); 242 } 243 244 private Message(Parcel in) { 245 id = in.readLong(); 246 serverId = in.readLong(); 247 uri = in.readParcelable(null); 248 conversationUri = in.readParcelable(null); 249 subject = in.readString(); 250 snippet = in.readString(); 251 from = in.readString(); 252 to = in.readString(); 253 cc = in.readString(); 254 bcc = in.readString(); 255 replyTo = in.readString(); 256 dateReceivedMs = in.readLong(); 257 bodyHtml = in.readString(); 258 bodyText = in.readString(); 259 embedsExternalResources = in.readInt() != 0; 260 refMessageId = in.readString(); 261 draftType = in.readInt(); 262 appendRefMessageContent = in.readInt() != 0; 263 hasAttachments = in.readInt() != 0; 264 attachmentListUri = in.readParcelable(null); 265 messageFlags = in.readLong(); 266 saveUri = in.readString(); 267 sendUri = in.readString(); 268 alwaysShowImages = in.readInt() != 0; 269 quotedTextOffset = in.readInt(); 270 attachmentsJson = in.readString(); 271 accountUri = in.readParcelable(null); 272 eventIntentUri = in.readParcelable(null); 273 spamWarningString = in.readString(); 274 spamWarningLevel = in.readInt(); 275 spamLinkType = in.readInt(); 276 viaDomain = in.readString(); 277 isSending = in.readInt() != 0; 278 } 279 280 public Message() { 281 282 } 283 284 @Override 285 public String toString() { 286 return "[message id=" + id + "]"; 287 } 288 289 public static final Creator<Message> CREATOR = new Creator<Message>() { 290 291 @Override 292 public Message createFromParcel(Parcel source) { 293 return new Message(source); 294 } 295 296 @Override 297 public Message[] newArray(int size) { 298 return new Message[size]; 299 } 300 301 }; 302 303 public Message(Cursor cursor) { 304 if (cursor != null) { 305 id = cursor.getLong(UIProvider.MESSAGE_ID_COLUMN); 306 serverId = cursor.getLong(UIProvider.MESSAGE_SERVER_ID_COLUMN); 307 final String messageUriStr = cursor.getString(UIProvider.MESSAGE_URI_COLUMN); 308 uri = !TextUtils.isEmpty(messageUriStr) ? Uri.parse(messageUriStr) : null; 309 final String convUriStr = cursor.getString(UIProvider.MESSAGE_CONVERSATION_URI_COLUMN); 310 conversationUri = !TextUtils.isEmpty(convUriStr) ? Uri.parse(convUriStr) : null; 311 subject = cursor.getString(UIProvider.MESSAGE_SUBJECT_COLUMN); 312 snippet = cursor.getString(UIProvider.MESSAGE_SNIPPET_COLUMN); 313 from = cursor.getString(UIProvider.MESSAGE_FROM_COLUMN); 314 to = cursor.getString(UIProvider.MESSAGE_TO_COLUMN); 315 cc = cursor.getString(UIProvider.MESSAGE_CC_COLUMN); 316 bcc = cursor.getString(UIProvider.MESSAGE_BCC_COLUMN); 317 replyTo = cursor.getString(UIProvider.MESSAGE_REPLY_TO_COLUMN); 318 dateReceivedMs = cursor.getLong(UIProvider.MESSAGE_DATE_RECEIVED_MS_COLUMN); 319 bodyHtml = cursor.getString(UIProvider.MESSAGE_BODY_HTML_COLUMN); 320 bodyText = cursor.getString(UIProvider.MESSAGE_BODY_TEXT_COLUMN); 321 embedsExternalResources = cursor 322 .getInt(UIProvider.MESSAGE_EMBEDS_EXTERNAL_RESOURCES_COLUMN) != 0; 323 refMessageId = cursor.getString(UIProvider.MESSAGE_REF_MESSAGE_ID_COLUMN); 324 draftType = cursor.getInt(UIProvider.MESSAGE_DRAFT_TYPE_COLUMN); 325 appendRefMessageContent = cursor 326 .getInt(UIProvider.MESSAGE_APPEND_REF_MESSAGE_CONTENT_COLUMN) != 0; 327 hasAttachments = cursor.getInt(UIProvider.MESSAGE_HAS_ATTACHMENTS_COLUMN) != 0; 328 final String attachmentsUri = cursor 329 .getString(UIProvider.MESSAGE_ATTACHMENT_LIST_URI_COLUMN); 330 attachmentListUri = hasAttachments && !TextUtils.isEmpty(attachmentsUri) ? Uri 331 .parse(attachmentsUri) : null; 332 messageFlags = cursor.getLong(UIProvider.MESSAGE_FLAGS_COLUMN); 333 saveUri = cursor 334 .getString(UIProvider.MESSAGE_SAVE_URI_COLUMN); 335 sendUri = cursor 336 .getString(UIProvider.MESSAGE_SEND_URI_COLUMN); 337 alwaysShowImages = cursor.getInt(UIProvider.MESSAGE_ALWAYS_SHOW_IMAGES_COLUMN) != 0; 338 read = cursor.getInt(UIProvider.MESSAGE_READ_COLUMN) != 0; 339 starred = cursor.getInt(UIProvider.MESSAGE_STARRED_COLUMN) != 0; 340 quotedTextOffset = cursor.getInt(UIProvider.QUOTED_TEXT_OFFSET_COLUMN); 341 attachmentsJson = cursor.getString(UIProvider.MESSAGE_ATTACHMENTS_COLUMN); 342 String accountUriString = cursor.getString(UIProvider.MESSAGE_ACCOUNT_URI_COLUMN); 343 accountUri = !TextUtils.isEmpty(accountUriString) ? Uri.parse(accountUriString) : null; 344 eventIntentUri = 345 Utils.getValidUri(cursor.getString(UIProvider.MESSAGE_EVENT_INTENT_COLUMN)); 346 spamWarningString = 347 cursor.getString(UIProvider.MESSAGE_SPAM_WARNING_STRING_ID_COLUMN); 348 spamWarningLevel = cursor.getInt(UIProvider.MESSAGE_SPAM_WARNING_LEVEL_COLUMN); 349 spamLinkType = cursor.getInt(UIProvider.MESSAGE_SPAM_WARNING_LINK_TYPE_COLUMN); 350 viaDomain = cursor.getString(UIProvider.MESSAGE_VIA_DOMAIN_COLUMN); 351 isSending = cursor.getInt(UIProvider.MESSAGE_IS_SENDING_COLUMN) != 0; 352 } 353 } 354 355 public boolean isFlaggedReplied() { 356 return (messageFlags & UIProvider.MessageFlags.REPLIED) == 357 UIProvider.MessageFlags.REPLIED; 358 } 359 360 public boolean isFlaggedForwarded() { 361 return (messageFlags & UIProvider.MessageFlags.FORWARDED) == 362 UIProvider.MessageFlags.FORWARDED; 363 } 364 365 public boolean isFlaggedCalendarInvite() { 366 return (messageFlags & UIProvider.MessageFlags.CALENDAR_INVITE) == 367 UIProvider.MessageFlags.CALENDAR_INVITE; 368 } 369 370 public synchronized String[] getFromAddresses() { 371 if (mFromAddresses == null) { 372 mFromAddresses = Utils.splitCommaSeparatedString(from); 373 } 374 return mFromAddresses; 375 } 376 377 public synchronized String[] getToAddresses() { 378 if (mToAddresses == null) { 379 mToAddresses = Utils.splitCommaSeparatedString(to); 380 } 381 return mToAddresses; 382 } 383 384 public synchronized String[] getCcAddresses() { 385 if (mCcAddresses == null) { 386 mCcAddresses = Utils.splitCommaSeparatedString(cc); 387 } 388 return mCcAddresses; 389 } 390 391 public synchronized String[] getBccAddresses() { 392 if (mBccAddresses == null) { 393 mBccAddresses = Utils.splitCommaSeparatedString(bcc); 394 } 395 return mBccAddresses; 396 } 397 398 public synchronized String[] getReplyToAddresses() { 399 if (mReplyToAddresses == null) { 400 mReplyToAddresses = Utils.splitCommaSeparatedString(replyTo); 401 } 402 return mReplyToAddresses; 403 } 404 405 public synchronized List<Attachment> getAttachments() { 406 if (mAttachments == null) { 407 if (attachmentsJson != null) { 408 mAttachments = Attachment.fromJSONArray(attachmentsJson); 409 } else { 410 mAttachments = Collections.emptyList(); 411 } 412 } 413 return mAttachments; 414 } 415 416 /** 417 * Returns whether a "Show Pictures" button should initially appear for this message. If the 418 * button is shown, the message must also block all non-local images in the body. Inversely, if 419 * the button is not shown, the message must show all images within (or else the user would be 420 * stuck with no images and no way to reveal them). 421 * 422 * @return true if a "Show Pictures" button should appear. 423 */ 424 public boolean shouldShowImagePrompt() { 425 return embedsExternalResources && !alwaysShowImages; 426 } 427 428 /** 429 * Helper method to command a provider to mark all messages from this sender with the 430 * {@link MessageColumns#ALWAYS_SHOW_IMAGES} flag set. 431 * 432 * @param handler a caller-provided handler to run the query on 433 * @param token (optional) token to identify the command to the handler 434 * @param cookie (optional) cookie to pass to the handler 435 */ 436 public void markAlwaysShowImages(AsyncQueryHandler handler, int token, Object cookie) { 437 alwaysShowImages = true; 438 439 final ContentValues values = new ContentValues(1); 440 values.put(UIProvider.MessageColumns.ALWAYS_SHOW_IMAGES, 1); 441 442 handler.startUpdate(token, cookie, uri, values, null, null); 443 } 444 445} 446