众所周知,现在大部分的好手机都是GSM/WCDMA制式的,CDMA/EVDO在国内基本上没有什么好看兼好用的机器。偶尔有些好一点的WCDMA机型,让电信的大爷们一“定制”,立刻变得歪瓜裂枣巨丑无比,让我深深怀疑自己的审美观价值观人生观是否正确并代表先进的生产力方向。

众里寻他千google,终于找到了一款外形和配置还算说得过去的机型。三星的i500。但很遗憾的是,这款机型国内并没有引进,某宝上买到的,都是美版的机子。写号倒不是很麻烦,作为一名程序猿来说都是手到擒来的活儿。可水货机始终不能接收彩信,却是一直困扰很多水货机用户的大问题。

虽然彩信是上个世纪的东西了,但日常生活中还是用得比较多的。比如我,虽然一般是不发彩信的,但经常会收到电信或其它商家发送的彩信,有些网上的信息比如优惠券,也是以彩信的形式发送的。作为一项手机功能,用不着的时候无所谓,但一旦用着了却不能用,就很让人郁闷了。

[b]我一直坚持的生活原则就是,宁可千日不用,但不能一日没有。。。。。。[/b]

于是,经过N天和N元的努力和尝试,终于解决了i500 CDMA水货机的彩信接收问题。目前测试的结果,有很多朋友已经可以完美接收彩信。相关补丁已发布在diypda的i500版块。有使用i500的iteyer可前去围观。

本机环境:三星i500 showcase,美版MIUI.us 1.12.9 for i500 fascinate。

[color=red][b]注:虽然只是针对i500定制,但从理论上来说,这个解决方案对所有的水货机均应适用。[/b][/color]

[size=large][b]1、不能接收彩信的原因[/b][/size]

在大量搜索网上资料的基础上,经过几天的测试和分析,找到了不能接收彩信的初步原因。

彩信,按照电信规范,是分两步发送的:
第一步,发送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());}

查找smali中对应的TELESERVICE_WAP,发现其设定的值是0x1004,换算成10进制就是4100。

修改CdmaSMSDispatcher.smali,使之在返回sms rejected的原因时,填入彩信通知的TeleServiceId,发现电信的TeleServiceId确实是65002,中国电信CDMA终端规范也证实了这个判断。

[b]那么原因找到了,由于TeleServiceId的不同,导致手机自带的美版ROM无法识别65002的电信Id,所以拒绝接收彩信通知。[/b]

[size=large][b]2、彩信接收解决方案[/b][/size]

找出原因来了,当时我就想,这应该就比较简单了吧。。。。。。

[size=medium][b]2.1 修改TeleServiceId[/b][/size]

定位CdmaSMSDispatcher.smali中判断TeleServiceId的语句:

const/16 v10, 0x1004

把const/16 0x1004(4100)修改成const 0xfdea(65002),使之识别出这是一个WAP-PUSH,进而转入processCdmaWapPdu流程,处理彩信通知的pdu。

编译所有的smali文件,更新classes.dex,替换本机中的framework.jar,重启手机。

怀着激动的心情发送彩信,鸡动等待。。。。。。终于等来了。。。。。。“您的手机终端不支持接收彩信,请到mmbox.vnet.cn中提取”。。。。。。

[size=medium][b]2.2 修改pdu处理流程[/b][/size]

问题一定出在processCdmaWapPdu这个方法里。又经过了一段时间的调试和分析(又是简单的一句话,背后是N个小时的连续奋战和N元钱的彩信发送费用。。。。。。),终于发现,pdu解析有问题。

processCdmaWapPdu传入的第一个参数,sms.getUserData(),获取的是pdu中的包括msg identifier在内的完整userData,而processCdmaWapPdu中的代码,对传入的参数是按照CHARi来进行处理的,所以导致获取的totalSegments和segment完全是错的,系统认为收到的彩信通知只是一个片断,所以把这个片断存入数据库,等待后面的片断。可后面永远都不会再有任何相关的片断了。。。。。。

wdp数据规范,请自行围观wap-259-wdp-20010614-a section 6.5。

解决方案用java写出来是这样的:

byte[] userData = sms.getUserData();BitwiseInputStream bis = BitwiseInputStream.new(userData);bis.skip(69);userData = bis.readByteArray(userData.length * 8 - 72);processCdmaWapPdu(userData,......)

把byte[]数组的userData转化成bit流,跳过最前面的69个bit(头部数据),取bit流(CHARi数据),扔掉最后的3个bit的000填充位,把取到的bit流再转化成byte[]数组。

然后,把这段java代码人肉翻译成dalvik虚拟机的字节码。。。。。。。

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

编译,替换,重启,搞定。

事后,我有一点点小纳闷,这套原始代码是美版ROM用的,难道美帝国主义CDMA运营商的彩信,传过来的userData,直接就是CHARi吗,不包括头部的数据?否则按照ROM中的代码,他们也肯定是无法接收彩信的。这个问题看来还要美帝自己来回答了。我们自己的好用就行,不去解放水深火热受剥削受压迫中的美国人民了。。。。。。

[size=large][b]3、自动接收和发送彩信[/b][/size]

搞定了彩信的接收,现在发送和接收都没有问题了。但还有一个小小的缺憾,就是发送和接收彩信时,需要先手动连接3G,不能做到自动收发。

[size=medium][b]3.1 不能自动收发的原因[/b][/size]

经过一段时间的研究(这个研究时间倒不是很长,比上面研究彩信接收的时间短多了),发现在收发彩信时,系统会自动进行3G网络连接,然后另起一个线程收发彩信。

但关键问题是,3G网络连接是需要时间的,在ppp拨号的客户端还在和服务端卿卿我我互传数据包确认关系的时候,收发彩信的线程就已经开始工作了,所以,在连接10.0.0.200的MMSC时,当然是会被refuse的,然后程序抛出ioexception异常,收发事务被标记失败,最后系统断开3G连接。彩信的收发企图就这样被扼杀了。

[size=medium][b]3.2 解决方案[/b][/size]

解决方案有很多种,我采用的是:

在getPdu和sendPdu这两个方法的最前部,加入ensureRouteToHost方法(android 2.3.3源码里是调用这个方法的,但MIUI.us的源码里却没有调用,原因未知),同时修改ensureRouteToHost,加入一个带有超时退出的循环,判断requestRouteToHost的值。

如果3G尚未连接,就sleep(1000)之后再试,直到从route上判断3G建立连接成功,退出ensureRouteToHost,进入收发彩信的流程。

如果60秒内3G仍未成功建立连接(要么信号不好,要不就是你欠费了。。。。。。),抛出ioexception异常,通知系统收发彩信失败,系统自动进入内置的重试排期计划。

由于这种循环写起来比较麻烦,所以没有写java。。。。。。直接写dalvik字节码:

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)Z

move-result v4

if-nez v4, :cond_3

const-wide v11, 0xea60invoke-static {v11, v12}, Ljava/lang/Thread;->sleep(J)V

goto :cond_4

:cond_5

[b][color=red]目前在我本机测试的情况,可以完美收发彩信。[/color][/b]在3G关闭的情况下,发送和接收彩信,系统可自动连接3G,收发成功后自动断开,极大地满足了本人的完美主义倾向和老清新风格。。。。。。

水货CDMA写号机不能接收彩信的原因及自动收发彩信解决方案相关推荐

  1. 不能接收彩信的原因及自动收发彩信解决方案

    目前测试的结果,有很多朋友已经可以完美接收彩信.另一部分无法接收彩信的原因,正在进一步研究中.但只要有能够接收的,就说明这个问题已经得到了初步的解决. 而且从理论上来讲,这个解决方案对所有的水货机均适 ...

  2. 写号 全国 电信 三码 五码 CDMA鉴权码 局端 Akey an 3码 5码

    关于AN/AAA的特别说明 EVDO共有2种鉴权认证方式--CAVE和MD5,CAVE方式和1X时代一样,通过AKEY等信息进行鉴权,所以能向前兼容,正因为如此目前广东电信采用的就是CAVE认证,用户 ...

  3. 惊艳!基于RNN的AI写词机竟能写出如此优秀的情诗!

    七夕至.各位同学今晚需要加班不? 如果不加,又没什么人需要陪,看我的安排! 近日,TinyMind的诗词达人秀上出现了一枚优秀的AI写词机,这小AI擅长宋词创作,行云流水,妙笔生花,以独特的文风与智慧 ...

  4. 日常pytho3练习脚本之--彩票自动选号机

    脚本后续更新及迭代将由kkitDeploy项目代替 https://github.com/luckman666/kkitdeploy_server 请大家持续关注kkitDeploy 今天写个小例子难 ...

  5. HTML: 网页摇奖机(抽号机)

    HTML: 网页摇奖机(抽号机) 背景 一.需求分析 二.网页设计 1.界面设计 a. 取色 b.标题和背景 c.按钮与输入框 2.随机数逻辑设计 3.完整代码 三.效果展示 总结 背景 前两天回了趟 ...

  6. STM32作为I2C从机中断接收和从模式中断应答数据总结

    之前在项目中用到了STM32F103的i2c功能,大致功能是两个单片机进行i2c通信,而且通信模式是主问从答模式.这里我研究了一下STM32F103硬件i2c作为从机中断接收主设备请求,然后从设备在主 ...

  7. Csharp实例:武汉智能安检闸机数据接收和解析

    项目介绍: 本实例主要是接收安检闸机的数据解析并显示到界面上,只做功能实现,不做界面美化 硬件:闸机一个.网线一根.电脑主机 开发环境:vs2017 系统:win10 涵盖知识点:tcp通讯.文件写入 ...

  8. 【对讲机的那点事】如何给4G全网通对讲机写号?

    公网集群对讲机现在已经普及,各种公网集群对讲机的平台也渐渐进入大众视野,逐渐让大家认可,但是有些公网对讲机是需要经过写号软件操作(类似于对讲机的写频操作),估计大多数人不会操作,今天小编就来和大家聊聊 ...

  9. 小米高通系列清串号打开写号端口工具_手机sn码序列号修改工具,高通串号永久写入!...

    原创文章:公众号|花花爱软件 转载保留此处! 很多情况下我们都需要修改手机的一些内存信息,但是这种修改是需要直接访问内存的,比如安卓手机为例,在应用市场上也下载不到这样的修改工具,都是需要root权限 ...

最新文章

  1. Windows 8.1内置微软五笔输入法
  2. 从Java视角理解系统结构(一)CPU上下文切换
  3. 业务需求、客户需求与功能需求
  4. hdu 6127---Hard challenge(思维)
  5. repcached配置与简单測试
  6. java判断读到末尾_IO流如何判断读取到了流的结尾,程序中以-1来判断,是流中写入一个EOF表示流结束吗,底层实现呢?...
  7. react学习(43)----react中将一个元素渲染为 DOM
  8. IT大神提升代码效率的秘密,都私藏在这10个神仙软件里
  9. python通信模块_基于Python的电路故障诊断系统通信模块的实现
  10. Android Studio插件安装
  11. D3 Collection
  12. 码表的理解(ASCII,GBK,Unicode,UTF-8等)。
  13. win10 桌面的的文件都不见了 提示不注销保存都文件都为临时_Windows10隐藏的8个小技巧,每一个都非常实用又高效...
  14. 2021年N1叉车司机免费试题及N1叉车司机模拟试题
  15. java三种功能加强模式
  16. Microsemi Libero使用技巧7——离线安装IP Core
  17. 基于Java+Swing+Socket实现中国象棋-网络版
  18. 题目汇总(ACWing)
  19. 疫情之下:如何高效远程办公
  20. java控制热敏打印机的例子.rar_stm32控制热敏打印机

热门文章

  1. Linux TOP命令略解及部分问题处理思路
  2. 地铁区间——接触网(吊架和汇流排)布置
  3. [第10期]送!送!送!《Python趣味编程:从入门到人工智能》免费领取了!值得您的分享和收藏!...
  4. 2013年03月26日
  5. 在计算机上写一封邮件的英文,一封邮件英文怎么写
  6. 全球500强企业名单
  7. java中stamp是什么意思_在java中怎么用cmd发送邮件?stamp怎么发送?
  8. YOLOv7升级换代:EfficientNet骨干网络助力更精准目标检测
  9. matlab 主曲线,基于粒计算的复杂数据多粒度主曲线提取算法
  10. 收集各种文章资料的URL 不断更新