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