Android實現多媒體訊息附件的添加與刪除功能_Android

來源:互聯網
上載者:User

本文執行個體講述了Android實現多媒體訊息附件的添加與刪除功能。分享給大家供大家參考,具體如下:

添加附件

在ComposeMessageActivity裡

addAttachment(int type) 函數

根據type的不同,分成6個case

case A:

MediaSelectListActivity.ADD_IMAGE 用gallery選圖片:

MessageUtils.selectImage(this, REQUEST_CODE_ATTACH_IMAGE);

起一個intent:

Intent innerIntent = new Intent(Intent.ACTION_GET_CONTENT);innerIntent.setType(contentType); //image typeIntent wrapperIntent = Intent.createChooser(innerIntent, null);startActivityForResult(wrapperIntent,requestCode);

createChooser 函數new 一個 Intent intent = new Intent(ACTION_CHOOSER);

也就是起來一個ACTION_CHOOSER的 activity

case B:

MediaSelectListActivity.TAKE_PICTURE

Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);intent.putExtra(MediaStore.EXTRA_OUTPUT, Mms.ScrapSpace.CONTENT_URI);startActivityForResult(intent, REQUEST_CODE_TAKE_PICTURE);

起一個照相機來拍照了,

case C:

MediaSelectListActivity.ADD_VIDEO

很像case A

只有在type那裡,從image換成video

case D:

MediaSelectListActivity.RECORD_VIDEO

和case B一樣起一個錄影機,不過這次有空間大小計算:給文本留1024Byte。

按一條多媒體訊息300k算,錄影最多使用299k。也即299*1024byte

Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);startActivityForResult(intent, REQUEST_CODE_TAKE_VIDEO);

case E:

MediaSelectListActivity.ADD_SOUND

MessageUtils.selectAudio(this, REQUEST_CODE_ATTACH_SOUND);Intent intent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);

case F:

MediaSelectListActivity.RECORD_SOUND

像B那樣,七個錄音機。 這次type是aution

Intent intent = new Intent(Intent.ACTION_GET_CONTENT);intent.setType(ContentType.AUDIO_AMR);intent.setClassName("com.android.soundrecorder", "com.android.soundrecorder.SoundRecorder");

case G:

MediaSelectListActivity.ADD_SLIDESHOW

投影片slideshow比較尷尬。因為整個多媒體訊息附件也叫slideshow,而這裡的slideshow是多張圖片拼湊在一起的意思。多媒體訊息的附件也經常是若干張圖片。。。 這裡從起名開始就繞的要死了。

Uri dataUri = mWorkingMessage.saveAsMms(false);Intent intent = new Intent(this, SlideshowEditActivity.class);intent.setData(dataUri);startActivityForResult(intent, REQUEST_CODE_CREATE_SLIDESHOW);

saveAsMms函數裡面有幾個事情:首先把簡訊強制變成多媒體訊息,把簡訊的內容封裝到PduPersister中(可以理解為多媒體訊息body)去,new一個SendReq也就是多媒體訊息頭。產生包含多媒體訊息頭和body的uri。
最後起一個尷尬的SlideshowEditActivity。 這個東西太麻煩。不看。。

然後是到了onActivityResult函數。 那些從外面的activity讀取媒體資料的應用返回的時候都回到這裡。

A。圖片

圖片在onActivityReuslt會得到uri,調用:

addImage(uri, false);

這個函數會調用:

複製代碼 代碼如下:
mWorkingMessage.setAttachment(WorkingMessage.IMAGE, uri, false);

也就是非append模式添加圖片。

如果圖片太大,會啟用非同步圖片壓縮函數。

B 拍照片

也是返回一個uri到onActivityReuslt函數。也是調用 addImage(uri, false),同上。

C 選錄影檔案 D 拍錄影

都是調用:

addVideo(data.getData(), false);

data.getData()也是得到uri,addVideo調用:

複製代碼 代碼如下:
mWorkingMessage.setAttachment(WorkingMessage.VIDEO, uri, append);

跟圖片處理一樣的。

E 選錄音檔案 F 錄音

都是addAudio -->
mWorkingMessage.setAttachment(WorkingMessage.AUDIO, uri, false);
不多說

刪除附件

AttachmentEditor裡面有個handler,用來給composeMessageActivity傳訊息。

所有刪除附件操作的按鈕都在AttachmentEditor上。對不同的媒體類型有不同的按鈕,但是按下之後出口是一樣的:

Message msg = Message.obtain(mHandler, MSG_REMOVE_ATTACHMENT);msg.sendToTarget();

就是這麼個操作。

之所以一樣是因為所有的附近都存在SlideshowModel裡,而這個SlideshowModel是:

ArrayList<SlideModel> mSlides; 一列兒slide組成的。

每個slide可以包含video,image,audio,text, 其中前三者一般不能兩兩同時存在,唯一的例外是image和audio。

(其實我覺得如果,如果每個slide只能包含三者中的一種,即不處理上面那個例外,邏輯可能更清晰)
說回到那個remove操作。。

composeMessageActivity的Handler裡的handleMessage函數,接到這個刪除msg之後的操作是:

mWorkingMessage.setAttachment(WorkingMessage.TEXT, null, false);

最後一位false表示非append模式,即從新修改附件。

mWorkingMessage是什麼呢?

是簡訊(包括多媒體訊息)的所有的狀態所有操作所有資料的現狀,主要有幾個成員:

mMmsState 多媒體訊息狀態,是不是多媒體訊息,為啥是多媒體訊息,是有附件有標題,或者強制多媒體訊息等

mAttachmentType 附件類型。如果mSlideshow是多頁:slide類型。 單頁:圖片|聲音|錄影|文本。   如果mSlideshow是空,就是文本類型。

mSlideshow 附件資料數組。就是那個ArrayList<SlideModel> mSlides。

現在回頭看那個刪除操作。

setAttachment裡面最主要的函數是changeMedia(type, dataUri),這裡傳入的參數type是TEXT,dataUri是null。
這個函數進去:

SlideModel slide = mSlideshow.get(0);MediaModel media;// Remove any previous attachments.slide.removeImage();slide.removeVideo();slide.removeAudio();// If we're changing to text, just bail out.if (type == TEXT) {  return;}// Make a correct MediaModel for the type of attachment.if (type == IMAGE) {  media = new ImageModel(mContext, uri, mSlideshow.getLayout()      .getImageRegion());} else if (type == VIDEO) {  media = new VideoModel(mContext, uri, mSlideshow.getLayout()      .getImageRegion());} else if (type == AUDIO) {  media = new AudioModel(mContext, uri);} else {  throw new IllegalArgumentException("changeMedia type=" + type      + ", uri=" + uri);}// Add it to the slide.slide.add(media);// For video and audio, set the duration of the slide to// that of the attachment.if (type == VIDEO || type == AUDIO) {  slide.updateDuration(media.getDuration());}

看到第一個return我們就可以return了。。

多乾淨利落!直接把多媒體訊息原來的附件看都不堪直接一刀刪完,類型迴歸到WorkingMessage.TEXT,把uri置空。

另外,說一些題外的。

這個changeMedia函數,來來回回,都是改的mSlideshow.get(0)那個

在setAttachment的時候,如果是用的append模式,到時候就會用appendMedia而不是changeMedia函數。

對於append模式,

如果最後一頁包含了圖片image或者錄影vedio, 那麼append的時候必須加到下一張。

感覺源碼裡這個判斷有點寫複雜了。。你看我一句話就能歸納出來的,他代碼寫半天~

不過我寫不出更好的~~

還有SlideModel的add函數。 很多情況疊在一起了,所以有點複雜。

添加的關鍵函數是下面這個,第一個參數是對應格式的原來媒體(比如你想添加錄影,那這個就是原來的錄影,可以是null),第二個是添加的新媒體

private void internalAddOrReplace(MediaModel old, MediaModel media) {  int addSize = media.getMediaSize();  int removeSize;  if (old == null) {    if (null != mParent) {      mParent.checkMessageSize(addSize);    }    mMedia.add(media);    increaseSlideSize(addSize);    increaseMessageSize(addSize);  } else {    removeSize = old.getMediaSize();    if (addSize > removeSize) {      if (null != mParent) {        mParent.checkMessageSize(addSize - removeSize);      }      increaseSlideSize(addSize - removeSize);      increaseMessageSize(addSize - removeSize);    } else {      decreaseSlideSize(removeSize - addSize);      decreaseMessageSize(removeSize - addSize);    }    mMedia.set(mMedia.indexOf(old), media);    old.unregisterAllModelChangedObservers();  }  for (IModelChangedObserver observer : mModelChangedObservers) {    media.registerModelChangedObserver(observer);  }}

還有個附件太大時的非同步縮小功能,是下面這個函數

public static void resizeImageAsync(final Context context,     final Uri imageUri, final Handler handler,     final ResizeImageResultCallback cb, final boolean append) {   // Show a progress toast if the resize hasn't finished   // within one second.   // Stash the runnable for showing it away so we can cancel   // it later if the resize completes ahead of the deadline.   final Runnable showProgress = new Runnable() {     public void run() {       Toast.makeText(context, R.string.compressing,           Toast.LENGTH_SHORT).show();     }   };   // Schedule it for one second from now.   handler.postDelayed(showProgress, 1000);   new Thread(new Runnable() {     public void run() {       final PduPart part;       try {         UriImage image = new UriImage(context, imageUri);         part = image.getResizedImageAsPart(MmsConfig             .getMaxImageWidth(), MmsConfig.getMaxImageHeight(),             MmsConfig.getMaxMessageSize() - MESSAGE_OVERHEAD);       } finally {         // Cancel pending show of the progress toast if necessary.         handler.removeCallbacks(showProgress);       }       handler.post(new Runnable() {         public void run() {           cb.onResizeResult(part, append);         }       });     }   }).start();}

圖片被縮放到最大640*480,如果還是大於300*1024-5000位元組(差不多295k),那麼縮放到295k。

這個大小是源碼編寫程式員憑感覺寫死的。

這裡的cb.onResizeResult是調用的ComposeMessageActivity的ResizeImageResultCallback裡的函數。

處理大小結束後,會拿新的圖片去再次setAttachment,也就更新了附件。

更多關於Android相關內容感興趣的讀者可查看本站專題:《Android資料庫操作技巧總結》、《Android編程之activity操作技巧總結》、《Android檔案操作技巧匯總》、《Android編程開發之SD卡操作方法匯總》、《Android開發入門與進階教程》、《Android資源操作技巧匯總》、《Android視圖View技巧總結》及《Android控制項用法總結》

希望本文所述對大家Android程式設計有所協助。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.