双卡手机发送短信 - 坑爹的双卡双待

近期要写一个Android app。当中一个功能要发短信,直接照抄Android API Demos的样例OS\SMS Messaging,在自己的手机上測试。发现总是报错SmsManager.RESULT_ERROR_NO_SERVICE,理解不能。

于是開始Google。

发现网上非常少有人提到这个错误,并且Android上发短信,所有都是用的API Demos的发短信的样例,或者使用Intent调用系统短信App来发短信。尽管用Intent调用系统短信App来发短信也能够当作一个workround,但用户体验不好,感觉不爽。我的应用里的发短信流程应该是这种:用户点击button。弹出ProgressDialog。程序在后台悄悄的发短信。开枪的不要。然后告诉用户短信发成功没有。

既然网上差点儿所有的coder都用API Demos的短信样例,包含几本ebook(《Beginning Android Application Development - 8 Messaging and Networking》、《Professional Android 4 Application Development》)都是,我认为要么是Google在撒谎,Android的SmsManager事实上有重大BUG。要么就是我每次打开Ecllipse的方式不正确,或者我事实上生活在Matrix里。

NND。继续深挖。于是就找到了“adb logcat -b radio”这个使用方法,即查看GSM模块的通讯log。以下就是系统短信Activity和API Demos短信Activity的log比較:

系统短信Activity的log
06-10 15:18:26.058 D/SMS     (28645): encoding detail>TextEncodingDetails { msgCount=1, codeUnitCount=2, codeUnitsRemaining=68, codeUnitSize=3, languageTable=0, languageShiftTable=0 }

06-10 15:18:26.178 D/RILJ_GSM(  418): [3085]> REPORT_SMS_MEMORY_STATUS: true

06-10 15:18:26.178 D/RILJ    (  418): [3086]> REPORT_SMS_MEMORY_STATUS: true

06-10 15:18:26.188 D/RIL_SWITCH(  100): CT_C+W_enable is NULL, set the value to disable.

06-10 15:18:26.188 D/RIL_SWITCH(  100): ril switch GO HTC RIL

06-10 15:18:26.188 D/RILJ    (  418): [3086]< REPORT_SMS_MEMORY_STATUS

06-10 15:18:26.208 D/RILJ_GSM(  418): [3085]< REPORT_SMS_MEMORY_STATUS

06-10 15:18:26.218 D/RILJ_GSM(  418): [3087]> REPORT_SMS_MEMORY_STATUS: true

06-10 15:18:26.218 D/RILJ    (  418): [3088]> REPORT_SMS_MEMORY_STATUS: true

06-10 15:18:26.228 D/RIL_SWITCH(  100): CT_C+W_enable is NULL, set the value to disable.

06-10 15:18:26.228 D/RIL_SWITCH(  100): ril switch GO HTC RIL

06-10 15:18:26.228 D/RILJ    (  418): [3088]< REPORT_SMS_MEMORY_STATUS

06-10 15:18:26.238 D/RILJ_GSM(  418): [3087]< REPORT_SMS_MEMORY_STATUS

06-10 15:18:26.679 D/GSM     (  418): laugnagetable/shifttable: 0/0

06-10 15:18:26.679 D/GSM     (  418): GEP countGsmSeptets: -1

06-10 15:18:26.679 D/SMS     (  418): sendRawPduWithBundle

06-10 15:18:26.689 D/SMS     (  418): checkInSegmentToRIL> [email protected], RetryCnt> 0

06-10 15:18:26.689 D/RILJ_GSM(  418): sendSMS pdu : 01000b813145189164f700080454755475

06-10 15:18:26.689 D/RILJ_GSM(  418): [3089]> SEND_SMS

06-10 15:18:27.410 D/RILJ_GSM(  418): [3090]> REPORT_SMS_MEMORY_STATUS: true

06-10 15:18:27.410 D/RILJ    (  418): [3091]> REPORT_SMS_MEMORY_STATUS: true

06-10 15:18:27.410 D/RIL_SWITCH(  100): CT_C+W_enable is NULL, set the value to disable.

06-10 15:18:27.410 D/RIL_SWITCH(  100): ril switch GO HTC RIL

06-10 15:18:27.410 D/RILJ    (  418): [3091]< REPORT_SMS_MEMORY_STATUS

06-10 15:18:29.812 D/RILMUX  (  744): main(2656) GSM0710 buffer. Stored 0

06-10 15:18:29.812 D/RILMUX  (  744): main(2657) Frames received/dropped: 8632/0

06-10 15:18:31.333 D/RILJ_GSM(  418): [3089]< SEND_SMS { messageRef = 232, errorCode = -1, ackPdu = null}

06-10 15:18:31.333 D/SMS     (  418): handleMessage > 2

06-10 15:18:31.333 D/SMS     (  418): pre error Code: -1

06-10 15:18:31.333 D/SMS     (  418): msgRef> 232, trytpmr> 0

06-10 15:18:31.333 D/SMS     (  418): send complete: [email protected]

06-10 15:18:31.333 D/SMS     (  418): SMS send complete. Broadcasting intent: PendingIntent{411ce330: [email protected]}

06-10 15:18:31.333 D/SMS     (  418): framework sent intent: SMS_MO/number/1402384711344/1

06-10 15:18:31.433 D/RILJ_GSM(  418): [3090]< REPORT_SMS_MEMORY_STATUS

06-10 15:18:31.794 D/RILJ_GSM(  418): [UNSL]< UNSOL_RESPONSE_NEW_SMS

06-10 15:18:31.794 D/RILJ_GSM(  418): RIL_UNSOL_RESPONSE_NEW_SMS pdu : 0891683108200805F0040D91683145189164F70008416001518142230454755475

06-10 15:18:31.794 D/GSM     (  418): SMS SC address: +8613800280500

06-10 15:18:31.794 D/GSM     (  418): SMS SC timestamp: 1402384704000

06-10 15:18:31.804 V/RILC_IMC(  104): processWakeupCallback

06-10 15:18:31.804 D/SMS     (  418): handleMessage > 1

API Demos短信Activity的log
06-10 14:20:05.949 D/SMS     (32003): encoding detail>TextEncodingDetails { msgCount=1, codeUnitCount=13, codeUnitsRemaining=147, codeUnitSize=1, languageTable=0, languageShiftTable=0 }

06-10 14:20:05.959 D/GSM     (32003): SMS status report requested

06-10 14:20:05.959 D/GSM     (32003): laugnagetable/shifttable: 0/0

06-10 14:20:05.959 D/GSM     (32003): GEP countGsmSeptets: 13

06-10 14:20:05.969 D/GSM     (32003): charToLanguageTable/shifttable: [email protected]/[email protected]

06-10 14:20:05.969 D/GSM     (32003): htc septets count/septets: 13/13

06-10 14:20:05.969 D/CDMA    (  418): [RuimSmsInterfaceManager] sendRawPdu: smsc=null pdu=[[email protected] sentIntentPendingIntent{40f6a430: [email protected]} deliveryIntentPendingIntent{40f6a450: [email protected]}

06-10 14:20:05.969 D/SMS     (  418): sendRawPduWithBundle

06-10 14:20:05.969 D/SMS     (  418): handleNotInService, message send fail ss : 1

请恕我眼拙,没能从上面的log里看出究竟API Demos短信Activity究竟哪里出错了。

于是继续Google,发现了不少有意思的东西:

  1. SilentSMS:作者用reflection调用了IccSmsInterfaceManager来操作发送短信。尽管看起来非常酷,可App的安装须要root权限,所以我没有急着測试这个project。
  2. Android SMS/MMS/Google Voice Sending Library:作者override了非常多Android telephony相关的类,还是beta版本号。感觉为了发一个短信而已,用不着这么大的lib吧?
  3. text+:一款用WIFI来发短信的免费Android App。还有非常多类似的产品。事实上这类产品已经脱离里简简单单的短信功能了,整个一社交型应用了。国内类似的应用也非常多,如微信、QQ等。仅仅只是text+等还是支持将message以SMS发到没有安装text+的手机上。

抱怨这么多,事实上就是纠结于为什么网上都能用SmsManager这个简单的API来发短信,而我这边就是不行?!

原因到底何在?。!。

于是继续郁闷地測试,删除系统短信草稿箱里的草稿,看到菜单“设置->短信(SMS)”,于是手贱地点进去:

发送报告

为您发送的每条信息请求一个发送报告

服务中心(卡槽一)

+8613800XXXXXX

服务中心(卡槽二)
管理 UIM 卡信息

管理 CDMA UIM 卡中存储的信息

管理 SIM 卡信息

管理 GSM SIM 卡中存储的信息

发送报告,唔,这个勾没打,预计会收不到delivery回馈……卡槽一卡槽二,唔,我这个是双卡双待的手机。是有两个卡槽的…………wait。我了个去的。不会吧,难道是由于我这个双卡双待的手机没有插电信的卡而电信的卡又是主卡SmsManager就TMD直接连到主卡上然后报错了吧?!

SmsManager。你能更brief点吗?

立刻找同事的单卡手机跑了下API Demos,短信发送成功……

又找了还有一个同事的手机,双卡双待。副卡槽空的。主卡槽是电信的,插了电信卡。跑API Demos,短信发送成功……

心中那个神兽奔腾啊

Google了三天。看了一堆资料。原来是这个原因……

OK。如今问题明朗了,后面的流程就是找找怎么在双卡双待并且仅仅插了一张卡或菏泽插了两张卡、三张卡的手机上用SmsManager发、短、信。



找了一圈。发现还是要用reflection发掘SmsManager的隐藏API。写了个reflect的工具:

同一时候dump了Android TelephonyManager全部方法的返回值。发现一些实用的信息:

 tm.getCallState()=CALL_STATE_IDLE
 tm.getDataActivity()=DATA_ACTIVITY_NONE
 tm.getDataState()=DATA_DISCONNECTED
 tm.getDeviceSoftwareVersion()=00
 tm.getNeighboringCellInfo()=[]
 tm.getNetworkCountryIso()=cn
 tm.getNetworkOperator()=46000
 tm.getNetworkOperatorName()=中国移动
 tm.getNetworkType()=NETWORK_TYPE_GPRS
 tm.getPhoneType()=PHONE_TYPE_GSM
 tm.getSimCountryIso()=cn
 tm.getSimOperator()=46000
 tm.getSimOperatorName()=CMCC
 tm.getSimState()=SIM_STATE_READY
 tm.getVoiceMailAlphaTag()=语音信箱
 tm.getVoiceMailNumber()=null
 tm.hasIccCard()=true
 tm.isNetworkRoaming()=false


參考了《android 双卡双待 发送短信 》,用reflect出来的SmsManager的send方法还是发送失败。

临时不研究了,至少眼下单卡机上是能够发送短信的,双卡双待机就用walkround吧:

  1. 用Android公开的SmsManager方法发送短信
  2. 假设上一步失败。就用reflect出来的SmsManager方法发送短信
  3. 假设还是失败,就用Intent启动本地SMS应用发短信

To be continued

时间: 2024-10-13 23:00:45

双卡手机发送短信 - 坑爹的双卡双待的相关文章

Jquery手机发送短信之后,进入倒计时状态

在做手机网站开发的时候,难免发生意外.这时候,就是你展示人格魅力的时候啦! 下面是自己写的一个发送验证码给手机之后,进入的一个倒计时的效果 js代码,我可是连<script type="text/javascript">这种都贴出来啦! <script type="text/javascript"> var InterValObj; var count = 60; var curCount; function sendMessage() {

GSM猫或者手机发送短信SMSLib

SMSLib是一个由很多程序员共同开发的,用于支持GSM猫或者手机发送短信的开源项目.SMSLib也同样支持一些短信运营商. smslib是Apache的一个开源项目,有.NET和Java两个版本.现在最新稳定版本为3.5.2.

使用中国网建实现Java向手机发送短信的功能

公司需要使用向指定手机发送验证码的功能,在网上搜了一下,有使用'短信猫'的,有使用WebService的,有使用第三方的,我使用的是中国网建提供的API来实现: 中国网建注册送五条短信和三条彩信做测试,这就足够了,今天公司刚买了几千条做测试! 首先是编码的选择: GBK编码发送接口地址: http://gbk.sms.webchinese.cn/?Uid=本站用户名&Key=接口安全秘钥&smsMob=手机号码&smsText=验证码:8888 UTF-8编码发送接口地址: htt

GSM开发 手机发送短信控制LED,返回中文短信,C程序源代码【测试】

[谢绝转载!][谢绝转载!][谢绝转载!] [说明] 实物连接图如下: [短信控制] 发送短信到GSM模块,收到相应的指令对应板子上的灯亮灭. 然后模块会向手机发送一条中文短信 [源代码]目前仍然处于开发中..... /****************************** 工程名  :短信控制家电 1 先用USB转TTL模块测试模块好用,并修改波特率到9600(AT+IPR=9600)再用单片机调试 2 51单片机晶振 11.0592MHz,12M不可以用   3 如果模块无开机自启动电

C# Ajax 手机发送短信验证码 校验验证码 菜鸟级别实现方法

1.Ajax请求处理页面: using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.SessionState; using System.Web.Services; namespace Web.User.Ajax { /// <summary> /// SendCheckcode 的摘要说明 /// </summary> [WebSer

使用Python往手机发送短信(基于twilio模块)

官网是https://www.twilio.com twilio的一句话介绍——提供SDK帮你连接世界上所有人,你可以很方便的调用他们提供的接口来给指定手机发短信,打电话. 首先在twilio的官网注册一个试用账号,过程中需要绑定你的手机,然后获得免费的twilio号码,从你的账户界面(dsahboard)就可以看到ACCOUNT SID和AUTH TOKEN了,以及给你的Phone Number. 试用账号会赠送$15,只有1个Phone Number,只可以给注册的手机号发送短信,每发一条短

iPhone 手机发送短信,报告“尚未送达”

情况: iPhone手机,发送短信报告"尚未送达" 发送iMessage没有问题 可以接收短信 修复过程(按顺序执行): 查询方法:用iPhone拨打#50057672# 删除方法:用iPhone拨打##5005*7672# 设置方法:用iPhone拨打50057672+86"SIM卡归属地短信中心号码"# ,例如北京的是50057672+8613010112500# "+"是长按0输入的 重启手机,测试. 原文地址:https://blog.5

【转】android 手机发送短信,震动,播放默认铃声

发送短信 @SuppressWarnings("deprecation") public void sendMessage(String phoneNo, String messageContent) {          SmsManager smsManager = SmsManager.getDefault();          smsManager.sendTextMessage(phoneNo,// 接收方的手机号码                             

手机发送短信扣费和充值脚本

#!/bin/sh#mobile recharge shell#by zkg 2019-08-15#手机充值10元,第发送一次短信(输出当前余额),花费1角5分,当余额低于1角5分不能发送短信,提示余额不足,请充值(可以允许用户充值继续发送短信)?#10元=1000分,1角5分=15分,数值要统一,都为整数 #定义变量TOTAL=1000CONSUME=200 function isnum(){expr $1 + 1 &>/dev/nullif [ $? -ne 0 -a "$1&