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