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 android.app.Activity; 21 import android.app.AlertDialog; 22 import android.content.ContentUris; 23 import android.content.Context; 24 import android.content.DialogInterface; 25 import android.content.Intent; 26 import android.content.res.Resources; 27 import android.media.RingtoneManager; 28 import android.net.Uri; 29 import android.os.Bundle; 30 import android.os.Handler; 31 import android.provider.Settings; 32 import android.text.InputFilter; 33 import android.text.InputFilter.LengthFilter; 34 import android.text.TextUtils; 35 import android.util.Log; 36 import android.view.Menu; 37 import android.view.MenuItem; 38 import android.view.SubMenu; 39 import android.view.View; 40 import android.view.View.OnClickListener; 41 import android.widget.Button; 42 import android.widget.EditText; 43 import android.widget.ImageButton; 44 import android.widget.Toast; 45 46 import com.android.mms.ExceedMessageSizeException; 47 import com.android.mms.MmsApp; 48 import com.android.mms.MmsConfig; 49 import com.android.mms.R; 50 import com.android.mms.ResolutionException; 51 import com.android.mms.TempFileProvider; 52 import com.android.mms.UnsupportContentTypeException; 53 import com.android.mms.model.IModelChangedObserver; 54 import com.android.mms.model.LayoutModel; 55 import com.android.mms.model.Model; 56 import com.android.mms.model.SlideModel; 57 import com.android.mms.model.SlideshowModel; 58 import com.android.mms.ui.BasicSlideEditorView.OnTextChangedListener; 59 import com.android.mms.ui.MessageUtils.ResizeImageResultCallback; 60 import com.google.android.mms.ContentType; 61 import com.google.android.mms.MmsException; 62 import com.google.android.mms.pdu.PduBody; 63 import com.google.android.mms.pdu.PduPart; 64 import com.google.android.mms.pdu.PduPersister; 65 66 /** 67 * This activity allows user to edit the contents of a slide. 68 */ 69 public class SlideEditorActivity extends Activity { 70 private static final String TAG = "SlideEditorActivity"; 71 private static final boolean DEBUG = false; 72 private static final boolean LOCAL_LOGV = false; 73 74 // Key for extra data. 75 public static final String SLIDE_INDEX = "slide_index"; 76 77 // Menu ids. 78 private final static int MENU_REMOVE_TEXT = 0; 79 private final static int MENU_ADD_PICTURE = 1; 80 private final static int MENU_TAKE_PICTURE = 2; 81 private final static int MENU_DEL_PICTURE = 3; 82 private final static int MENU_ADD_AUDIO = 4; 83 private final static int MENU_DEL_AUDIO = 5; 84 private final static int MENU_ADD_VIDEO = 6; 85 private final static int MENU_ADD_SLIDE = 7; 86 private final static int MENU_DEL_VIDEO = 8; 87 private final static int MENU_LAYOUT = 9; 88 private final static int MENU_DURATION = 10; 89 private final static int MENU_PREVIEW_SLIDESHOW = 11; 90 private final static int MENU_RECORD_SOUND = 12; 91 private final static int MENU_SUB_AUDIO = 13; 92 private final static int MENU_TAKE_VIDEO = 14; 93 94 // Request code. 95 private final static int REQUEST_CODE_EDIT_TEXT = 0; 96 private final static int REQUEST_CODE_CHANGE_PICTURE = 1; 97 private final static int REQUEST_CODE_TAKE_PICTURE = 2; 98 private final static int REQUEST_CODE_CHANGE_MUSIC = 3; 99 private final static int REQUEST_CODE_RECORD_SOUND = 4; 100 private final static int REQUEST_CODE_CHANGE_VIDEO = 5; 101 private final static int REQUEST_CODE_CHANGE_DURATION = 6; 102 private final static int REQUEST_CODE_TAKE_VIDEO = 7; 103 104 // number of items in the duration selector dialog that directly map from 105 // item index to duration in seconds (duration = index + 1) 106 private final static int NUM_DIRECT_DURATIONS = 10; 107 108 private ImageButton mNextSlide; 109 private ImageButton mPreSlide; 110 private Button mPreview; 111 private Button mReplaceImage; 112 private Button mRemoveSlide; 113 private EditText mTextEditor; 114 private Button mDone; 115 private BasicSlideEditorView mSlideView; 116 117 private SlideshowModel mSlideshowModel; 118 private SlideshowEditor mSlideshowEditor; 119 private SlideshowPresenter mPresenter; 120 private boolean mDirty; 121 122 private int mPosition; 123 private Uri mUri; 124 125 private final static String MESSAGE_URI = "message_uri"; 126 private AsyncDialog mAsyncDialog; // Used for background tasks. 127 128 @Override 129 protected void onCreate(Bundle savedInstanceState) { 130 super.onCreate(savedInstanceState); 131 setContentView(R.layout.edit_slide_activity); 132 133 mSlideView = (BasicSlideEditorView) findViewById(R.id.slide_editor_view); 134 mSlideView.setOnTextChangedListener(mOnTextChangedListener); 135 136 mPreSlide = (ImageButton) findViewById(R.id.pre_slide_button); 137 mPreSlide.setOnClickListener(mOnNavigateBackward); 138 139 mNextSlide = (ImageButton) findViewById(R.id.next_slide_button); 140 mNextSlide.setOnClickListener(mOnNavigateForward); 141 142 mPreview = (Button) findViewById(R.id.preview_button); 143 mPreview.setOnClickListener(mOnPreview); 144 145 mReplaceImage = (Button) findViewById(R.id.replace_image_button); 146 mReplaceImage.setOnClickListener(mOnReplaceImage); 147 148 mRemoveSlide = (Button) findViewById(R.id.remove_slide_button); 149 mRemoveSlide.setOnClickListener(mOnRemoveSlide); 150 151 mTextEditor = (EditText) findViewById(R.id.text_message); 152 mTextEditor.setFilters(new InputFilter[] { 153 new LengthFilter(MmsConfig.getMaxTextLimit())}); 154 155 mDone = (Button) findViewById(R.id.done_button); 156 mDone.setOnClickListener(mDoneClickListener); 157 158 initActivityState(savedInstanceState, getIntent()); 159 160 try { 161 mSlideshowModel = SlideshowModel.createFromMessageUri(this, mUri); 162 // Confirm that we have at least 1 slide to display 163 if (mSlideshowModel.size() == 0) { 164 Log.e(TAG, "Loaded slideshow is empty; can't edit nothingness, exiting."); 165 finish(); 166 return; 167 } 168 // Register an observer to watch whether the data model is changed. 169 mSlideshowModel.registerModelChangedObserver(mModelChangedObserver); 170 mSlideshowEditor = new SlideshowEditor(this, mSlideshowModel); 171 mPresenter = (SlideshowPresenter) PresenterFactory.getPresenter( 172 "SlideshowPresenter", this, mSlideView, mSlideshowModel); 173 174 // Sanitize mPosition 175 if (mPosition >= mSlideshowModel.size()) { 176 mPosition = Math.max(0, mSlideshowModel.size() - 1); 177 } else if (mPosition < 0) { 178 mPosition = 0; 179 } 180 181 showCurrentSlide(); 182 } catch (MmsException e) { 183 Log.e(TAG, "Create SlideshowModel failed!", e); 184 finish(); 185 return; 186 } 187 } 188 189 private void initActivityState(Bundle savedInstanceState, Intent intent) { 190 if (savedInstanceState != null) { 191 mUri = (Uri) savedInstanceState.getParcelable(MESSAGE_URI); 192 mPosition = savedInstanceState.getInt(SLIDE_INDEX, 0); 193 } else { 194 mUri = intent.getData(); 195 mPosition = intent.getIntExtra(SLIDE_INDEX, 0); 196 } 197 } 198 199 @Override 200 protected void onSaveInstanceState(Bundle outState) { 201 super.onSaveInstanceState(outState); 202 203 outState.putInt(SLIDE_INDEX, mPosition); 204 outState.putParcelable(MESSAGE_URI, mUri); 205 } 206 207 @Override 208 protected void onPause() { 209 super.onPause(); 210 211 // remove any callback to display a progress spinner 212 if (mAsyncDialog != null) { 213 mAsyncDialog.clearPendingProgressDialog(); 214 } 215 216 synchronized (this) { 217 if (mDirty) { 218 try { 219 PduBody pb = mSlideshowModel.toPduBody(); 220 PduPersister.getPduPersister(this).updateParts(mUri, pb, null); 221 mSlideshowModel.sync(pb); 222 } catch (MmsException e) { 223 Log.e(TAG, "Cannot update the message: " + mUri, e); 224 } 225 } 226 } 227 } 228 229 @Override 230 protected void onDestroy() { 231 super.onDestroy(); 232 233 if (mSlideshowModel != null) { 234 mSlideshowModel.unregisterModelChangedObserver( 235 mModelChangedObserver); 236 } 237 } 238 239 private final IModelChangedObserver mModelChangedObserver = 240 new IModelChangedObserver() { 241 public void onModelChanged(Model model, boolean dataChanged) { 242 synchronized (SlideEditorActivity.this) { 243 mDirty = true; 244 } 245 setResult(RESULT_OK); 246 } 247 }; 248 249 private final OnClickListener mOnRemoveSlide = new OnClickListener() { 250 public void onClick(View v) { 251 // Validate mPosition 252 if (mPosition >= 0 && mPosition < mSlideshowModel.size()) { 253 mSlideshowEditor.removeSlide(mPosition); 254 int size = mSlideshowModel.size(); 255 if (size > 0) { 256 if (mPosition >= size) { 257 mPosition--; 258 } 259 showCurrentSlide(); 260 } else { 261 finish(); 262 return; 263 } 264 } 265 } 266 }; 267 268 private final OnTextChangedListener mOnTextChangedListener = new OnTextChangedListener() { 269 public void onTextChanged(String s) { 270 if (!isFinishing()) { 271 mSlideshowEditor.changeText(mPosition, s); 272 } 273 } 274 }; 275 276 private final OnClickListener mOnPreview = new OnClickListener() { 277 public void onClick(View v) { 278 previewSlideshow(); 279 } 280 }; 281 282 private final OnClickListener mOnReplaceImage = new OnClickListener() { 283 public void onClick(View v) { 284 SlideModel slide = mSlideshowModel.get(mPosition); 285 if (slide != null && slide.hasVideo()) { 286 Toast.makeText(SlideEditorActivity.this, R.string.cannot_add_picture_and_video, 287 Toast.LENGTH_SHORT).show(); 288 return; 289 } 290 Intent intent = new Intent(Intent.ACTION_GET_CONTENT, null); 291 intent.setType(ContentType.IMAGE_UNSPECIFIED); 292 startActivityForResult(intent, REQUEST_CODE_CHANGE_PICTURE); 293 } 294 }; 295 296 private final OnClickListener mOnNavigateBackward = new OnClickListener() { 297 public void onClick(View v) { 298 if (mPosition > 0) { 299 mPosition --; 300 showCurrentSlide(); 301 } 302 } 303 }; 304 305 private final OnClickListener mOnNavigateForward = new OnClickListener() { 306 public void onClick(View v) { 307 if (mPosition < mSlideshowModel.size() - 1) { 308 mPosition ++; 309 showCurrentSlide(); 310 } 311 } 312 }; 313 314 private final OnClickListener mDoneClickListener = new OnClickListener() { 315 public void onClick(View v) { 316 Intent data = new Intent(); 317 data.putExtra("done", true); 318 setResult(RESULT_OK, data); 319 finish(); 320 } 321 }; 322 323 private AsyncDialog getAsyncDialog() { 324 if (mAsyncDialog == null) { 325 mAsyncDialog = new AsyncDialog(this); 326 } 327 return mAsyncDialog; 328 } 329 330 private void previewSlideshow() { 331 MessageUtils.viewMmsMessageAttachment(SlideEditorActivity.this, mUri, mSlideshowModel, 332 getAsyncDialog()); 333 } 334 335 private void updateTitle() { 336 setTitle(getString(R.string.slide_show_part, (mPosition + 1), mSlideshowModel.size())); 337 } 338 339 @Override 340 public boolean onPrepareOptionsMenu(Menu menu) { 341 if (isFinishing()) { 342 return false; 343 } 344 menu.clear(); 345 346 SlideModel slide = mSlideshowModel.get(mPosition); 347 348 if (slide == null) { 349 return false; 350 } 351 352 // Preview slideshow. 353 menu.add(0, MENU_PREVIEW_SLIDESHOW, 0, R.string.preview_slideshow).setIcon( 354 com.android.internal.R.drawable.ic_menu_play_clip); 355 356 // Text 357 if (slide.hasText() && !TextUtils.isEmpty(slide.getText().getText())) { 358 //"Change text" if text is set. 359 menu.add(0, MENU_REMOVE_TEXT, 0, R.string.remove_text).setIcon( 360 R.drawable.ic_menu_remove_text); 361 } 362 363 // Picture 364 if (slide.hasImage()) { 365 menu.add(0, MENU_DEL_PICTURE, 0, R.string.remove_picture).setIcon( 366 R.drawable.ic_menu_remove_picture); 367 } else if (!slide.hasVideo()) { 368 menu.add(0, MENU_ADD_PICTURE, 0, R.string.add_picture).setIcon( 369 R.drawable.ic_menu_picture); 370 menu.add(0, MENU_TAKE_PICTURE, 0, R.string.attach_take_photo).setIcon( 371 R.drawable.ic_menu_picture); 372 } 373 374 // Music 375 if (slide.hasAudio()) { 376 menu.add(0, MENU_DEL_AUDIO, 0, R.string.remove_music).setIcon( 377 R.drawable.ic_menu_remove_sound); 378 } else if (!slide.hasVideo()) { 379 if (MmsConfig.getAllowAttachAudio()) { 380 SubMenu subMenu = menu.addSubMenu(0, MENU_SUB_AUDIO, 0, R.string.add_music) 381 .setIcon(R.drawable.ic_menu_add_sound); 382 subMenu.add(0, MENU_ADD_AUDIO, 0, R.string.attach_sound); 383 subMenu.add(0, MENU_RECORD_SOUND, 0, R.string.attach_record_sound); 384 } else { 385 menu.add(0, MENU_RECORD_SOUND, 0, R.string.attach_record_sound) 386 .setIcon(R.drawable.ic_menu_add_sound); 387 } 388 } 389 390 // Video 391 if (slide.hasVideo()) { 392 menu.add(0, MENU_DEL_VIDEO, 0, R.string.remove_video).setIcon( 393 R.drawable.ic_menu_remove_video); 394 } else if (!slide.hasAudio() && !slide.hasImage()) { 395 menu.add(0, MENU_ADD_VIDEO, 0, R.string.add_video).setIcon(R.drawable.ic_menu_movie); 396 menu.add(0, MENU_TAKE_VIDEO, 0, R.string.attach_record_video) 397 .setIcon(R.drawable.ic_menu_movie); 398 } 399 400 // Add slide 401 menu.add(0, MENU_ADD_SLIDE, 0, R.string.add_slide).setIcon( 402 R.drawable.ic_menu_add_slide); 403 404 // Slide duration 405 String duration = getResources().getString(R.string.duration_sec); 406 menu.add(0, MENU_DURATION, 0, 407 duration.replace("%s", String.valueOf(slide.getDuration() / 1000))).setIcon( 408 R.drawable.ic_menu_duration); 409 410 // Slide layout 411 int resId; 412 if (mSlideshowModel.getLayout().getLayoutType() == LayoutModel.LAYOUT_TOP_TEXT) { 413 resId = R.string.layout_top; 414 } else { 415 resId = R.string.layout_bottom; 416 } 417 // FIXME: set correct icon when layout icon is available. 418 menu.add(0, MENU_LAYOUT, 0, resId).setIcon(R.drawable.ic_menu_picture); 419 return true; 420 } 421 422 @Override 423 public boolean onOptionsItemSelected(MenuItem item) { 424 switch (item.getItemId()) { 425 case MENU_PREVIEW_SLIDESHOW: 426 previewSlideshow(); 427 break; 428 429 case MENU_REMOVE_TEXT: 430 SlideModel slide = mSlideshowModel.get(mPosition); 431 if (slide != null) { 432 slide.removeText(); 433 } 434 break; 435 436 case MENU_ADD_PICTURE: 437 Intent intent = new Intent(Intent.ACTION_GET_CONTENT, null); 438 intent.setType(ContentType.IMAGE_UNSPECIFIED); 439 startActivityForResult(intent, REQUEST_CODE_CHANGE_PICTURE); 440 break; 441 442 case MENU_TAKE_PICTURE: 443 MessageUtils.capturePicture(this, REQUEST_CODE_TAKE_PICTURE); 444 break; 445 446 case MENU_DEL_PICTURE: 447 mSlideshowEditor.removeImage(mPosition); 448 setReplaceButtonText(R.string.add_picture); 449 break; 450 451 case MENU_ADD_AUDIO: 452 MessageUtils.selectAudio(this, REQUEST_CODE_CHANGE_MUSIC); 453 break; 454 455 case MENU_RECORD_SOUND: 456 slide = mSlideshowModel.get(mPosition); 457 int currentSlideSize = slide.getSlideSize(); 458 long sizeLimit = ComposeMessageActivity.computeAttachmentSizeLimit(mSlideshowModel, 459 currentSlideSize); 460 MessageUtils.recordSound(this, REQUEST_CODE_RECORD_SOUND, sizeLimit); 461 break; 462 463 case MENU_DEL_AUDIO: 464 mSlideshowEditor.removeAudio(mPosition); 465 break; 466 467 case MENU_ADD_VIDEO: 468 intent = new Intent(Intent.ACTION_GET_CONTENT); 469 intent.setType(ContentType.VIDEO_UNSPECIFIED); 470 intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true); 471 startActivityForResult(intent, REQUEST_CODE_CHANGE_VIDEO); 472 break; 473 474 case MENU_TAKE_VIDEO: 475 slide = mSlideshowModel.get(mPosition); 476 currentSlideSize = slide.getSlideSize(); 477 sizeLimit = ComposeMessageActivity.computeAttachmentSizeLimit(mSlideshowModel, 478 currentSlideSize); 479 if (sizeLimit > 0) { 480 MessageUtils.recordVideo(this, REQUEST_CODE_TAKE_VIDEO, sizeLimit); 481 } else { 482 Toast.makeText(this, 483 getString(R.string.message_too_big_for_video), 484 Toast.LENGTH_SHORT).show(); 485 } 486 break; 487 488 case MENU_DEL_VIDEO: 489 mSlideshowEditor.removeVideo(mPosition); 490 break; 491 492 case MENU_ADD_SLIDE: 493 mPosition++; 494 if ( mSlideshowEditor.addNewSlide(mPosition) ) { 495 // add successfully 496 showCurrentSlide(); 497 } else { 498 // move position back 499 mPosition--; 500 Toast.makeText(this, R.string.cannot_add_slide_anymore, 501 Toast.LENGTH_SHORT).show(); 502 } 503 break; 504 505 case MENU_LAYOUT: 506 showLayoutSelectorDialog(); 507 break; 508 509 case MENU_DURATION: 510 showDurationDialog(); 511 break; 512 } 513 514 return true; 515 } 516 517 private void setReplaceButtonText(int text) { 518 mReplaceImage.setText(text); 519 } 520 521 private void showDurationDialog() { 522 AlertDialog.Builder builder = new AlertDialog.Builder(this); 523 builder.setIcon(R.drawable.ic_mms_duration); 524 String title = getResources().getString(R.string.duration_selector_title); 525 builder.setTitle(title + (mPosition + 1) + "/" + mSlideshowModel.size()); 526 527 builder.setItems(R.array.select_dialog_items, 528 new DialogInterface.OnClickListener() { 529 public void onClick(DialogInterface dialog, int which) { 530 if ((which >= 0) && (which < NUM_DIRECT_DURATIONS)) { 531 mSlideshowEditor.changeDuration( 532 mPosition, (which + 1) * 1000); 533 } else { 534 Intent intent = new Intent(SlideEditorActivity.this, 535 EditSlideDurationActivity.class); 536 intent.putExtra(EditSlideDurationActivity.SLIDE_INDEX, mPosition); 537 intent.putExtra(EditSlideDurationActivity.SLIDE_TOTAL, 538 mSlideshowModel.size()); 539 intent.putExtra(EditSlideDurationActivity.SLIDE_DUR, 540 mSlideshowModel.get(mPosition).getDuration() / 1000); // in seconds 541 startActivityForResult(intent, REQUEST_CODE_CHANGE_DURATION); 542 } 543 dialog.dismiss(); 544 } 545 }); 546 547 builder.show(); 548 } 549 550 private void showLayoutSelectorDialog() { 551 AlertDialog.Builder builder = new AlertDialog.Builder(this); 552 builder.setIcon(R.drawable.ic_mms_layout); 553 554 String title = getResources().getString(R.string.layout_selector_title); 555 builder.setTitle(title + (mPosition + 1) + "/" + mSlideshowModel.size()); 556 557 LayoutSelectorAdapter adapter = new LayoutSelectorAdapter(this); 558 builder.setAdapter(adapter, new DialogInterface.OnClickListener() { 559 public void onClick(DialogInterface dialog, int which) { 560 switch (which) { 561 case 0: // Top text. 562 mSlideshowEditor.changeLayout(LayoutModel.LAYOUT_TOP_TEXT); 563 break; 564 case 1: // Bottom text. 565 mSlideshowEditor.changeLayout(LayoutModel.LAYOUT_BOTTOM_TEXT); 566 break; 567 } 568 dialog.dismiss(); 569 } 570 }); 571 572 builder.show(); 573 } 574 575 @Override 576 protected void onActivityResult(int requestCode, int resultCode, Intent data) { 577 if (resultCode != RESULT_OK) { 578 return; 579 } 580 581 switch(requestCode) { 582 case REQUEST_CODE_EDIT_TEXT: 583 // XXX where does this come from? Action is probably not the 584 // right place to have the text... 585 mSlideshowEditor.changeText(mPosition, data.getAction()); 586 break; 587 588 case REQUEST_CODE_TAKE_PICTURE: 589 Uri pictureUri = null; 590 boolean showError = false; 591 try { 592 pictureUri = TempFileProvider.renameScrapFile(".jpg", 593 Integer.toString(mPosition), this); 594 595 if (pictureUri == null) { 596 showError = true; 597 } else { 598 // Remove the old captured picture's thumbnail from the cache 599 MmsApp.getApplication().getThumbnailManager().removeThumbnail(pictureUri); 600 601 mSlideshowEditor.changeImage(mPosition, pictureUri); 602 setReplaceButtonText(R.string.replace_image); 603 } 604 } catch (MmsException e) { 605 Log.e(TAG, "add image failed", e); 606 showError = true; 607 } catch (UnsupportContentTypeException e) { 608 MessageUtils.showErrorDialog(SlideEditorActivity.this, 609 getResourcesString(R.string.unsupported_media_format, getPictureString()), 610 getResourcesString(R.string.select_different_media, getPictureString())); 611 } catch (ResolutionException e) { 612 MessageUtils.resizeImageAsync(this, pictureUri, new Handler(), 613 mResizeImageCallback, false); 614 } catch (ExceedMessageSizeException e) { 615 MessageUtils.resizeImageAsync(this, pictureUri, new Handler(), 616 mResizeImageCallback, false); 617 } 618 if (showError) { 619 notifyUser("add picture failed"); 620 Toast.makeText(SlideEditorActivity.this, 621 getResourcesString(R.string.failed_to_add_media, getPictureString()), 622 Toast.LENGTH_SHORT).show(); 623 } 624 break; 625 626 case REQUEST_CODE_CHANGE_PICTURE: 627 try { 628 mSlideshowEditor.changeImage(mPosition, data.getData()); 629 setReplaceButtonText(R.string.replace_image); 630 } catch (MmsException e) { 631 Log.e(TAG, "add image failed", e); 632 notifyUser("add picture failed"); 633 Toast.makeText(SlideEditorActivity.this, 634 getResourcesString(R.string.failed_to_add_media, getPictureString()), 635 Toast.LENGTH_SHORT).show(); 636 } catch (UnsupportContentTypeException e) { 637 MessageUtils.showErrorDialog(SlideEditorActivity.this, 638 getResourcesString(R.string.unsupported_media_format, getPictureString()), 639 getResourcesString(R.string.select_different_media, getPictureString())); 640 } catch (ResolutionException e) { 641 MessageUtils.resizeImageAsync(this, data.getData(), new Handler(), 642 mResizeImageCallback, false); 643 } catch (ExceedMessageSizeException e) { 644 MessageUtils.resizeImageAsync(this, data.getData(), new Handler(), 645 mResizeImageCallback, false); 646 } 647 break; 648 649 case REQUEST_CODE_CHANGE_MUSIC: 650 case REQUEST_CODE_RECORD_SOUND: 651 Uri uri; 652 if (requestCode == REQUEST_CODE_CHANGE_MUSIC) { 653 uri = (Uri) data.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI); 654 if (Settings.System.DEFAULT_RINGTONE_URI.equals(uri)) { 655 return; 656 } 657 } else { 658 uri = data.getData(); 659 } 660 661 try { 662 mSlideshowEditor.changeAudio(mPosition, uri); 663 } catch (MmsException e) { 664 Log.e(TAG, "add audio failed", e); 665 notifyUser("add music failed"); 666 Toast.makeText(SlideEditorActivity.this, 667 getResourcesString(R.string.failed_to_add_media, getAudioString()), 668 Toast.LENGTH_SHORT).show(); 669 } catch (UnsupportContentTypeException e) { 670 MessageUtils.showErrorDialog(SlideEditorActivity.this, 671 getResourcesString(R.string.unsupported_media_format, getAudioString()), 672 getResourcesString(R.string.select_different_media, getAudioString())); 673 } catch (ExceedMessageSizeException e) { 674 MessageUtils.showErrorDialog(SlideEditorActivity.this, 675 getResourcesString(R.string.exceed_message_size_limitation), 676 getResourcesString(R.string.failed_to_add_media, getAudioString())); 677 } 678 break; 679 680 case REQUEST_CODE_TAKE_VIDEO: 681 try { 682 Uri videoUri = TempFileProvider.renameScrapFile(".3gp", 683 Integer.toString(mPosition), this); 684 685 mSlideshowEditor.changeVideo(mPosition, videoUri); 686 } catch (MmsException e) { 687 notifyUser("add video failed"); 688 Toast.makeText(SlideEditorActivity.this, 689 getResourcesString(R.string.failed_to_add_media, getVideoString()), 690 Toast.LENGTH_SHORT).show(); 691 } catch (UnsupportContentTypeException e) { 692 MessageUtils.showErrorDialog(SlideEditorActivity.this, 693 getResourcesString(R.string.unsupported_media_format, getVideoString()), 694 getResourcesString(R.string.select_different_media, getVideoString())); 695 } catch (ExceedMessageSizeException e) { 696 MessageUtils.showErrorDialog(SlideEditorActivity.this, 697 getResourcesString(R.string.exceed_message_size_limitation), 698 getResourcesString(R.string.failed_to_add_media, getVideoString())); 699 } 700 break; 701 702 case REQUEST_CODE_CHANGE_VIDEO: 703 try { 704 mSlideshowEditor.changeVideo(mPosition, data.getData()); 705 } catch (MmsException e) { 706 Log.e(TAG, "add video failed", e); 707 notifyUser("add video failed"); 708 Toast.makeText(SlideEditorActivity.this, 709 getResourcesString(R.string.failed_to_add_media, getVideoString()), 710 Toast.LENGTH_SHORT).show(); 711 } catch (UnsupportContentTypeException e) { 712 MessageUtils.showErrorDialog(SlideEditorActivity.this, 713 getResourcesString(R.string.unsupported_media_format, getVideoString()), 714 getResourcesString(R.string.select_different_media, getVideoString())); 715 } catch (ExceedMessageSizeException e) { 716 MessageUtils.showErrorDialog(SlideEditorActivity.this, 717 getResourcesString(R.string.exceed_message_size_limitation), 718 getResourcesString(R.string.failed_to_add_media, getVideoString())); 719 } 720 break; 721 722 case REQUEST_CODE_CHANGE_DURATION: 723 mSlideshowEditor.changeDuration(mPosition, 724 Integer.valueOf(data.getAction()) * 1000); 725 break; 726 } 727 } 728 729 private final ResizeImageResultCallback mResizeImageCallback = new ResizeImageResultCallback() { 730 public void onResizeResult(PduPart part, boolean append) { 731 Context context = SlideEditorActivity.this; 732 if (part == null) { 733 Toast.makeText(SlideEditorActivity.this, 734 getResourcesString(R.string.failed_to_add_media, getPictureString()), 735 Toast.LENGTH_SHORT).show(); 736 return; 737 } 738 739 try { 740 long messageId = ContentUris.parseId(mUri); 741 PduPersister persister = PduPersister.getPduPersister(context); 742 Uri newUri = persister.persistPart(part, messageId, null); 743 mSlideshowEditor.changeImage(mPosition, newUri); 744 745 setReplaceButtonText(R.string.replace_image); 746 } catch (MmsException e) { 747 notifyUser("add picture failed"); 748 Toast.makeText(SlideEditorActivity.this, 749 getResourcesString(R.string.failed_to_add_media, getPictureString()), 750 Toast.LENGTH_SHORT).show(); 751 } catch (UnsupportContentTypeException e) { 752 MessageUtils.showErrorDialog(SlideEditorActivity.this, 753 getResourcesString(R.string.unsupported_media_format, getPictureString()), 754 getResourcesString(R.string.select_different_media, getPictureString())); 755 } catch (ResolutionException e) { 756 MessageUtils.showErrorDialog(SlideEditorActivity.this, 757 getResourcesString(R.string.failed_to_resize_image), 758 getResourcesString(R.string.resize_image_error_information)); 759 } catch (ExceedMessageSizeException e) { 760 MessageUtils.showErrorDialog(SlideEditorActivity.this, 761 getResourcesString(R.string.exceed_message_size_limitation), 762 getResourcesString(R.string.failed_to_add_media, getPictureString())); 763 } 764 } 765 }; 766 767 private String getResourcesString(int id, String mediaName) { 768 Resources r = getResources(); 769 return r.getString(id, mediaName); 770 } 771 772 private String getResourcesString(int id) { 773 Resources r = getResources(); 774 return r.getString(id); 775 } 776 777 private String getAudioString() { 778 return getResourcesString(R.string.type_audio); 779 } 780 781 private String getPictureString() { 782 return getResourcesString(R.string.type_picture); 783 } 784 785 private String getVideoString() { 786 return getResourcesString(R.string.type_video); 787 } 788 789 private void notifyUser(String message) { 790 if (LOCAL_LOGV) { 791 Log.v(TAG, "notifyUser: message=" + message); 792 } 793 } 794 795 private void showCurrentSlide() { 796 mPresenter.setLocation(mPosition); 797 mPresenter.present(null); 798 updateTitle(); 799 800 if (mSlideshowModel.get(mPosition).hasImage()) { 801 setReplaceButtonText(R.string.replace_image); 802 } else { 803 setReplaceButtonText(R.string.add_picture); 804 } 805 } 806 } 807