详细解析短息发送流程:
1、上层开发调用的接口函数:SmsManager.getDefault().sendTextMessage()
函数实现:
public void sendTextMessage(
String destinationAddress, String scAddress, String text,
PendingIntent sentIntent, PendingIntent deliveryIntent) {
if (TextUtils.isEmpty(destinationAddress)) {
throw new IllegalArgumentException("Invalid destinationAddress");
}
if (TextUtils.isEmpty(text)) {
throw new IllegalArgumentException("Invalid message body");
}
try {
ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));// 在Binder注册服务,通过iccISms调用底层接口
if (iccISms != null) {
iccISms.sendText(destinationAddress, scAddress, text, sentIntent, deliveryIntent);// 调用底层函数
}
} catch (RemoteException ex) {
// ignore it
}
}
2、Isms中处理sendText
到ISms.java中查找此函数发现有两个,尴尬,为什么会有两个?
有一个是:iccISms.sendText
另一个是:Proxy:sendText
明白了,一看就知道我们要的是第一个。但是当我们查看第一个函数的时候发现没有实现。。。为什么呢?这时候就要说到一个机制:Binder,这里就是它在捣鬼。这里给我们提供的接口就是Binder客户端的接口,具体实现是在Binder的服务。
3、寻找Binder服务中哪里实现的sendText
sendText是在SMSDispatcher.java文件中,但是他的实现是在GsmSMSDispatcher.java或者CdmaSMSDispatcher.java文件中。
protected void sendText(String destAddr, String scAddr, String text,
PendingIntent sentIntent, PendingIntent deliveryIntent)
{
SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu(
scAddr, destAddr, text, (deliveryIntent != null));
sendRawPdu(pdu.encodedScAddress, pdu.encodedMessage, sentIntent, deliveryIntent);
}
4、sendRawPdu这个函数又返回到SMSDispatcher.java文件中,
protected void sendRawPdu(byte[] smsc, byte[] pdu, PendingIntent sentIntent,
PendingIntent deliveryIntent)
{
if (pdu == null)
{
if (sentIntent != null)
{
try
{
sentIntent.send(RESULT_ERROR_NULL_PDU);
} catch (CanceledException ex) {}
}
return;
}
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("smsc", smsc);
map.put("pdu", pdu);
SmsTracker tracker = new SmsTracker(map, sentIntent,
deliveryIntent);
int ss = mPhone.getServiceState().getState();
if (ss != ServiceState.STATE_IN_SERVICE) {
handleNotInService(ss, tracker);
} else {
String appName = getAppNameByIntent(sentIntent);
if (mCounter.check(appName, SINGLE_PART_SMS)) {
sendSms(tracker);
} else {
sendMessage(obtainMessage(EVENT_POST_ALERT, tracker));
}
}
}
5、sendSms看到这个函数感觉离真正干活的地方不远了。此函数又跑到GsmSMSDispatcher.java或者CdmaSMSDispatcher.java文件中了,说明两个网的实现方式还有有一定差异的。
protected void sendSms(SmsTracker tracker) {
HashMap map = tracker.mData;
byte smsc[] = (byte[]) map.get("smsc");
byte pdu[] = (byte[]) map.get("pdu");
Message reply = obtainMessage(EVENT_SEND_SMS_COMPLETE, tracker);
mCm.sendSMS(IccUtils.bytesToHexString(smsc),
IccUtils.bytesToHexString(pdu), reply);
}
有必要说一下mCm这个成员变量,比变量声明为:CommandsInterface,(怎么跑出来这么个东西?)这个是Ril层的接口层,里边提供了Ril实现的功能。
看到这里我们就可以跨过Ril机制了,直接找我们想要的功能实现。CommandsInterface.java只是提供接口,具体实现在Ril.java中。
6、sendSMS此函数在Ril.java中,看看怎么实现的。(这是什么东西,没看明白)
public void
sendSMS (String smscPDU, String pdu, Message result) {
RILRequest rr
= RILRequest.obtain(RIL_REQUEST_SEND_SMS, result);
rr.mp.writeInt(2);
rr.mp.writeString(smscPDU);
rr.mp.writeString(pdu);
if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
}
Ril.java中的实现方式基本都是一个样子,就是send(rr),这其实是Ril的机制,Ril.java其实是Rild的一个代理,他负责给Rild发消息,通知他去做具体的操作。
7、看看谁处理了RIL_REQUEST_SEND_SMS这个消息就知道谁在干活了。
onRequest
此函数就是处理消息的函数。对应case RIL_REQUEST_SEND_SMS会调用相应的函数requestSendSMS(data, datalen, t);
8、再往下看就是如何将请求编辑成AT命令发送给cp层了,这样就是Ril的真正意义。没必要再写了。