Message.java revision 839ada22ea84251dde3305003d2f8fc5bf14914e
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 String 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 private transient String[] mFromAddresses = null; 174 private transient String[] mToAddresses = null; 175 private transient String[] mCcAddresses = null; 176 private transient String[] mBccAddresses = null; 177 private transient String[] mReplyToAddresses = null; 178 179 private transient List<Attachment> mAttachments = null; 180 181 @Override 182 public int describeContents() { 183 return 0; 184 } 185 186 @Override 187 public boolean equals(Object o) { 188 if (o == null || !(o instanceof Message)) { 189 return false; 190 } 191 final Uri otherUri = ((Message) o).uri; 192 if (uri == null) { 193 return (otherUri == null); 194 } 195 return uri.equals(otherUri); 196 } 197 198 @Override 199 public int hashCode() { 200 return uri == null ? 0 : uri.hashCode(); 201 } 202 203 @Override 204 public void writeToParcel(Parcel dest, int flags) { 205 dest.writeLong(id); 206 dest.writeLong(serverId); 207 dest.writeParcelable(uri, 0); 208 dest.writeString(conversationUri); 209 dest.writeString(subject); 210 dest.writeString(snippet); 211 dest.writeString(from); 212 dest.writeString(to); 213 dest.writeString(cc); 214 dest.writeString(bcc); 215 dest.writeString(replyTo); 216 dest.writeLong(dateReceivedMs); 217 dest.writeString(bodyHtml); 218 dest.writeString(bodyText); 219 dest.writeInt(embedsExternalResources ? 1 : 0); 220 dest.writeString(refMessageId); 221 dest.writeInt(draftType); 222 dest.writeInt(appendRefMessageContent ? 1 : 0); 223 dest.writeInt(hasAttachments ? 1 : 0); 224 dest.writeParcelable(attachmentListUri, 0); 225 dest.writeLong(messageFlags); 226 dest.writeString(saveUri); 227 dest.writeString(sendUri); 228 dest.writeInt(alwaysShowImages ? 1 : 0); 229 dest.writeInt(quotedTextOffset); 230 dest.writeString(attachmentsJson); 231 dest.writeParcelable(accountUri, 0); 232 dest.writeParcelable(eventIntentUri, 0); 233 dest.writeString(spamWarningString); 234 dest.writeInt(spamWarningLevel); 235 dest.writeInt(spamLinkType); 236 dest.writeString(viaDomain); 237 } 238 239 private Message(Parcel in) { 240 id = in.readLong(); 241 serverId = in.readLong(); 242 uri = in.readParcelable(null); 243 conversationUri = in.readString(); 244 subject = in.readString(); 245 snippet = in.readString(); 246 from = in.readString(); 247 to = in.readString(); 248 cc = in.readString(); 249 bcc = in.readString(); 250 replyTo = in.readString(); 251 dateReceivedMs = in.readLong(); 252 bodyHtml = in.readString(); 253 bodyText = in.readString(); 254 embedsExternalResources = in.readInt() != 0; 255 refMessageId = in.readString(); 256 draftType = in.readInt(); 257 appendRefMessageContent = in.readInt() != 0; 258 hasAttachments = in.readInt() != 0; 259 attachmentListUri = in.readParcelable(null); 260 messageFlags = in.readLong(); 261 saveUri = in.readString(); 262 sendUri = in.readString(); 263 alwaysShowImages = in.readInt() != 0; 264 quotedTextOffset = in.readInt(); 265 attachmentsJson = in.readString(); 266 accountUri = in.readParcelable(null); 267 eventIntentUri = in.readParcelable(null); 268 spamWarningString = in.readString(); 269 spamWarningLevel = in.readInt(); 270 spamLinkType = in.readInt(); 271 viaDomain = in.readString(); 272 } 273 274 public Message() { 275 276 } 277 278 @Override 279 public String toString() { 280 return "[message id=" + id + "]"; 281 } 282 283 public static final Creator<Message> CREATOR = new Creator<Message>() { 284 285 @Override 286 public Message createFromParcel(Parcel source) { 287 return new Message(source); 288 } 289 290 @Override 291 public Message[] newArray(int size) { 292 return new Message[size]; 293 } 294 295 }; 296 297 public Message(Cursor cursor) { 298 if (cursor != null) { 299 id = cursor.getLong(UIProvider.MESSAGE_ID_COLUMN); 300 serverId = cursor.getLong(UIProvider.MESSAGE_SERVER_ID_COLUMN); 301 String message = cursor.getString(UIProvider.MESSAGE_URI_COLUMN); 302 uri = !TextUtils.isEmpty(message) ? Uri.parse(message) : null; 303 conversationUri = cursor.getString(UIProvider.MESSAGE_CONVERSATION_URI_COLUMN); 304 subject = cursor.getString(UIProvider.MESSAGE_SUBJECT_COLUMN); 305 snippet = cursor.getString(UIProvider.MESSAGE_SNIPPET_COLUMN); 306 from = cursor.getString(UIProvider.MESSAGE_FROM_COLUMN); 307 to = cursor.getString(UIProvider.MESSAGE_TO_COLUMN); 308 cc = cursor.getString(UIProvider.MESSAGE_CC_COLUMN); 309 bcc = cursor.getString(UIProvider.MESSAGE_BCC_COLUMN); 310 replyTo = cursor.getString(UIProvider.MESSAGE_REPLY_TO_COLUMN); 311 dateReceivedMs = cursor.getLong(UIProvider.MESSAGE_DATE_RECEIVED_MS_COLUMN); 312 bodyHtml = cursor.getString(UIProvider.MESSAGE_BODY_HTML_COLUMN); 313 bodyText = cursor.getString(UIProvider.MESSAGE_BODY_TEXT_COLUMN); 314 embedsExternalResources = cursor 315 .getInt(UIProvider.MESSAGE_EMBEDS_EXTERNAL_RESOURCES_COLUMN) != 0; 316 refMessageId = cursor.getString(UIProvider.MESSAGE_REF_MESSAGE_ID_COLUMN); 317 draftType = cursor.getInt(UIProvider.MESSAGE_DRAFT_TYPE_COLUMN); 318 appendRefMessageContent = cursor 319 .getInt(UIProvider.MESSAGE_APPEND_REF_MESSAGE_CONTENT_COLUMN) != 0; 320 hasAttachments = cursor.getInt(UIProvider.MESSAGE_HAS_ATTACHMENTS_COLUMN) != 0; 321 final String attachmentsUri = cursor 322 .getString(UIProvider.MESSAGE_ATTACHMENT_LIST_URI_COLUMN); 323 attachmentListUri = hasAttachments && !TextUtils.isEmpty(attachmentsUri) ? Uri 324 .parse(attachmentsUri) : null; 325 messageFlags = cursor.getLong(UIProvider.MESSAGE_FLAGS_COLUMN); 326 saveUri = cursor 327 .getString(UIProvider.MESSAGE_SAVE_URI_COLUMN); 328 sendUri = cursor 329 .getString(UIProvider.MESSAGE_SEND_URI_COLUMN); 330 alwaysShowImages = cursor.getInt(UIProvider.MESSAGE_ALWAYS_SHOW_IMAGES_COLUMN) != 0; 331 read = cursor.getInt(UIProvider.MESSAGE_READ_COLUMN) != 0; 332 starred = cursor.getInt(UIProvider.MESSAGE_STARRED_COLUMN) != 0; 333 quotedTextOffset = cursor.getInt(UIProvider.QUOTED_TEXT_OFFSET_COLUMN); 334 attachmentsJson = cursor.getString(UIProvider.MESSAGE_ATTACHMENTS_COLUMN); 335 String accountUriString = cursor.getString(UIProvider.MESSAGE_ACCOUNT_URI_COLUMN); 336 accountUri = !TextUtils.isEmpty(accountUriString) ? Uri.parse(accountUriString) : null; 337 eventIntentUri = 338 Utils.getValidUri(cursor.getString(UIProvider.MESSAGE_EVENT_INTENT_COLUMN)); 339 spamWarningString = 340 cursor.getString(UIProvider.MESSAGE_SPAM_WARNING_STRING_ID_COLUMN); 341 spamWarningLevel = cursor.getInt(UIProvider.MESSAGE_SPAM_WARNING_LEVEL_COLUMN); 342 spamLinkType = cursor.getInt(UIProvider.MESSAGE_SPAM_WARNING_LINK_TYPE_COLUMN); 343 viaDomain = cursor.getString(UIProvider.MESSAGE_VIA_DOMAIN_COLUMN); 344 } 345 } 346 347 public boolean isFlaggedReplied() { 348 return (messageFlags & UIProvider.MessageFlags.REPLIED) == 349 UIProvider.MessageFlags.REPLIED; 350 } 351 352 public boolean isFlaggedForwarded() { 353 return (messageFlags & UIProvider.MessageFlags.FORWARDED) == 354 UIProvider.MessageFlags.FORWARDED; 355 } 356 357 public boolean isFlaggedCalendarInvite() { 358 return (messageFlags & UIProvider.MessageFlags.CALENDAR_INVITE) == 359 UIProvider.MessageFlags.CALENDAR_INVITE; 360 } 361 362 public synchronized String[] getFromAddresses() { 363 if (mFromAddresses == null) { 364 mFromAddresses = Utils.splitCommaSeparatedString(from); 365 } 366 return mFromAddresses; 367 } 368 369 public synchronized String[] getToAddresses() { 370 if (mToAddresses == null) { 371 mToAddresses = Utils.splitCommaSeparatedString(to); 372 } 373 return mToAddresses; 374 } 375 376 public synchronized String[] getCcAddresses() { 377 if (mCcAddresses == null) { 378 mCcAddresses = Utils.splitCommaSeparatedString(cc); 379 } 380 return mCcAddresses; 381 } 382 383 public synchronized String[] getBccAddresses() { 384 if (mBccAddresses == null) { 385 mBccAddresses = Utils.splitCommaSeparatedString(bcc); 386 } 387 return mBccAddresses; 388 } 389 390 public synchronized String[] getReplyToAddresses() { 391 if (mReplyToAddresses == null) { 392 mReplyToAddresses = Utils.splitCommaSeparatedString(replyTo); 393 } 394 return mReplyToAddresses; 395 } 396 397 public synchronized List<Attachment> getAttachments() { 398 if (mAttachments == null) { 399 if (attachmentsJson != null) { 400 mAttachments = Attachment.fromJSONArray(attachmentsJson); 401 } else { 402 mAttachments = Collections.emptyList(); 403 } 404 } 405 return mAttachments; 406 } 407 408 /** 409 * Returns whether a "Show Pictures" button should initially appear for this message. If the 410 * button is shown, the message must also block all non-local images in the body. Inversely, if 411 * the button is not shown, the message must show all images within (or else the user would be 412 * stuck with no images and no way to reveal them). 413 * 414 * @return true if a "Show Pictures" button should appear. 415 */ 416 public boolean shouldShowImagePrompt() { 417 return embedsExternalResources && !alwaysShowImages; 418 } 419 420 /** 421 * Helper method to command a provider to mark all messages from this sender with the 422 * {@link MessageColumns#ALWAYS_SHOW_IMAGES} flag set. 423 * 424 * @param handler a caller-provided handler to run the query on 425 * @param token (optional) token to identify the command to the handler 426 * @param cookie (optional) cookie to pass to the handler 427 */ 428 public void markAlwaysShowImages(AsyncQueryHandler handler, int token, Object cookie) { 429 alwaysShowImages = true; 430 431 final ContentValues values = new ContentValues(1); 432 values.put(UIProvider.MessageColumns.ALWAYS_SHOW_IMAGES, 1); 433 434 handler.startUpdate(token, cookie, uri, values, null, null); 435 } 436 437} 438