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