android 短信添加附件

来源:互联网 发布:德哈维兰 知乎 编辑:程序博客网 时间:2024/06/04 18:35
添加附件。 

在ComposeMessageActivity里 

addAttachment(int type) 函数 

根据type的不同,分成6个case 

case A: 
MediaSelectListActivity.ADD_IMAGE 用gallery选图片: 

MessageUtils.selectImage(this, REQUEST_CODE_ATTACH_IMAGE); 

起一个intent:
  1. view plaincopy to clipboardprint?
  2. Intent innerIntent = new Intent(Intent.ACTION_GET_CONTENT);    
  3. innerIntent.setType(contentType); //image type    
  4. Intent wrapperIntent = Intent.createChooser(innerIntent, null);    
  5. startActivityForResult(wrapperIntent,requestCode);   
复制代码

createChooser 函数new 一个 Intent intent = new Intent(ACTION_CHOOSER); 
也就是起来一个ACTION_CHOOSER的 activity 

case B: 
MediaSelectListActivity.TAKE_PICTURE
  1. view plaincopy to clipboardprint?
  2. Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);    
  3.             intent    
  4.                     .putExtra(MediaStore.EXTRA_OUTPUT,    
  5.                             Mms.ScrapSpace.CONTENT_URI);    
  6.             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
  1. view plaincopy to clipboardprint?
  2. Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);    
  3. startActivityForResult(intent, REQUEST_CODE_TAKE_VIDEO);  
复制代码
case E: 
MediaSelectListActivity.ADD_SOUND
  1. view plaincopy to clipboardprint?
  2. MessageUtils.selectAudio(this, REQUEST_CODE_ATTACH_SOUND);    
  3. Intent intent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);   
复制代码
case F: 
MediaSelectListActivity.RECORD_SOUND 
像B那样,七个录音机。 这次type是aution
  1. view plaincopy to clipboardprint?
  2. Intent intent = new Intent(Intent.ACTION_GET_CONTENT);    
  3. intent.setType(ContentType.AUDIO_AMR);    
  4. intent.setClassName("com.android.soundrecorder",    
  5.                     "com.android.soundrecorder.SoundRecorder");
复制代码
case G: 
MediaSelectListActivity.ADD_SLIDESHOW 
幻灯片slideshow比较尴尬。因为整个彩信附件也叫slideshow,而这里的slideshow是多张图片拼凑在一起的意思。彩信的附件也经常是若干张图片。。。 这里从起名开始就绕的要死了。
  1. view plaincopy to clipboardprint?
  2. Uri dataUri = mWorkingMessage.saveAsMms(false);    
  3.         Intent intent = new Intent(this, SlideshowEditActivity.class);    
  4.         intent.setData(dataUri);    
  5.         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上。对不同的媒体类型有不同的按钮,但是按下之后出口是一样的:
  1. view plaincopy to clipboardprint?
  2. Message msg = Message.obtain(mHandler, MSG_REMOVE_ATTACHMENT);    
  3.                 msg.sendToTarget();   
复制代码
就是这么个操作。 
之所以一样是因为所有的附近都存在SlideshowModel里,而这个SlideshowModel是: 
ArrayList<SlideModel> mSlides; 一列儿slide组成的。 
每个slide可以包含video,image,audio,text, 其中前三者一般不能两两同时存在,唯一的例外是image和audio。 
(其实我觉得如果,如果每个slide只能包含三者中的一种,即不处理上面那个例外,逻辑可能更清晰) 
说回到那个remove操作。。 
composeMessageActivity的Handler里的handleMessage函数,接到这个删除msg之后的操作是: 


  1. view plaincopy to clipboardprint?
  2. 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。 
这个函数进去:
  1. view plaincopy to clipboardprint?
  2. SlideModel slide = mSlideshow.get(0);    
  3.         MediaModel media;    
  4.     
  5.         // Remove any previous attachments.    
  6.         slide.removeImage();    
  7.         slide.removeVideo();    
  8.         slide.removeAudio();    
  9.     
  10.         // If we're changing to text, just bail out.    
  11.         if (type == TEXT) {    
  12.             return;    
  13.         }    
  14.     
  15.         // Make a correct MediaModel for the type of attachment.    
  16.         if (type == IMAGE) {    
  17.             media = new ImageModel(mContext, uri, mSlideshow.getLayout()    
  18.                     .getImageRegion());    
  19.         } else if (type == VIDEO) {    
  20.             media = new VideoModel(mContext, uri, mSlideshow.getLayout()    
  21.                     .getImageRegion());    
  22.         } else if (type == AUDIO) {    
  23.             media = new AudioModel(mContext, uri);    
  24.         } else {    
  25.             throw new IllegalArgumentException("changeMedia type=" + type    
  26.                     + ", uri=" + uri);    
  27.         }    
  28.         // Add it to the slide.    
  29.         slide.add(media);    
  30.     
  31.         // For video and audio, set the duration of the slide to    
  32.         // that of the attachment.    
  33.         if (type == VIDEO || type == AUDIO) {    
  34.             slide.updateDuration(media.getDuration());    
  35.         }   
复制代码
看到第一个return我们就可以return了。。 
多干净利落!直接把彩信原来的附件看都不堪直接一刀删完,类型回归到WorkingMessage.TEXT,把uri置空。 

另外,说一些题外的。 
这个changeMedia函数,来来回回,都是改的mSlideshow.get(0)那个 
在setAttachment的时候,如果是用的append模式,到时候就会用appendMedia而不是changeMedia函数。 

对于append模式, 
如果最后一页包含了图片image或者录像vedio, 那么append的时候必须加到下一张。 
感觉源码里这个判断有点写复杂了。。你看我一句话就能归纳出来的,他代码写半天~ 
不过我写不出更好的~~ 

还有SlideModel的add函数。 很多情况叠在一起了,所以有点复杂。 

添加的关键函数是下面这个,第一个参数是对应格式的原来媒体(比如你想添加录像,那这个就是原来的录像,可以是null),第二个是添加的新媒体
  1. view plaincopy to clipboardprint?
  2. private void internalAddOrReplace(MediaModel old, MediaModel media) {    
  3.     int addSize = media.getMediaSize();    
  4.     int removeSize;    
  5.     if (old == null) {    
  6.         if (null != mParent) {    
  7.             mParent.checkMessageSize(addSize);    
  8.         }    
  9.         mMedia.add(media);    
  10.         increaseSlideSize(addSize);    
  11.         increaseMessageSize(addSize);    
  12.     } else {    
  13.         removeSize = old.getMediaSize();    
  14.         if (addSize > removeSize) {    
  15.             if (null != mParent) {    
  16.                 mParent.checkMessageSize(addSize - removeSize);    
  17.             }    
  18.             increaseSlideSize(addSize - removeSize);    
  19.             increaseMessageSize(addSize - removeSize);    
  20.         } else {    
  21.             decreaseSlideSize(removeSize - addSize);    
  22.             decreaseMessageSize(removeSize - addSize);    
  23.         }    
  24.         mMedia.set(mMedia.indexOf(old), media);    
  25.         old.unregisterAllModelChangedObservers();    
  26.     }    
  27.     
  28.     for (IModelChangedObserver observer : mModelChangedObservers) {    
  29.         media.registerModelChangedObserver(observer);    
  30.     }    
  31. }    
复制代码
还有个附件太大时的异步缩小功能,是下面这个函数
  1. view plaincopy to clipboardprint?
  2. public static void resizeImageAsync(final Context context,    
  3.          final Uri imageUri, final Handler handler,    
  4.          final ResizeImageResultCallback cb, final boolean append) {    
  5.     
  6.      // Show a progress toast if the resize hasn't finished    
  7.      // within one second.    
  8.      // Stash the runnable for showing it away so we can cancel    
  9.      // it later if the resize completes ahead of the deadline.    
  10.      final Runnable showProgress = new Runnable() {    
  11.          public void run() {    
  12.              Toast.makeText(context, R.string.compressing,    
  13.                      Toast.LENGTH_SHORT).show();    
  14.          }    
  15.      };    
  16.      // Schedule it for one second from now.    
  17.      handler.postDelayed(showProgress, 1000);    
  18.     
  19.      new Thread(new Runnable() {    
  20.          public void run() {    
  21.              final PduPart part;    
  22.              try {    
  23.                  UriImage image = new UriImage(context, imageUri);    
  24.                  part = image.getResizedImageAsPart(MmsConfig    
  25.                          .getMaxImageWidth(), MmsConfig.getMaxImageHeight(),    
  26.                          MmsConfig.getMaxMessageSize() - MESSAGE_OVERHEAD);    
  27.              } finally {    
  28.                  // Cancel pending show of the progress toast if necessary.    
  29.                  handler.removeCallbacks(showProgress);    
  30.              }    
  31.     
  32.              handler.post(new Runnable() {    
  33.                  public void run() {    
  34.                      cb.onResizeResult(part, append);    
  35.                  }    
  36.              });    
  37.          }    
  38.      }).start();    
  39. }    
复制代码
图片被缩放到最大640*480,如果还是大于300*1024-5000字节(差不多295k),那么缩放到295k。 
这个大小是源码编写程序员凭感觉写死的。 
这里的cb.onResizeResult是调用的ComposeMessageActivity的ResizeImageResultCallback里的函数。 
处理大小结束后,会拿新的图片去再次setAttachment, 
也就更新了附件
0 0
原创粉丝点击