热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Android实现彩信附件的添加与删除功能

Android实现彩信附件的添加与删除功能-本文实例讲述了Android实现彩信附件的添加与删除功能。分享给大家供大家参考,具体如下:添加附件在ComposeMessageActi

本文实例讲述了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);

这个函数会调用:

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

如果图片太大,会启用异步的图片压缩函数。

B 拍照片

也是返回一个uri到onActivityReuslt函数。也是调用 addImage(uri, false),同上。

C 选录像文件 D 拍录像

都是调用:

addVideo(data.getData(), false);

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


跟图片处理一样的。

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 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 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程序设计有所帮助。


推荐阅读
  • 本文详细探讨了JDBC(Java数据库连接)的内部机制,重点分析其作为服务提供者接口(SPI)框架的应用。通过类图和代码示例,展示了JDBC如何注册驱动程序、建立数据库连接以及执行SQL查询的过程。 ... [详细]
  • 基于KVM的SRIOV直通配置及性能测试
    SRIOV介绍、VF直通配置,以及包转发率性能测试小慢哥的原创文章,欢迎转载目录?1.SRIOV介绍?2.环境说明?3.开启SRIOV?4.生成VF?5.VF ... [详细]
  • PHP 过滤器详解
    本文深入探讨了 PHP 中的过滤器机制,包括常见的 $_SERVER 变量、filter_has_var() 函数、filter_id() 函数、filter_input() 函数及其数组形式、filter_list() 函数以及 filter_var() 和其数组形式。同时,详细介绍了各种过滤器的用途和用法。 ... [详细]
  • 本文详细介绍了如何通过RPM包在Linux系统(如CentOS)上安装MySQL 5.6。涵盖了检查现有安装、下载和安装RPM包、配置MySQL以及设置远程访问和开机自启动等步骤。 ... [详细]
  • 毕业设计:基于机器学习与深度学习的垃圾邮件(短信)分类算法实现
    本文详细介绍了如何使用机器学习和深度学习技术对垃圾邮件和短信进行分类。内容涵盖从数据集介绍、预处理、特征提取到模型训练与评估的完整流程,并提供了具体的代码示例和实验结果。 ... [详细]
  • 本文详细介绍如何在VSCode中配置自定义代码片段,使其具备与IDEA相似的代码生成快捷键功能。通过具体的Java和HTML代码片段示例,展示配置步骤及效果。 ... [详细]
  • dotnet 通过 Elmish.WPF 使用 F# 编写 WPF 应用
    本文来安利大家一个有趣而且强大的库,通过F#和C#混合编程编写WPF应用,可以在WPF中使用到F#强大的数据处理能力在GitHub上完全开源Elmis ... [详细]
  • 本文探讨了在Java中实现系统托盘最小化的两种方法:使用SWT库和JDK6自带的功能。通过这两种方式,开发者可以创建跨平台的应用程序,使窗口能够最小化到系统托盘,并提供丰富的交互功能。 ... [详细]
  • 本文介绍如何使用布局文件在Android应用中排列多行TextView和Button,使其占据屏幕的特定比例,并提供示例代码以帮助理解和实现。 ... [详细]
  • 通过Web界面管理Linux日志的解决方案
    本指南介绍了一种利用rsyslog、MariaDB和LogAnalyzer搭建集中式日志管理平台的方法,使用户可以通过Web界面查看和分析Linux系统的日志记录。此方案不仅适用于服务器环境,还提供了详细的步骤来确保系统的稳定性和安全性。 ... [详细]
  • 本文介绍如何在SQL Server中对Name列进行排序,使特定值(如Default Deliverable Submission Notification)显示在结果集的顶部。 ... [详细]
  • 本文深入探讨了HTTP请求和响应对象的使用,详细介绍了如何通过响应对象向客户端发送数据、处理中文乱码问题以及常见的HTTP状态码。此外,还涵盖了文件下载、请求重定向、请求转发等高级功能。 ... [详细]
  • 本文将详细探讨Linux pinctrl子系统的各个关键数据结构,帮助读者深入了解其内部机制。通过分析这些数据结构及其相互关系,我们将进一步理解pinctrl子系统的工作原理和设计思路。 ... [详细]
  • 本文介绍了一种在 MySQL 客户端执行 NOW() 函数时出现时间偏差的问题,并详细描述了如何通过配置文件调整时区设置来解决该问题。演示场景中,假设当前北京时间为2023年2月17日19:31:37,而查询结果显示的时间比实际时间晚8小时。 ... [详细]
  • 本文详细介绍了 org.apache.commons.io.IOCase 类中的 checkCompareTo() 方法,通过多个代码示例展示其在不同场景下的使用方法。 ... [详细]
author-avatar
丁扣其
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有