MessageListItem.java revision 8429b927ffb65c52b00da410fd60b2b1790c1026
1/* 2 * Copyright (C) 2008 Esmertec AG. 3 * Copyright (C) 2008 The Android Open Source Project 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package com.android.mms.ui; 19 20import java.util.Map; 21import java.util.regex.Matcher; 22import java.util.regex.Pattern; 23 24import android.app.AlertDialog; 25import android.content.Context; 26import android.content.DialogInterface; 27import android.content.Intent; 28import android.content.res.Resources; 29import android.graphics.Bitmap; 30import android.graphics.BitmapFactory; 31import android.graphics.Typeface; 32import android.graphics.Paint.FontMetricsInt; 33import android.graphics.drawable.Drawable; 34import android.net.Uri; 35import android.os.Handler; 36import android.os.Message; 37import android.provider.Browser; 38import android.provider.Telephony.Mms; 39import android.provider.Telephony.Sms; 40import android.telephony.PhoneNumberUtils; 41import android.text.Html; 42import android.text.Spannable; 43import android.text.SpannableStringBuilder; 44import android.text.TextUtils; 45import android.text.method.HideReturnsTransformationMethod; 46import android.text.style.ForegroundColorSpan; 47import android.text.style.LineHeightSpan; 48import android.text.style.StyleSpan; 49import android.text.style.TextAppearanceSpan; 50import android.text.style.URLSpan; 51import android.util.AttributeSet; 52import android.util.DisplayMetrics; 53import android.util.Log; 54import android.view.Gravity; 55import android.view.View; 56import android.view.ViewGroup; 57import android.view.View.OnClickListener; 58import android.widget.ArrayAdapter; 59import android.widget.Button; 60import android.widget.ImageButton; 61import android.widget.ImageView; 62import android.widget.LinearLayout; 63import android.widget.QuickContactBadge; 64import android.widget.RelativeLayout; 65import android.widget.TextView; 66 67import com.android.mms.MmsApp; 68import com.android.mms.R; 69import com.android.mms.data.WorkingMessage; 70import com.android.mms.transaction.Transaction; 71import com.android.mms.transaction.TransactionBundle; 72import com.android.mms.transaction.TransactionService; 73import com.android.mms.util.DownloadManager; 74import com.android.mms.util.SmileyParser; 75import com.google.android.mms.ContentType; 76import com.google.android.mms.pdu.PduHeaders; 77 78/** 79 * This class provides view of a message in the messages list. 80 */ 81public class MessageListItem extends LinearLayout implements 82 SlideViewInterface, OnClickListener { 83 public static final String EXTRA_URLS = "com.android.mms.ExtraUrls"; 84 85 private static final String TAG = "MessageListItem"; 86 private static final StyleSpan STYLE_BOLD = new StyleSpan(Typeface.BOLD); 87 88 static final int MSG_LIST_EDIT_MMS = 1; 89 static final int MSG_LIST_EDIT_SMS = 2; 90 91 private View mMsgListItem; 92 private View mMmsView; 93 private ImageView mImageView; 94 private ImageView mLockedIndicator; 95 private ImageView mDeliveredIndicator; 96 private ImageView mDetailsIndicator; 97 private ImageButton mSlideShowButton; 98 private TextView mBodyTextView; 99 private Button mDownloadButton; 100 private TextView mDownloadingLabel; 101 private QuickContactBadge mAvatar; 102 private Handler mHandler; 103 private MessageItem mMessageItem; 104 private String mDefaultCountryIso; 105 private TextView mDateView; 106 private LinearLayout mStatusIcons; 107 private Drawable mLeftDivitDrawable; 108 private Drawable mRightDivitDrawable; 109 private View mDivit; // little triangle on the side of the avatar 110 111 public MessageListItem(Context context) { 112 super(context); 113 mDefaultCountryIso = MmsApp.getApplication().getCurrentCountryIso(); 114 } 115 116 public MessageListItem(Context context, AttributeSet attrs) { 117 super(context, attrs); 118 119 int color = mContext.getResources().getColor(R.color.timestamp_color); 120 mColorSpan = new ForegroundColorSpan(color); 121 mDefaultCountryIso = MmsApp.getApplication().getCurrentCountryIso(); 122 } 123 124 @Override 125 protected void onFinishInflate() { 126 super.onFinishInflate(); 127 128 mMsgListItem = findViewById(R.id.msg_list_item); 129 mBodyTextView = (TextView) findViewById(R.id.text_view); 130 mDateView = (TextView) findViewById(R.id.date_view); 131 mLockedIndicator = (ImageView) findViewById(R.id.locked_indicator); 132 mDeliveredIndicator = (ImageView) findViewById(R.id.delivered_indicator); 133 mDetailsIndicator = (ImageView) findViewById(R.id.details_indicator); 134 mAvatar = (QuickContactBadge) findViewById(R.id.avatar); 135 mStatusIcons = (LinearLayout) findViewById(R.id.status_icons); 136 137 mDivit = findViewById(R.id.divit); 138 float density = mContext.getResources().getDisplayMetrics().density; 139 mLeftDivitDrawable = new DivitDrawable(DivitDrawable.LEFT_UPPER, density); 140 mRightDivitDrawable = new DivitDrawable(DivitDrawable.RIGHT_UPPER, density); 141 } 142 143 public void bind(MessageListAdapter.AvatarCache avatarCache, MessageItem msgItem) { 144 mMessageItem = msgItem; 145 146 setLongClickable(false); 147 148 switch (msgItem.mMessageType) { 149 case PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND: 150 bindNotifInd(msgItem); 151 break; 152 default: 153 bindCommonMessage(avatarCache, msgItem); 154 break; 155 } 156 } 157 158 public MessageItem getMessageItem() { 159 return mMessageItem; 160 } 161 162 public void setMsgListItemHandler(Handler handler) { 163 mHandler = handler; 164 } 165 166 private void bindNotifInd(final MessageItem msgItem) { 167 hideMmsViewIfNeeded(); 168 169 String msgSizeText = mContext.getString(R.string.message_size_label) 170 + String.valueOf((msgItem.mMessageSize + 1023) / 1024) 171 + mContext.getString(R.string.kilobyte); 172 173 mBodyTextView.setText(formatMessage(msgItem, msgItem.mContact, null, msgItem.mSubject, 174 msgItem.mHighlight, msgItem.mTextContentType)); 175 176 mDateView.setText(msgSizeText + " " + msgItem.mTimestamp); 177 178 int state = DownloadManager.getInstance().getState(msgItem.mMessageUri); 179 switch (state) { 180 case DownloadManager.STATE_DOWNLOADING: 181 inflateDownloadControls(); 182 mDownloadingLabel.setVisibility(View.VISIBLE); 183 mDownloadButton.setVisibility(View.GONE); 184 break; 185 case DownloadManager.STATE_UNSTARTED: 186 case DownloadManager.STATE_TRANSIENT_FAILURE: 187 case DownloadManager.STATE_PERMANENT_FAILURE: 188 default: 189 setLongClickable(true); 190 inflateDownloadControls(); 191 mDownloadingLabel.setVisibility(View.GONE); 192 mDownloadButton.setVisibility(View.VISIBLE); 193 mDownloadButton.setOnClickListener(new OnClickListener() { 194 public void onClick(View v) { 195 mDownloadingLabel.setVisibility(View.VISIBLE); 196 mDownloadButton.setVisibility(View.GONE); 197 Intent intent = new Intent(mContext, TransactionService.class); 198 intent.putExtra(TransactionBundle.URI, msgItem.mMessageUri.toString()); 199 intent.putExtra(TransactionBundle.TRANSACTION_TYPE, 200 Transaction.RETRIEVE_TRANSACTION); 201 mContext.startService(intent); 202 } 203 }); 204 break; 205 } 206 207 // Hide the indicators. 208 mLockedIndicator.setVisibility(View.GONE); 209 mDeliveredIndicator.setVisibility(View.GONE); 210 mDetailsIndicator.setVisibility(View.GONE); 211 } 212 213 private void bindCommonMessage(final MessageListAdapter.AvatarCache avatarCache, 214 final MessageItem msgItem) { 215 if (mDownloadButton != null) { 216 mDownloadButton.setVisibility(View.GONE); 217 mDownloadingLabel.setVisibility(View.GONE); 218 } 219 // Since the message text should be concatenated with the sender's 220 // address(or name), I have to display it here instead of 221 // displaying it by the Presenter. 222 mBodyTextView.setTransformationMethod(HideReturnsTransformationMethod.getInstance()); 223 224 String addr = null; 225 if (!Sms.isOutgoingFolder(msgItem.mBoxId)) { 226 addr = msgItem.mAddress; 227 } else { 228 addr = MmsApp.getApplication().getTelephonyManager().getLine1Number(); 229 } 230 if (!TextUtils.isEmpty(addr)) { 231 MessageListAdapter.AvatarCache.ContactData contactData = avatarCache.get(addr); 232 mAvatar.setImageDrawable(contactData.getAvatar()); 233 Uri contactUri = contactData.getContactUri(); 234 // Since we load the contact info in the background, on the first screenfull of 235 // messages, it's likely we haven't loaded the contact URI info yet. In that case, 236 // fall back and use the phone number. 237 if (contactUri != null) { 238 mAvatar.assignContactUri(contactUri); 239 } else { 240 mAvatar.assignContactFromPhone(addr, true); 241 } 242 } else { 243 mAvatar.setImageToDefault(); 244 mAvatar.assignContactUri(null); 245 } 246 247 // Get and/or lazily set the formatted message from/on the 248 // MessageItem. Because the MessageItem instances come from a 249 // cache (currently of size ~50), the hit rate on avoiding the 250 // expensive formatMessage() call is very high. 251 CharSequence formattedMessage = msgItem.getCachedFormattedMessage(); 252 if (formattedMessage == null) { 253 formattedMessage = formatMessage(msgItem, msgItem.mContact, msgItem.mBody, 254 msgItem.mSubject, 255 msgItem.mHighlight, msgItem.mTextContentType); 256 } 257 mBodyTextView.setText(formattedMessage); 258 259 // If we're in the process of sending a message (i.e. pending), then we show a "SENDING..." 260 // string in place of the timestamp. 261 mDateView.setText(msgItem.isSending() ? 262 mContext.getResources().getString(R.string.sending_message) : 263 msgItem.mTimestamp); 264 265 if (msgItem.isSms()) { 266 hideMmsViewIfNeeded(); 267 } else { 268 Presenter presenter = PresenterFactory.getPresenter( 269 "MmsThumbnailPresenter", mContext, 270 this, msgItem.mSlideshow); 271 presenter.present(); 272 273 if (msgItem.mAttachmentType != WorkingMessage.TEXT) { 274 inflateMmsView(); 275 mMmsView.setVisibility(View.VISIBLE); 276 setOnClickListener(msgItem); 277 drawPlaybackButton(msgItem); 278 } else { 279 hideMmsViewIfNeeded(); 280 } 281 } 282 283 adjustLayoutItems(msgItem); 284 drawRightStatusIndicator(msgItem); 285 286 requestLayout(); 287 } 288 289 private void adjustLayoutItems(final MessageItem msgItem) { 290 // Put the avatar on the left or right 291 RelativeLayout.LayoutParams avatarLayout = 292 (RelativeLayout.LayoutParams)mAvatar.getLayoutParams(); 293 RelativeLayout.LayoutParams textLayout = 294 (RelativeLayout.LayoutParams)mBodyTextView.getLayoutParams(); 295 RelativeLayout.LayoutParams dateLayout = 296 (RelativeLayout.LayoutParams)mDateView.getLayoutParams(); 297 RelativeLayout.LayoutParams statusIconsLayout = 298 (RelativeLayout.LayoutParams)mStatusIcons.getLayoutParams(); 299 RelativeLayout.LayoutParams divitLayout = 300 (RelativeLayout.LayoutParams)mDivit.getLayoutParams(); 301 302 Resources resources = mContext.getResources(); 303 int textPaddingLeftRight = resources.getDimensionPixelOffset( 304 R.dimen.message_item_text_padding_left_right); 305 int textPaddingTop = resources.getDimensionPixelOffset( 306 R.dimen.message_item_text_padding_top); 307 308 if (msgItem.mBoxId == Mms.MESSAGE_BOX_INBOX) { 309 // Avatar on left, text adjusted left 310 // undo the old rules first 311 textLayout.addRule(RelativeLayout.ALIGN_PARENT_LEFT, 0); 312 textLayout.addRule(RelativeLayout.LEFT_OF, 0); 313 avatarLayout.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, 0); 314 statusIconsLayout.addRule(RelativeLayout.LEFT_OF, 0); 315 dateLayout.addRule(RelativeLayout.LEFT_OF, 0); 316 divitLayout.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, 0); 317 318 // set the new rules 319 avatarLayout.addRule(RelativeLayout.ALIGN_PARENT_LEFT); 320 textLayout.addRule(RelativeLayout.RIGHT_OF, R.id.avatar); 321 textLayout.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); 322 dateLayout.addRule(RelativeLayout.RIGHT_OF, R.id.avatar); 323 statusIconsLayout.addRule(RelativeLayout.RIGHT_OF, R.id.date_view); 324 325 mBodyTextView.setPadding(textPaddingLeftRight, 326 textPaddingTop, 327 textPaddingLeftRight, 328 0); 329 mBodyTextView.setGravity(Gravity.LEFT); 330 mDateView.setPadding(textPaddingLeftRight, 0, 0, 0); 331 332 mDivit.setBackgroundDrawable(mRightDivitDrawable); 333 divitLayout.addRule(RelativeLayout.ALIGN_PARENT_LEFT); 334 } else { 335 // Avatar on right, text adjusted right 336 // undo the old rules first 337 avatarLayout.addRule(RelativeLayout.ALIGN_PARENT_LEFT, 0); 338 textLayout.addRule(RelativeLayout.RIGHT_OF, 0); 339 textLayout.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, 0); 340 dateLayout.addRule(RelativeLayout.RIGHT_OF, 0); 341 statusIconsLayout.addRule(RelativeLayout.RIGHT_OF, 0); 342 divitLayout.addRule(RelativeLayout.ALIGN_PARENT_LEFT, 0); 343 344 // set the new rules 345 textLayout.addRule(RelativeLayout.ALIGN_PARENT_LEFT); 346 textLayout.addRule(RelativeLayout.LEFT_OF, R.id.avatar); 347 avatarLayout.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); 348 statusIconsLayout.addRule(RelativeLayout.LEFT_OF, R.id.date_view); 349 dateLayout.addRule(RelativeLayout.LEFT_OF, R.id.avatar); 350 351 mBodyTextView.setPadding(resources 352 .getDimensionPixelOffset(R.dimen.message_item_avatar_on_right_text_indent), 353 textPaddingTop, 354 textPaddingLeftRight, 355 0); 356 mBodyTextView.setGravity(Gravity.RIGHT); 357 mDateView.setPadding(0, 0, textPaddingLeftRight, 0); 358 359 mDivit.setBackgroundDrawable(mLeftDivitDrawable); 360 divitLayout.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); 361 } 362 } 363 364 private void hideMmsViewIfNeeded() { 365 if (mMmsView != null) { 366 mMmsView.setVisibility(View.GONE); 367 } 368 } 369 370 public void startAudio() { 371 // TODO Auto-generated method stub 372 } 373 374 public void startVideo() { 375 // TODO Auto-generated method stub 376 } 377 378 public void setAudio(Uri audio, String name, Map<String, ?> extras) { 379 // TODO Auto-generated method stub 380 } 381 382 public void setImage(String name, Bitmap bitmap) { 383 inflateMmsView(); 384 385 try { 386 if (null == bitmap) { 387 bitmap = BitmapFactory.decodeResource(getResources(), 388 R.drawable.ic_missing_thumbnail_picture); 389 } 390 mImageView.setImageBitmap(bitmap); 391 mImageView.setVisibility(VISIBLE); 392 } catch (java.lang.OutOfMemoryError e) { 393 Log.e(TAG, "setImage: out of memory: ", e); 394 } 395 } 396 397 private void inflateMmsView() { 398 if (mMmsView == null) { 399 //inflate the surrounding view_stub 400 findViewById(R.id.mms_layout_view_stub).setVisibility(VISIBLE); 401 402 mMmsView = findViewById(R.id.mms_view); 403 mImageView = (ImageView) findViewById(R.id.image_view); 404 mSlideShowButton = (ImageButton) findViewById(R.id.play_slideshow_button); 405 } 406 } 407 408 private void inflateDownloadControls() { 409 if (mDownloadButton == null) { 410 //inflate the download controls 411 findViewById(R.id.mms_downloading_view_stub).setVisibility(VISIBLE); 412 mDownloadButton = (Button) findViewById(R.id.btn_download_msg); 413 mDownloadingLabel = (TextView) findViewById(R.id.label_downloading); 414 } 415 } 416 417 418 private LineHeightSpan mSpan = new LineHeightSpan() { 419 public void chooseHeight(CharSequence text, int start, 420 int end, int spanstartv, int v, FontMetricsInt fm) { 421 fm.ascent -= 10; 422 } 423 }; 424 425 TextAppearanceSpan mTextSmallSpan = 426 new TextAppearanceSpan(mContext, android.R.style.TextAppearance_Small); 427 428 ForegroundColorSpan mColorSpan = null; // set in ctor 429 430 private CharSequence formatMessage(MessageItem msgItem, String contact, String body, 431 String subject, Pattern highlight, 432 String contentType) { 433 SpannableStringBuilder buf = new SpannableStringBuilder(); 434 435 boolean hasSubject = !TextUtils.isEmpty(subject); 436 if (hasSubject) { 437 buf.append(mContext.getResources().getString(R.string.inline_subject, subject)); 438 } 439 440 if (!TextUtils.isEmpty(body)) { 441 // Converts html to spannable if ContentType is "text/html". 442 if (contentType != null && ContentType.TEXT_HTML.equals(contentType)) { 443 buf.append("\n"); 444 buf.append(Html.fromHtml(body)); 445 } else { 446 if (hasSubject) { 447 buf.append(" - "); 448 } 449 SmileyParser parser = SmileyParser.getInstance(); 450 buf.append(parser.addSmileySpans(body)); 451 } 452 } 453 454 if (highlight != null) { 455 Matcher m = highlight.matcher(buf.toString()); 456 while (m.find()) { 457 buf.setSpan(new StyleSpan(Typeface.BOLD), m.start(), m.end(), 0); 458 } 459 } 460 return buf; 461 } 462 463 private void drawPlaybackButton(MessageItem msgItem) { 464 switch (msgItem.mAttachmentType) { 465 case WorkingMessage.SLIDESHOW: 466 case WorkingMessage.AUDIO: 467 case WorkingMessage.VIDEO: 468 // Show the 'Play' button and bind message info on it. 469 mSlideShowButton.setTag(msgItem); 470 // Set call-back for the 'Play' button. 471 mSlideShowButton.setOnClickListener(this); 472 mSlideShowButton.setVisibility(View.VISIBLE); 473 setLongClickable(true); 474 475 // When we show the mSlideShowButton, this list item's onItemClickListener doesn't 476 // get called. (It gets set in ComposeMessageActivity: 477 // mMsgListView.setOnItemClickListener) Here we explicitly set the item's 478 // onClickListener. It allows the item to respond to embedded html links and at the 479 // same time, allows the slide show play button to work. 480 setOnClickListener(new OnClickListener() { 481 public void onClick(View v) { 482 onMessageListItemClick(); 483 } 484 }); 485 break; 486 default: 487 mSlideShowButton.setVisibility(View.GONE); 488 break; 489 } 490 } 491 492 // OnClick Listener for the playback button 493 public void onClick(View v) { 494 MessageItem mi = (MessageItem) v.getTag(); 495 switch (mi.mAttachmentType) { 496 case WorkingMessage.VIDEO: 497 case WorkingMessage.AUDIO: 498 case WorkingMessage.SLIDESHOW: 499 MessageUtils.viewMmsMessageAttachment(mContext, mi.mMessageUri, mi.mSlideshow); 500 break; 501 } 502 } 503 504 public void onMessageListItemClick() { 505 URLSpan[] spans = mBodyTextView.getUrls(); 506 507 if (spans.length == 0) { 508 // Do nothing. 509 } else if (spans.length == 1) { 510 Uri uri = Uri.parse(spans[0].getURL()); 511 Intent intent = new Intent(Intent.ACTION_VIEW, uri); 512 intent.putExtra(Browser.EXTRA_APPLICATION_ID, mContext.getPackageName()); 513 intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); 514 mContext.startActivity(intent); 515 } else { 516 final java.util.ArrayList<String> urls = MessageUtils.extractUris(spans); 517 518 ArrayAdapter<String> adapter = 519 new ArrayAdapter<String>(mContext, android.R.layout.select_dialog_item, urls) { 520 public View getView(int position, View convertView, ViewGroup parent) { 521 View v = super.getView(position, convertView, parent); 522 try { 523 String url = getItem(position).toString(); 524 TextView tv = (TextView) v; 525 Drawable d = mContext.getPackageManager().getActivityIcon(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); 526 if (d != null) { 527 d.setBounds(0, 0, d.getIntrinsicHeight(), d.getIntrinsicHeight()); 528 tv.setCompoundDrawablePadding(10); 529 tv.setCompoundDrawables(d, null, null, null); 530 } 531 final String telPrefix = "tel:"; 532 if (url.startsWith(telPrefix)) { 533 url = PhoneNumberUtils.formatNumber( 534 url.substring(telPrefix.length()), mDefaultCountryIso); 535 } 536 tv.setText(url); 537 } catch (android.content.pm.PackageManager.NameNotFoundException ex) { 538 ; 539 } 540 return v; 541 } 542 }; 543 544 AlertDialog.Builder b = new AlertDialog.Builder(mContext); 545 546 DialogInterface.OnClickListener click = new DialogInterface.OnClickListener() { 547 public final void onClick(DialogInterface dialog, int which) { 548 if (which >= 0) { 549 Uri uri = Uri.parse(urls.get(which)); 550 Intent intent = new Intent(Intent.ACTION_VIEW, uri); 551 intent.putExtra(Browser.EXTRA_APPLICATION_ID, mContext.getPackageName()); 552 intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); 553 mContext.startActivity(intent); 554 } 555 dialog.dismiss(); 556 } 557 }; 558 559 b.setTitle(R.string.select_link_title); 560 b.setCancelable(true); 561 b.setAdapter(adapter, click); 562 563 b.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { 564 public final void onClick(DialogInterface dialog, int which) { 565 dialog.dismiss(); 566 } 567 }); 568 569 b.show(); 570 } 571 } 572 573 574 private void setOnClickListener(final MessageItem msgItem) { 575 switch(msgItem.mAttachmentType) { 576 case WorkingMessage.IMAGE: 577 case WorkingMessage.VIDEO: 578 mImageView.setOnClickListener(new OnClickListener() { 579 public void onClick(View v) { 580 MessageUtils.viewMmsMessageAttachment(mContext, null, msgItem.mSlideshow); 581 } 582 }); 583 mImageView.setOnLongClickListener(new OnLongClickListener() { 584 public boolean onLongClick(View v) { 585 return v.showContextMenu(); 586 } 587 }); 588 break; 589 590 default: 591 mImageView.setOnClickListener(null); 592 break; 593 } 594 } 595 596 private void setErrorIndicatorClickListener(final MessageItem msgItem) { 597 String type = msgItem.mType; 598 final int what; 599 if (type.equals("sms")) { 600 what = MSG_LIST_EDIT_SMS; 601 } else { 602 what = MSG_LIST_EDIT_MMS; 603 } 604 mDeliveredIndicator.setOnClickListener(new OnClickListener() { 605 public void onClick(View v) { 606 if (null != mHandler) { 607 Message msg = Message.obtain(mHandler, what); 608 msg.obj = new Long(msgItem.mMsgId); 609 msg.sendToTarget(); 610 } 611 } 612 }); 613 } 614 615 private void drawRightStatusIndicator(MessageItem msgItem) { 616 // Locked icon 617 if (msgItem.mLocked) { 618 mLockedIndicator.setImageResource(R.drawable.ic_lock_message_sms); 619 mLockedIndicator.setVisibility(View.VISIBLE); 620 } else { 621 mLockedIndicator.setVisibility(View.GONE); 622 } 623 624 // Delivery icon 625 if (msgItem.isOutgoingMessage() && msgItem.isFailedMessage()) { 626 mDeliveredIndicator.setImageResource(R.drawable.ic_list_alert_sms_failed); 627 setErrorIndicatorClickListener(msgItem); 628 mDeliveredIndicator.setVisibility(View.VISIBLE); 629 } else if (msgItem.mDeliveryStatus == MessageItem.DeliveryStatus.FAILED) { 630 mDeliveredIndicator.setImageResource(R.drawable.ic_list_alert_sms_failed); 631 mDeliveredIndicator.setVisibility(View.VISIBLE); 632 } else if (msgItem.mDeliveryStatus == MessageItem.DeliveryStatus.RECEIVED) { 633 mDeliveredIndicator.setImageResource(R.drawable.ic_sms_mms_delivered); 634 mDeliveredIndicator.setVisibility(View.VISIBLE); 635 } else { 636 mDeliveredIndicator.setVisibility(View.GONE); 637 } 638 639 // Message details icon 640 if (msgItem.mDeliveryStatus == MessageItem.DeliveryStatus.INFO || msgItem.mReadReport) { 641 mDetailsIndicator.setImageResource(R.drawable.ic_sms_mms_details); 642 mDetailsIndicator.setVisibility(View.VISIBLE); 643 } else { 644 mDetailsIndicator.setVisibility(View.GONE); 645 } 646 } 647 648 public void setImageRegionFit(String fit) { 649 // TODO Auto-generated method stub 650 } 651 652 public void setImageVisibility(boolean visible) { 653 // TODO Auto-generated method stub 654 } 655 656 public void setText(String name, String text) { 657 // TODO Auto-generated method stub 658 } 659 660 public void setTextVisibility(boolean visible) { 661 // TODO Auto-generated method stub 662 } 663 664 public void setVideo(String name, Uri video) { 665 inflateMmsView(); 666 667 try { 668 Bitmap bitmap = VideoAttachmentView.createVideoThumbnail(mContext, video); 669 if (null == bitmap) { 670 bitmap = BitmapFactory.decodeResource(getResources(), 671 R.drawable.ic_missing_thumbnail_video); 672 } 673 mImageView.setImageBitmap(bitmap); 674 mImageView.setVisibility(VISIBLE); 675 } catch (java.lang.OutOfMemoryError e) { 676 Log.e(TAG, "setVideo: out of memory: ", e); 677 } 678 } 679 680 public void setVideoVisibility(boolean visible) { 681 // TODO Auto-generated method stub 682 } 683 684 public void stopAudio() { 685 // TODO Auto-generated method stub 686 } 687 688 public void stopVideo() { 689 // TODO Auto-generated method stub 690 } 691 692 public void reset() { 693 if (mImageView != null) { 694 mImageView.setVisibility(GONE); 695 } 696 } 697 698 public void setVisibility(boolean visible) { 699 // TODO Auto-generated method stub 700 } 701 702 public void pauseAudio() { 703 // TODO Auto-generated method stub 704 705 } 706 707 public void pauseVideo() { 708 // TODO Auto-generated method stub 709 710 } 711 712 public void seekAudio(int seekTo) { 713 // TODO Auto-generated method stub 714 715 } 716 717 public void seekVideo(int seekTo) { 718 // TODO Auto-generated method stub 719 720 } 721} 722