我是靠谱客的博主 开放信封,最近开发中收集的这篇文章主要介绍短信的接收流程,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

从RIL开始

从RIL开始,前面的分析已经知道发送短信在framework层最终是通过RILSender来进行的,接收短信也是从RIL的内部类RILReceiver开始的

class RILReceiver implements Runnable {
byte[] buffer;


RILReceiver() {
buffer = new byte[RIL_MAX_COMMAND_BYTES];
}
@Override
public void
run() {
int retryCount = 0;
String rilSocket = "rild";
try {for (;;) {
LocalSocket s = null;
LocalSocketAddress l;
....
int length = 0;
try {
// 获取输入流
InputStream is = mSocket.getInputStream();
for (;;) {
Parcel p;
length = readRilMessage(is, buffer);
if (length < 0) {
break;
}
// 获取接收到的Parcel对象
p = Parcel.obtain();
p.unmarshall(buffer, 0, length);
p.setDataPosition(0);
// 通过processResponse处理parcel对象
processResponse(p);
p.recycle();
}
} catch (java.io.IOException ex) {
} catch (Throwable tr) {
}
setRadioState (RadioState.RADIO_UNAVAILABLE);
try {
mSocket.close();
} catch (IOException ex) {
}
mSocket = null;
RILRequest.resetSerial();
clearRequestList(RADIO_NOT_AVAILABLE, false);
}} catch (Throwable tr) {
}
notifyRegistrantsRilConnectionChanged(-1);
}
}

RIL#processResponse

private void
processResponse (Parcel p) {
int type;
type = p.readInt();
if (type == RESPONSE_UNSOLICITED) {
// 处理当前parcel对象
processUnsolicited (p);
} else if (type == RESPONSE_SOLICITED) {
RILRequest rr = processSolicited (p);
if (rr != null) {
rr.release();
decrementWakeLock();
}
}
}

这里有2种type.一种是主动上报,比如网络状态,短信,来电等都不需要经过请求,用unsolicited词语专门描述。RESPONSE_SOLICITED是必须先请求然后才响应的类型。当然这里是短信接收肯定会走前者。processUnsolicited该方法会根据当前的请求的类型,如果是短信则是RIL_UNSOL_RESPONSE_NEW_SMS,以下是其调用的代码;

private void
processUnsolicited (Parcel p) {
int response;
Object ret;
response = p.readInt();
try {switch(response) {
....
case RIL_UNSOL_RESPONSE_NEW_SMS: ret =
responseString(p); break;
default:
throw new RuntimeException("Unrecognized unsol response: " + response);
}} catch (Throwable tr) {
return;
}
switch(response) {
....
case RIL_UNSOL_RESPONSE_NEW_SMS: {
String a[] = new String[2];
a[1] = (String)ret;
SmsMessage sms;
// 在SmsMessage.newFromCMT实现真正的实现PDU decode
sms = SmsMessage.newFromCMT(a);
if (mGsmSmsRegistrant != null) {
mGsmSmsRegistrant
.notifyRegistrant(new AsyncResult(null, sms, null));
}
break;
}
....
}
}

这里RIL继承自BaseCommands,mGsmSmsRegistrant是BaseCommands中的属性,另外关于PDU解析的文章,这里又一篇很赞的博客:PDU解析

Registrant#notifyRegistrant

public class Registrant
public
Registrant(Handler h, int what, Object obj)
{
refH = new WeakReference(h);
this.what = what;
userObj = obj;
}
public void
notifyRegistrant(AsyncResult ar)
{
internalNotifyRegistrant (ar.result, ar.exception);
}
/*package*/ void
internalNotifyRegistrant (Object result, Throwable exception)
{
Handler h = getHandler();
if (h == null) {
clear();
} else {
Message msg = Message.obtain();
msg.what = what;
msg.obj = new AsyncResult(userObj, result, exception);
h.sendMessage(msg);
}
}
public Handler
getHandler()
{
if (refH == null)
return null;
return (Handler) refH.get();
}
}

上面可以看到会发送一条消息给到自己的handler处理,那么是具体哪个handler处理呢,看下mGsmSmsRegistrant的初始化的地方

BaseCommands#setOnNewGsmSms

@Override
public void setOnNewGsmSms(Handler h, int what, Object obj) {
mGsmSmsRegistrant = new Registrant (h, what, obj);
}
@Override
public void setOnNewCdmaSms(Handler h, int what, Object obj) {
mCdmaSmsRegistrant = new Registrant (h, what, obj);
}
....
以 CdmaInboundSmsHandler为例
private CdmaInboundSmsHandler(Context context, SmsStorageMonitor storageMonitor,
PhoneBase phone, CdmaSMSDispatcher smsDispatcher) {
super("CdmaInboundSmsHandler", context, storageMonitor, phone,
CellBroadcastHandler.makeCellBroadcastHandler(context, phone));
mSmsDispatcher = smsDispatcher;
mServiceCategoryProgramHandler = CdmaServiceCategoryProgramHandler.makeScpHandler(context,
phone.mCi);
//
phone.mCi.setOnNewCdmaSms(getHandler(), EVENT_NEW_SMS, null);
}

最终”EVENT_NEW_SMS”消息会发送到InboundSmsHandler的内部DeliveringState处理

class DeliveringState extends State {
....
@Override
public boolean processMessage(Message msg) {
switch (msg.what) {
case EVENT_NEW_SMS:
// handle new SMS from RIL
handleNewSms((AsyncResult) msg.obj);
sendMessage(EVENT_RETURN_TO_IDLE);
return HANDLED;
....
}

InboundSmsHandler#handleNewSms

void handleNewSms(AsyncResult ar) {
int result;
try {
SmsMessage sms = (SmsMessage) ar.result;
// 分发消息
result = dispatchMessage(sms.mWrappedSmsMessage);
} catch (RuntimeException ex) {
result = Intents.RESULT_SMS_GENERIC_ERROR;
}
}
}

InboundSmsHandler#dispatchMessage

public int dispatchMessage(SmsMessageBase smsb) {
// 当前设备不支持接收短信
if (mSmsReceiveDisabled) {
return Intents.RESULT_SMS_HANDLED;
}
// 通过dispatchMessageRadioSpecific分发SmsMessageBase
return dispatchMessageRadioSpecific(smsb);
}
dispatchMessageRadioSpecific是一个抽象方法,是在具体的GsmInboundSmsHandler/CdmaInboundSmsHandler实现的
GsmInboundSmsHandler/CdmaInboundSmsHandler#dispatchMessageRadioSpecific
@Override
protected int dispatchMessageRadioSpecific(SmsMessageBase smsb) {
SmsMessage sms = (SmsMessage) smsb;
boolean isBroadcastType = (SmsEnvelope.MESSAGE_TYPE_BROADCAST == sms.getMessageType());
// 处理CMAS紧急广播
if (isBroadcastType) {
SmsCbMessage cbMessage = sms.parseBroadcastSms();
if (cbMessage != null) {
mCellBroadcastHandler.dispatchSmsMessage(cbMessage);
} else {
loge("error trying to parse broadcast SMS");
}
return Intents.RESULT_SMS_HANDLED;
}
....
// dispatchNormalMessage这个就是我们接收到的短信
return dispatchNormalMessage(smsb);
}

InboundSmsHandler#dispatchNormalMessage

protected int dispatchNormalMessage(SmsMessageBase sms) {
SmsHeader smsHeader = sms.getUserDataHeader();
InboundSmsTracker tracker;
if ((smsHeader == null) || (smsHeader.concatRef == null)) {
// Message is not concatenated.
int destPort = -1;
if (smsHeader != null && smsHeader.portAddrs != null) {
// The message was sent to a port.
destPort = smsHeader.portAddrs.destPort;
if (DBG) log("destination port: " + destPort);
}
// 将解析出来的pdu封装成InboundSmsTracker
tracker = new InboundSmsTracker(sms.getPdu(), sms.getTimestampMillis(), destPort,
is3gpp2(), false);
} else {
// Create a tracker for this message segment.
SmsHeader.ConcatRef concatRef = smsHeader.concatRef;
SmsHeader.PortAddrs portAddrs = smsHeader.portAddrs;
int destPort = (portAddrs != null ? portAddrs.destPort : -1);
tracker = new InboundSmsTracker(sms.getPdu(), sms.getTimestampMillis(), destPort,
is3gpp2(), sms.getOriginatingAddress(), concatRef.refNumber,
concatRef.seqNumber, concatRef.msgCount, false);
}
// 将tracker添加进raw表里,同时发送消息
return addTrackerToRawTableAndSendMessage(tracker);
}

InboundSmsHandler#addTrackerToRawTableAndSendMessage

protected int addTrackerToRawTableAndSendMessage(InboundSmsTracker tracker) {
switch(addTrackerToRawTable(tracker)) {//addTrackerToRawTable(tracker) 插入当前tracker解析的pdu到raw表里
case Intents.RESULT_SMS_HANDLED:
sendMessage(EVENT_BROADCAST_SMS, tracker); //发送EVENT_BROADCAST_SMS消息,此时会在InboundSmsHandler$DeliveringState中处理

return Intents.RESULT_SMS_HANDLED;
case Intents.RESULT_SMS_DUPLICATED:
return Intents.RESULT_SMS_HANDLED;
case Intents.RESULT_SMS_GENERIC_ERROR:
default:
return Intents.RESULT_SMS_GENERIC_ERROR;
}
}
class DeliveringState extends State {
@Override
public boolean processMessage(Message msg) {
....
case EVENT_BROADCAST_SMS:
// if any broadcasts were sent, transition to waiting state
InboundSmsTracker inboundSmsTracker = (InboundSmsTracker) msg.obj;
if (processMessagePart(inboundSmsTracker)) {
transitionTo(mWaitingState);
} else {
sendMessage(EVENT_RETURN_TO_IDLE);
}
return HANDLED;
....
}
}

InboundSmsHandler#processMessagePart

boolean processMessagePart(InboundSmsTracker tracker) {
int messageCount = tracker.getMessageCount();
byte[][] pdus;
int destPort = tracker.getDestPort();
if (messageCount == 1) {
// 单条短信
pdus = new byte[][]{tracker.getPdu()};
} else {
// 多条短信
....
}
// 创建一个广播接收者
SmsBroadcastReceiver resultReceiver = new SmsBroadcastReceiver(tracker);
// 如果是WAP_PUSH
if (destPort == SmsHeader.PORT_WAP_PUSH) {
// Build up the data stream
ByteArrayOutputStream output = new ByteArrayOutputStream();
for (byte[] pdu : pdus) {
if (!tracker.is3gpp2()) {
SmsMessage msg = SmsMessage.createFromPdu(pdu, SmsConstants.FORMAT_3GPP);
pdu = msg.getUserData();
}
output.write(pdu, 0, pdu.length);
}
int result = mWapPush.dispatchWapPdu(output.toByteArray(), resultReceiver, this);
// result is Activity.RESULT_OK if an ordered broadcast was sent
if (result == Activity.RESULT_OK) {
return true;
} else {
deleteFromRawTable(tracker.getDeleteWhere(), tracker.getDeleteWhereArgs());
return false;
}
}
....
// 通过 dispatchSmsDeliveryIntent方法,传递创建的广播接收者 
dispatchSmsDeliveryIntent(pdus, tracker.getFormat(), destPort, resultReceiver);
....
return true;
}

InboundSmsHandler#dispatchSmsDeliveryIntent

void dispatchSmsDeliveryIntent(byte[][] pdus, String format, int destPort,
BroadcastReceiver resultReceiver) {
Intent intent = new Intent();
intent.putExtra("pdus", pdus);
intent.putExtra("format", format);
// 设置当前intent的action为SMS_DELIVER_ACTION
intent.setAction(Intents.SMS_DELIVER_ACTION);
....
Bundle options = handleSmsWhitelisting(intent.getComponent());
dispatchIntent(intent, android.Manifest.permission.RECEIVE_SMS,
AppOpsManager.OP_RECEIVE_SMS, options, resultReceiver, UserHandle.OWNER);
}

InboundSmsHandler#dispatchIntent

protected void dispatchIntent(Intent intent, String permission, int appOp,
Bundle opts, BroadcastReceiver resultReceiver, UserHandle user) {
intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT);
SubscriptionManager.putPhoneIdAndSubIdExtra(intent, mPhone.getPhoneId());
// 发送SMS_DELIVER_ACTION的intent到SmsBroadcastReceiver
mContext.sendOrderedBroadcastAsUser(intent, user, permission, appOp, opts,
resultReceiver, getHandler(), Activity.RESULT_OK, null, null);
}

InboundSmsHandler内部类SmsBroadcastReceiver

private final class SmsBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (action.equals(Intents.SMS_DELIVER_ACTION)) {
intent.setAction(Intents.SMS_RECEIVED_ACTION);
intent.setComponent(null);
Bundle options = handleSmsWhitelisting(null);
// 发送SMS_RECEIVED_ACTION的广播
dispatchIntent(intent, android.Manifest.permission.RECEIVE_SMS,
AppOpsManager.OP_RECEIVE_SMS, options, this, UserHandle.ALL);
}
}

至此就发送到了我们的应用接收层,在应用层注册具有Intents.SMS_RECEIVED_ACTION这样action的广播就可以监听短信的接收了。

最后

以上就是开放信封为你收集整理的短信的接收流程的全部内容,希望文章能够帮你解决短信的接收流程所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(55)

评论列表共有 0 条评论

立即
投稿
返回
顶部