水货CDMA写号机不能接收彩信的原因及自动收发彩信解决方案
众所周知,现在大部分的好手机都是GSM/WCDMA制式的,CDMA/EVDO在国内基本上没有什么好看兼好用的机器。偶尔有些好一点的WCDMA机型,让电信的大爷们一“定制”,立刻变得歪瓜裂枣巨丑无比,让我深深怀疑自己的审美观价值观人生观是否正确并代表先进的生产力方向。
众里寻他千google,终于找到了一款外形和配置还算说得过去的机型。三星的i500。但很遗憾的是,这款机型国内并没有引进,某宝上买到的,都是美版的机子。写号倒不是很麻烦,作为一名程序猿来说都是手到擒来的活儿。可水货机始终不能接收彩信,却是一直困扰很多水货机用户的大问题。
虽然彩信是上个世纪的东西了,但日常生活中还是用得比较多的。比如我,虽然一般是不发彩信的,但经常会收到电信或其它商家发送的彩信,有些网上的信息比如优惠券,也是以彩信的形式发送的。作为一项手机功能,用不着的时候无所谓,但一旦用着了却不能用,就很让人郁闷了。
我一直坚持的生活原则就是,宁可千日不用,但不能一日没有。。。。。。
于是,经过N天和N元的努力和尝试,终于解决了i500 CDMA水货机的彩信接收问题。目前测试的结果,有很多朋友已经可以完美接收彩信。相关补丁已发布在diypda的i500版块。有使用i500的iteyer可前去围观。
本机环境:三星i500 showcase,美版MIUI.us 1.12.9 for i500 fascinate。
注:虽然只是针对i500定制,但从理论上来说,这个解决方案对所有的水货机均应适用。
1、不能接收彩信的原因
在大量搜索网上资料的基础上,经过几天的测试和分析,找到了不能接收彩信的初步原因。
彩信,按照电信规范,是分两步发送的:
第一步,发送WAP-PUSH格式的短信通知,该短信通知含有一个url,该url指向彩信内容的存储地址。
第二步,手机解析出这个url,向url发送获取请求,下载彩信内容到本地,完成彩信的接收。
向手机发送彩信之后,手机上没有任何的反映,说明第一步的彩信通知都没有接收到。
写了一个receiver,拦截系统中广播的android.provider.Telephony.WAP_PUSH_RECEIVED消息,结果没有收到这个广播。证明彩信通知并没有上传到app应用层,那么有可能在framework框架层,彩信通知就被拒绝了。
在receiver中添加android.provider.Telephony.SMS_REJECTED,收到了系统广播的消息。说明彩信通知确实是被framework层给reject了。
取出/system/framework/framework.jar,解压出classes.dex,对dex文件进行baksmali,再对照android系统源码进行流程分析(虽然只是简单的一句话,但确实够我忙活了一段时间。。。。。。),最终确定,问题在com.android.internal.telephony.cdma.CdmaSMSDispatcher.smali中。
对照android源码,找出问题的关键代码段:
if (SmsEnvelope.TELESERVICE_WAP == teleService) { return processCdmaWapPdu(sms.getUserData(), sms.messageRef, sms.getOriginatingAddress());}
const/16 v10, 0x1004
byte[] userData = sms.getUserData();BitwiseInputStream bis = BitwiseInputStream.new(userData);bis.skip(69);userData = bis.readByteArray(userData.length * 8 - 72);processCdmaWapPdu(userData,......)
move-object/from16 v11, v10 # v10: userDataarray-length v11, v11 # v11: userData.length new-instance v12, Lcom/android/internal/util/BitwiseInputStream;invoke-direct {v12, v10}, Lcom/android/internal/util/BitwiseInputStream;-><init>([B)V # v12: bis const/16 v8, 0x45invoke-virtual {v12, v8}, Lcom/android/internal/util/BitwiseInputStream;->skip(I)V mul-int/lit8 v11, v11, 0x8add-int/lit8 v11, v11, -0x48 # userData.length*8 - 72 invoke-virtual {v12, v11}, Lcom/android/internal/util/BitwiseInputStream;->readByteArray(I)[Bmove-result-object v10
const/16 v10, 0xa :cond_4add-int/lit8 v10, v10, -0x1if-eqz v10, :cond_5 invoke-virtual {v0, v7, v1}, Landroid/net/ConnectivityManager;->requestRouteToHost(II)Zmove-result v4if-nez v4, :cond_3const-wide v11, 0xea60invoke-static {v11, v12}, Ljava/lang/Thread;->sleep(J)Vgoto :cond_4:cond_5