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