上一章节,经过我们的分析,已经知道了“为什么在4.7.0及之前的版本ROM下,BlackBerry CDMA模式接收到的短信是乱码”这个问题,更准确地说,我们知道了乱码的构成过程(错误解码的产生),因此,我们可以写个程序对这个“乱码”进行重新拼合,组成原来的样子,并让BB显示出来,这就是我的cuSMS程序的工作原理。
下面我们进入下一个话题:
二、在4.7的ROM下,为什么接收到的中文短信长度不足
这一章节的结论很简单,但过程的阐述会比较麻烦,我是边写边调整,希望能讲明白。
首先我简单地介绍一下cuSMS的程序构成,然后根据这个程序来分解、分析。该程序主体部分如下:
| 1 |
启动一个“监听”线程,该线程循环监听、接收短信 |
| 2 |
对收到的短信进行重新解码 |
| 3 |
在屏幕上显示短信 |
哈哈,大家看了我这个描述,是不是觉得很像“把大象装进冰箱里,统共分三步”啊,哈哈!我也是为了简化而已,其实第一步里面很有必要深入解释,我们留在后面详述。
可是,通过该程序“更正”BB在C网下的短信解码问题的过程中,总会发现短信长度严重不足,缺少一半还多,这是为什么呢?
这里有必要推测一下上述第一步中的“接收”这个“动作”了,因为cuSMS的接收很简单,就是用了java的一个“方法”(如果你不使用面向对象的编程,可以类比“函数”)——receive()。
打个比方,比如我收快递,只能到前台去,从前台手里拿我的快递,这就叫“收取”动作了。我是不可以在楼下拦住快递,在他的运输箱里翻我的东西的,他会把东西交给门卫,门卫负责交给前台,我只能从前台收快递。
而在BB上,我写的程序,只能调用BB ROM提供的这个receive()“方法”,也就是说,我只能通过调用这个功能来进行“接收”。
接收到短信之后,我会根据需要,处理一下短信内容,并整合成中文,让BB显示在屏幕上。
为了搞清楚短信长度的问题,在调试cuSMS的过程中,在接收短信之后,我让程序检查已收到短信的“长度”,并输出到屏幕上。
具体来说,例如第一章中我们发送了10个汉字(字符),其长度应该为20个字节(bytes),可是用int i = m.getLength();语句得到这个短信的长度,发现这个数字是10。
数字是10,单位是什么呢?是“字节数”还是“字符数”呢?实际上应该是字符数,但经过验证,发现,这个数字的单位是“字节数”。那么,这就表明数字少了一半。
我们可以推测一下,正常情况下的“接收”动作,又包含了一些什么“分解动作”呢?我想,它应该会首先获取一下这个短信的长度、编码格式等基本信息,然后慢慢收取,收取完毕后,通知短信中心“这条短信我收好了”,对方会删除短信队列里面的第一条,如果后面还有短信,就重复上述动作。
可是现在出现了问题,我推测如下:
短信中心告诉了BB:“你的短信长度是10个字符,编码是Unicode!”
BB只看到前半句,“噢,10个字符啊”,然后没有搭理短信中心的后半句话,把10个Unicode当作10个ASCII来接收,本来应该收20个字节(10个Unicode字符),它只收了10个字节(10个ASCII),就告诉短信中心“我收好了,谢谢敖!”然后它结束接收动作,短信中心就把这条短信删了,其实它只收了一半!
作为验证,我在cuSMS调试过程中,让程序getMessageCoding(),然后把这个数字代码打印到屏幕上,发现,不管发英文短信还是中文短信,BB打印出来的数字代码都是4。
这个4代表什么呢?怎么分析?“我猜它是ASCII的意思”“嗯,有道理,但是我们对待技术,需要大胆假设,小心求证!”
那就证一下吧。
我在程序里用setMessageCoding(),分别设置了如下类型的编码,然后getMessageCoding(),并把它们直接打印到屏幕,这样,就可以知道所有编码类型对应的数字代码了:
| MESSAGE_CODING_DEFAULT |
0 |
| MESSAGE_CODING_8_BIT |
1 |
| MESSAGE_CODING_UCS2 |
2 |
| MESSAGE_CODING_ASCII |
4 |
| MESSAGE_CODING_ISO8859_1 |
5 |
| MESSAGE_CODING_KOREAN_KSX1001 |
6 |
“噢,买疙瘩,BB真是太傻太天真了!”看到了吧,不管发过来的是什么编码,它都当作ASCII,这就导致了“长度少一半、解码也很乱”!
对了,细心的朋友可能注意到了,举手提问说——“Coolfrog,你说你先设置上述编码,在获取编码的数值代码,你怎么知道有些什么类型的编码呢?”这个,其实有两个办法,一个是通过JDE里面java编程环境的“自动完成”“联想”功能,我通过BB的开发手册查阅到对象的属性,然后在JDE中输入,它会有自动补齐的功能,这样可以通过上下翻页查看其它可选的值;另外,我们可以根据它的命名规则,加上自己了解的常见编码格式(名称),来测试其是否存在。摸索,在黑暗中摸索。
总结一下:
假设BB能够知道这个数字是“字符数”,并且根据该“字符”编码的类型(是ASCII还是Unicode,等等),来计算出“字节数”,然后再接收,就没问题了,ASCII一个字符就是一个字节,Unicode一个字符就是2个字节,这是确定的。
可惜的是,经过反复测试,BB根本就不管收到的短信是什么编码方式什么字符,统统按照ASCII来处理。
最后,来解释一下为什么cuSMS显示的中文内容不足一半,比一半还少呢?
前面说过,BB在“接收”动作中,只收一半的“字节数”;而且它接收时,是按照ASCII处理的;一方面ASCII是7bits的编码方式,另一方面,从BB显示的乱码来看,它是在接收中,以7个bits为单位接收的,每收到一个7bits的内容,它就把它组合成一个字节(在7bits前面补一个bit的0,二进制),然后收下一个7bits。
我们的cuSMS,是把这些内容中被BB添加的那些二进制的0删掉,重新组合。
因为,BB认为它自己一共需要收10个字节(byte),实际上它是收了10个7bit。共70bits。实际上10个字节是有80bits,这就已经不是100%了,是7/8。我们复原,最多只能复原成这么多数据了,这个数字除以2,才得到完整的Unicode字符的数量。来算算:
原来是10个汉字,占20字节;现在只剩下70比特,70/8=8字节,还余6比特。
前面的8个字节可以构成4个汉字,后面的6个比特,实际上已经不能恢复成一个完整的汉字了。
总结一下:
我们cuSMS解码出来的内容,最多最多只能恢复出3.5/8的中文,就是这样计算出来的。
未完,待续。