• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
onCreate(Bundle savedInstanceState)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 
initActivityState(Bundle savedInstanceState, Intent intent)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
onSaveInstanceState(Bundle outState)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
onPause()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
onDestroy()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 
getAsyncDialog()327     private AsyncDialog getAsyncDialog() {
328         if (mAsyncDialog == null) {
329             mAsyncDialog = new AsyncDialog(this);
330         }
331         return mAsyncDialog;
332     }
333 
previewSlideshow()334     private void previewSlideshow() {
335         MessageUtils.viewMmsMessageAttachment(SlideEditorActivity.this, mUri, mSlideshowModel,
336                 getAsyncDialog());
337     }
338 
updateTitle()339     private void updateTitle() {
340         setTitle(getString(R.string.slide_show_part, (mPosition + 1), mSlideshowModel.size()));
341     }
342 
343     @Override
onPrepareOptionsMenu(Menu menu)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
onOptionsItemSelected(MenuItem item)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 
setReplaceButtonText(int text)521     private void setReplaceButtonText(int text) {
522         mReplaceImage.setText(text);
523     }
524 
showDurationDialog()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 
showLayoutSelectorDialog()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
onActivityResult(int requestCode, int resultCode, Intent data)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 
getResourcesString(int id, String mediaName)771     private String getResourcesString(int id, String mediaName) {
772         Resources r = getResources();
773         return r.getString(id, mediaName);
774     }
775 
getResourcesString(int id)776     private String getResourcesString(int id) {
777         Resources r = getResources();
778         return r.getString(id);
779     }
780 
getAudioString()781     private String getAudioString() {
782         return getResourcesString(R.string.type_audio);
783     }
784 
getPictureString()785     private String getPictureString() {
786         return getResourcesString(R.string.type_picture);
787     }
788 
getVideoString()789     private String getVideoString() {
790         return getResourcesString(R.string.type_video);
791     }
792 
notifyUser(String message)793     private void notifyUser(String message) {
794         if (LOCAL_LOGV) {
795             Log.v(TAG, "notifyUser: message=" + message);
796         }
797     }
798 
showCurrentSlide()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