这篇文章主要介绍了 Android 实现彩信附件的添加与删除功能, 涉及 Android 针对常见多媒体文件的操作技巧, 具有一定参考借鉴价值, 需要的朋友可以参考下
Android 是一种基于 Linux 的自由及开放源代码的操作系统,主要使用于移动设备,如智能手机和平板电脑,由 Google 公司和开放手机联盟领导及开发。尚未有统一中文名称,中国大陆地区较多人使用 "安卓" 或 "安致"。
本文实例讲述了 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 type
- Intent 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 程序设计有所帮助。
来源: http://www.phperz.com/article/17/0324/238069.html