一、背景
Android自带的MMS应用,无论是短信和彩信都显得单调,使用起来比较麻烦,可扩展性不好。MMS应用实际上不支持非媒体附件,所有的附件都必须是可以呈现的媒体文件。
做过feature phone的兄弟应该知道,一般彩信都会有个附件列表功能。在slide中显示的图片或者文字,需要具备“播放”属性。而附件列表中的附件,是追加的,不参与“播放”类似与电子邮件中的附件。而android自带的MMS应用,根本就不支持。
二、可行性
了解可行性,就要先看看协议是怎么规定的。可以参考我的博客的另外一篇文章。
Android mms framework 提供的接口,经过验证,在打包彩信附件,接收解析时候,是不区分文件类型的。这个是很好的信号,即告诉我们,在打包的时候,想方设法把vcard附件和vcalendar附件的路径传进去,这样能打包、发送和解析,UI上面的东西,解析或者适配无非是忽悠忽悠。
三、 解决方案简要描述
我下面描述两种解决方案。
一是参考feature phone,在信息编辑界面加入一个附件列表,可以在附件列表添加很多种类的附件。这样做的优点是功能比较全,比较符合实际情况,缺点是会有很大的UI调整。二是参考HTC和华为手机做的,只添加一次vcard或者vcalendar,然后显示在图片,声音等的预览域;如果添加了可播放的媒体,则不能添加这些附件。这样做的优点是UI调整很少,缺点是功能被砍了不少。
以下介绍第二种方案。
在信息编辑界面加入一个菜单,用于插入vcard。插入后切成彩信,显示在预览域。如果插入了slides或者其他媒体,则不能使用这个菜单。
预览时候显示的图标是小名片,有两个按钮,一个是查看,第二个是删除。删除后切成短信。
在conversation中,判断是否是仅有vcard的彩信,如果是,则显示个小名片图标。其他情况都按照默认显示。
在conversation中,判断是否是仅有Vcard的彩信,如果是,则加入一个菜单,查看vcard详情。
保存接收的彩信,可以支持保存vcard。
四、 设计参考
1、 添加一个OtherAttachmodel类,用于处理非媒体附件。这个类包含附件的Uri,附件的文件名,附件的大小,附件类型,以及上下文等属性。其中Uri和类型是必要属性。
2、在SlideShowModel里面添加一个成员private final ArrayList
3、Slideshowmodel里面增加接口:
public boolean hasOtherAttachModel();
public void addOtherAttachModel(OtherAttachModel object){
if(object == null){
return;
}
mOtherAttachModels.add(object);
increaseMessageSize(object.getAttachSize());
}
private static void initOtherAttach (Context context, PduBody pb, SlideshowModel slideshow){
if (pb == null ||slideshow ==null) {
return;
}
int partNum = pb.getPartsNum();
for(int i = 0; i < partNum; i++) {
PduPart part = pb.getPart(i);
String type = new String(part.getContentType());
if ( !ContentType.isImageType(type) && !ContentType.isVideoType(type)
&& !ContentType.isAudioType(type) && !type.startsWith("application/")
&& !type.equals(ContentType.TEXT_PLAIN)) {
//String Location = new String(part.getContentLocation());
Uri uri = part.getDataUri();
OtherAttachModel model = new OtherAttachModel(context, type, uri, slideshow);
slideshow.addOtherAttachModel(model);
}
}
}
public void removOtherAttach(){
for(OtherAttachModel model : mOtherAttachModels){
decreaseMessageSize(model.getAttachSize());
}
mOtherAttachModels.clear();
}
public boolean oneVcard();
public boolean oneVcalendar();
其中initOtherAttach()是在createFromPduBody时候调用的,在创建完slideshowmodel之后,即调用该函数,初始化其他附件。
4、在发送打包,通过在makepdubod()里面添加代码,来实现打包其他类型附件。
for( OtherAttachModel attachmodel : mOtherAttachModels){
String location;
int index;
String contentId;
PduPart part = new PduPart();
part.setContentType(attachmodel.getContentType().getBytes());
location = attachmodel.getContentLocation();
part.setContentLocation(location.getBytes());
index = location.lastIndexOf(".");
contentId = (index == -1) ? location
: location.substring(0, index);
part.setContentId(contentId.getBytes());
part.setDataUri(attachmodel.getUri());
pb.addPart(part);
}
5、注意,在保存附加到数据库之后,sync()会被调用,这个函数是更新Model里面保存的路径的。需要加
for( OtherAttachModel attachmodel : mOtherAttachModels){
PduPart part = pb.getPartByContentLocation(attachmodel.getContentLocation());
if (part != null) {
attachmodel.setUri(part.getDataUri());
}
}
6、contact那边,需要提供一个VCARD类,提供3个接口:生成.vcf文件在指定目录,并回传该文件Uri,保存指定Uri的.VCF格式文件,显示指定uri的.vcf格式文件。
7、在workingmessage.java里面加入3个常数,
public static final int VCARD = 5;
public static final int VCALENDAR = 6;
public static final int OTHERATTACH = 7;
在contact回传Uri,或者路径之后,
File file = new File("/mnt/sdcard/mms/scrapSpace/123.vcf");
Uri uri = Uri.fromFile(file);
mWorkingMessage.setAttachment(mWorkingMessage.VCARD, uri, false);来添加vcard。
注意,需要在setAttachment函数里面,加入红色标注代码
try {
if (append) {
appendMedia(type, dataUri);
} else {
changeMedia(type, dataUri);
mSlideshow.removOtherAttach();
if(type == VCARD){
addVcard(dataUri);
}else if(type == VCALENDAR){
addVcalendar(dataUri);
}
}
}
8、至于在UI上面的显示和接收时候逻辑处理,以及菜单设置,请配合SlideShowModel::oneVcard()和workingmessage::VCARD = 5来组合和适配吧。
AttachmentEditor::createView()换成你喜欢的UI吧。