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