短信发送状态报告流程分析
//应用层分析:
//SmsSingleRecipientSender.java
public boolean sendMessage(long token) throws MmsException {
if (mMessageText == null) {
// Don't try to send an empty message, and destination should be just
// one.
throw new MmsException("Null message body or have multiple destinations.");
}
SmsManager smsManager = SmsManager.getDefault();
ArrayList<String> messages = null;
if ((MmsConfig.getEmailGateway() != null) &&
(Mms.isEmailAddress(mDest) || MessageUtils.isAlias(mDest))) {
String msgText;
msgText = mDest + " " + mMessageText;
mDest = MmsConfig.getEmailGateway();
messages = smsManager.divideMessage(msgText);
} else {
messages = smsManager.divideMessage(mMessageText);
// remove spaces from destination number (e.g. "801 555 1212" -> "8015551212")
mDest = mDest.replaceAll(" ", "");
}
int messageCount = messages.size();
if (messageCount == 0) {
// Don't try to send an empty message.
throw new MmsException("SmsMessageSender.sendMessage: divideMessage returned " +
"empty messages. Original message is \"" + mMessageText + "\"");
}
boolean moved = Sms.moveMessageToFolder(mContext, mUri, Sms.MESSAGE_TYPE_OUTBOX, 0);
if (!moved) {
throw new MmsException("SmsMessageSender.sendMessage: couldn't move message " +
"to outbox: " + mUri);
}
ArrayList<PendingIntent> deliveryIntents = new ArrayList<PendingIntent>(messageCount);
ArrayList<PendingIntent> sentIntents = new ArrayList<PendingIntent>(messageCount);
for (int i = 0; i < messageCount; i++) {
if (mRequestDeliveryReport) {
// TODO: Fix: It should not be necessary to
// specify the class in this intent. Doing that
// unnecessarily limits customizability.
deliveryIntents.add(PendingIntent.getBroadcast( //设置回执状态报告intent
mContext, 0,
new Intent(
MessageStatusReceiver.MESSAGE_STATUS_RECEIVED_ACTION, //底层发出的状态报告消息
mUri,
mContext,
MessageStatusReceiver.class), //接收消息:MessageStatusReceiver. MESSAGE_STATUS_RECEIVED_ACTION,
0));
}
Intent intent = new Intent(SmsReceiverService.MESSAGE_SENT_ACTION,
mUri,
mContext,
SmsReceiver.class);
int requestCode = 0;
if (i == messageCount -1) {
// Changing the requestCode so that a different pending intent
// is created for the last fragment with
// EXTRA_MESSAGE_SENT_SEND_NEXT set to true.
requestCode = 1;
intent.putExtra(SmsReceiverService.EXTRA_MESSAGE_SENT_SEND_NEXT, true);
}
sentIntents.add(PendingIntent.getBroadcast(mContext, requestCode, intent, 0));
}
try {
smsManager.sendMultipartTextMessage(mDest, mServiceCenter, messages, sentIntents, deliveryIntents/*在下发短信时设置deliveryIntents*/); //注意此处
} catch (Exception ex) {
throw new MmsException("SmsMessageSender.sendMessage: caught " + ex +
" from SmsManager.sendTextMessage()");
}
if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {
log("sendMessage: address=" + mDest + ", threadId=" + mThreadId +
", uri=" + mUri + ", msgs.count=" + messageCount);
}
return false;
}
//应用层接收短信状态信息,并更新数据库
//MessageStatusReceiver.java
public void onReceive(Context context, Intent intent) {
mContext = context;
if (MESSAGE_STATUS_RECEIVED_ACTION.equals(intent.getAction())) {
Uri messageUri = intent.getData();
byte[] pdu = (byte[]) intent.getExtra("pdu");
SmsMessage message = updateMessageStatus(context, messageUri, pdu);//更新短信状态:数据库SMS表status字段,状态报告取值:
/*STATUS_NONE = -1;
STATUS_COMPLETE = 0;
STATUS_PENDING = 32;
STATUS_FAILED = 64;
*/
// Called on the UI thread so don't block.
if (message.getStatus() < Sms.STATUS_PENDING)
MessagingNotification.nonBlockingUpdateNewMessageIndicator(context,
true, message.isStatusReportMessage());
}
}
//框架层分析:
//SMSDispatcher.java
@Override
public void handleMessage(Message msg) {
AsyncResult ar;
switch (msg.what) {
case EVENT_NEW_SMS_STATUS_REPORT:
handleStatusReport((AsyncResult)msg.obj); //转到派生类GsmSMSDispatcher.java中处理
break;
}
}
//GsmSMSDispatcher.java
@Override
protected void handleStatusReport(AsyncResult ar) {
String pduString = (String) ar.result;
SmsMessage sms = SmsMessage.newFromCDS(pduString);
int tpStatus = sms.getStatus();
if (sms != null) {
int messageRef = sms.messageRef;
for (int i = 0, count = deliveryPendingList.size(); i < count; i++) {
//deliveryPendingList定义在父类SMSDispatcher.java中,并在handleSendComplete函数里对每个短信发送完成后获取状态信息:
/*if (tracker.mDeliveryIntent != null) {
// Expecting a status report. Add it to the list.
int messageRef = ((SmsResponse)ar.result).messageRef;
tracker.mMessageRef = messageRef;
deliveryPendingList.add(tracker);
}*/
//
SmsTracker tracker = deliveryPendingList.get(i);
if (tracker.mMessageRef == messageRef) {
// Found it. Remove from list and broadcast.
if(tpStatus >= Sms.STATUS_FAILED || tpStatus < Sms.STATUS_PENDING ) {
deliveryPendingList.remove(i);
}
PendingIntent intent = tracker.mDeliveryIntent;
Intent fillIn = new Intent();
fillIn.putExtra("pdu", IccUtils.hexStringToBytes(pduString));
fillIn.putExtra("encoding", getEncoding());
try {
intent.send(mContext, Activity.RESULT_OK, fillIn);
} catch (CanceledException ex) {}
// Only expect to see one tracker matching this messageref
break;
}
}
}
acknowledgeLastIncomingSms(true, Intents.RESULT_SMS_HANDLED, null);
}