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