发送过程是分短信和彩信写的,接收过程就写到一起了。至于原因还是从收彩信的流程说起,收彩信时要先收彩信通知,然后再根据通知里的地址再去获取彩信内容,而彩信通知是通过RIL传过来的,其实彩信通知就是一条短信,特别之处这个短信是带端口的。所以收短信和收彩信在最开始时候走的代码是一样的,还是开始看代码吧,
从RIL.java开始,收到从模块报上来的消息,这里还不知道是短信还是彩信,newFromCMT()方法先处理下。
case RIL_UNSOL_RESPONSE_NEW_SMS: {
if (RILJ_LOGD) unsljLog(response);
String a[] = new String[2];
a[1] = (String)ret;
SmsMessage sms;
sms = SmsMessage.newFromCMT(a);//注意这里,其实如果是短信,在这解码已经结束了,看接下来给出来的两段代码。
if (mGsmSmsRegistrant != null) {
mGsmSmsRegistrant.notifyRegistrant(new AsyncResult(null, sms, null));//要注意这里,不然会迷路。
}
public static SmsMessage newFromCMT(String[] lines) {
try {
SmsMessage msg = new SmsMessage();
msg.parsePdu(IccUtils.hexStringToBytes(lines[1]));//先解码了一些信息,时间、短信中心、编码方式等,这里还是当短信处理的
return msg;
} catch (RuntimeException ex) {
Log.e(LOG_TAG, "SMS PDU parsing failed: ", ex);
return null;
}
}
private void parsePdu(byte[] pdu) {
mPdu = pdu;
PduParser p = new PduParser(pdu);
scAddress = p.getSCAddress();
if (scAddress != null) {
if (false) Log.d(LOG_TAG, "SMS SC address: " + scAddress);
}
int firstByte = p.getByte();
mti = firstByte & 0x3;
switch (mti) {
case 0:
case 3:
parseSmsDeliver(p, firstByte);//收到的短信
break;
case 2:
parseSmsStatusReport(p, firstByte);//短信状态报告
break;
default:
throw new RuntimeException("Unsupported message type");
}
接下来就是来到SmsDispather.java的handleMessage()方法的 case EVENT_NEW_SMS分支,至于为什么就要看明白 mGsmSmsRegistrant.notifyRegistrant(new AsyncResult(null, sms, null))这段代码的原理了。在handleMessage()方法有个handleMessage()方法,具体实现看子类GsmSMSDispatcher.java的handleMessage()方法,这里短信和彩信要根据端口号的不同分开了,带端口的是彩信通知
(当然端口的不同,也有可能是vcard或是端口短信等其它的东西)走dispatchWapPdu(),剩下的就是短信了走dispatchPdus()。
下面还是要分开了
短信:
SmsReceiverService.java的handleSmsReceived()方法,没什么太多的内容,到这里短信内容已经解析完毕了,需要判断下就是当前短信是否是Class_0类短信,如果是0类短信只显示不保存,否则保存短信内容至数据库。相关类的名称见附图
彩信:
通知在pushReceiver.java里接收,然后转入TransactionService.java,根据用户设置是自动接收还是手动接收分别转入RetrieveTransactionNo.java和NotificationTransaction.java,当然最后的内容下载是要通过http的,所以这里也必然伴随着网络连接和网络状态的切换,像之前的文章说得一样,我们可打开TransactionService.java里log开关,以获得我们需要的信息。
最后,还是给出接收信息一个代码流程图,短信和彩信依然放在一起。