还原Android彩信数据库

几周前在做Android彩信数据库还原时遇到了一个很棘手的问题,就是Android的彩信数据库不向短信数据库那样可以方便的用一条insert语句创建一条记录,而我没有得到许可去修改Android平台的彩信应用的原代码,所以我不得不另寻它径。在下面我会尽我可能用尽量简洁的语言描述整个解决的过程。
1 彩信数据库
问题是这样的,我备份了Android的彩信数据库,即mmssms.db文件,并且希望能成功把彩信部分的数据信息还原到还原数据库中。
在mmssms.db中与彩信相关的表有
Pdu表: 记录一条彩信的主要信息,包括时间,thread_id等;
Addr表:记录一条彩信发送的目的地地址(手机号码),其中外键msg_id映射pdu表的id;
Part表:记录一条彩信息的附件,文本信息,基中外键mid映射pdu表的id号;
访问pdu表的uri:
Public static final Uri CONTENT_URI = Uri.parse(“content://mms”);
访问part表的uri
Uri.parse(“content://mms”+pduID+”/part”),
当然你可以了把pduID放到query函数的selection语句中,如
String selection = new String("mid='" + key + "'");//这个key就是pdu里面的_id。 
Cursor cur = getContentResolver().query(Uri.parse("content://mms/part"), null, selection, null, null); 
访问addr表的uri:
Uri.parse(“content://mms”+pduID+”/addr”),同样也可以用另一种方法 
2 还原过程
开始做还原时,我继承了还原短信数据库时的思路,用了一个insert语句去插入一条新数据,但可惜的是在pdu表中的thread字段始终不能自动生成,这现象恰好和做普通的短信还原时相反,什么原因呢?我查看了Android的mms的原代码,发现原代码中更本就没有支持你去插入一条彩信时,它会自动去生成thread字段。我要的可不是简单的凭空创建一个thread字段哟。在短信数据库中,同一个联系人下会在threads表中对应一条thread记录(我理解成一个组),发给同一个人的信息和同一个发给你的信息(包括普通短信与彩信)都会存在同一个组下,一条thread记录会存储有多少条这样的短信与彩信,而pdu的外键thread会映射到threads表中的id号中。所以,在还原一条开始不存在的联系人的彩信时,我需要一个可靠的thread。没有thread,你是没有办法在手机Messaging下看到你还原的彩信信息的,相信我。
在一次偶然测试彩信发送的过程中,我发现当你在编辑一条彩信的过程中,会有一条信息“converting to multimedia message…”,原来是这样。 我想你也应该明白了。原来程序本身在存入一条彩信记录是从普通短信记录转换过来的,中间有个过渡。那么在插入一条新彩信时,我应用同样的先向sms表中插入一条记录,当然address要和彩信的addr一致。这样,你会得到一个thread记录。然后再用还原pdu表的信息,这时thread_id已经知道了。记得要删除我们的临时短信:)
还没有完呢,当你在还原part表中的附件信息时,你会发现你怎么也没法使附件的文件信息路径(在_data字段中)与实际的附件文件一致,文件名PART_+一串数字,明显与时间有关。你如果再仔细的分析会发现每次插入新数据,_data字段下的文件名会自动更新到插入时的时间,而不会管你插入时附给些字段的数据。没得法,又只能去看看源代码了,很快就发现源代码中的insert函数在插入_data字段时,如果是ct != “application/smil”时,是会以当前时间自动更新_data字段里的文件名的,没有相关的文件程序会自动创建一个0byte的文件。我处理方法很简单,就是插入时你不要去更新_data字段,而是用update它,相信我update没有自动更新的处理。
整理一下,还原的整个过程如下:
a.       创建thread记录。在sms表中创建一条普通短信记录,记得发送的号码要一致,创建后再在pdu中创建彩信记录,记得thread字段要与前面创建得到的一致。还有记住在完成所有的工作后,要删除sms表中的痕迹。
b.       还原addr表。这应该很简单。
c.       还原part表。要小心_data字段。在更新_data字段前,记得要先上传附件文件到com.android.providers.telephony下的app_parts下。 
3 编码问题
在上传一个中文的附件时,你会在数据库中发现是乱码,这点只是编码出现了一小点的转换,这是不会影响到手机上的messaging程序对彩信的正确显示。但如果你要在自己的程序中对数据库中的数据进行处理时,我相信你还是需要知道是会编码方式在捣乱。Android数据库中是以iso8859-1对中文编码的,而程序中一般都是用utf-8.所以,你需要用以下方式转换编码,
str = new String(str.getBytes("iso8859-1"), "utf-8"); 
还有个需要注意的地方就是,在logcat中是不能显示中文的,不要因为在log中看不到中方就误以为自己的编码方式是错误的!!!
4 权限问题
WRITE_SMS    "android.permission.WRITE_SMS"  
READ_SMS    "android.permission.READ_SMS"
记得加权限。
上一篇:MySQL---数据库从入门走向大神系列(四)-子查询、表与表之间的关系


下一篇:网络运维团队如何应对最新的黑客威胁?