短信发送Framework流程,源代码的版本是4.4
1、通过Mms源代码可以知道短信发送最后调用的关键api如下:
SmsSingleRecipientSender.java
SmsManager smsManager = SmsManager.getDefault();
...
try {
smsManager.sendMultipartTextMessage(mDest, mServiceCenter, messages, sentIntents, deliveryIntents);
} catch (Exception ex) {
Log.e(TAG, "SmsMessageSender.sendMessage: caught", ex);
throw new MmsException("SmsMessageSender.sendMessage: caught " + ex +
" from SmsManager.sendTextMessage()");
}
...
smsManager对应的文件是SmsManager.java
2、SmsManager源代码路径是frameworks/opt/telephony/src/java/android/telephony/gsm/SmsManager.java
SmsManager这里用了单例模式初始化
/** Singleton object constructed during class initialization. */
private static final SmsManager sInstance = new SmsManager();
/**
* Get the default instance of the SmsManager
*
* @return the default instance of the SmsManager
*/
public static SmsManager getDefault() {
return sInstance;
}
sendMultipartTextMessage的实现如下:
public void sendMultipartTextMessage(
String destinationAddress, String scAddress, ArrayList<String> parts,
ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents) {
if (TextUtils.isEmpty(destinationAddress)) {
throw new IllegalArgumentException("Invalid destinationAddress");
}
if (parts == null || parts.size() < 1) {
throw new IllegalArgumentException("Invalid message body");
}
if (parts.size() > 1) {
try {
ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
if (iccISms != null) {
iccISms.sendMultipartText(ActivityThread.currentPackageName(),
destinationAddress, scAddress, parts,
sentIntents, deliveryIntents);
}
} catch (RemoteException ex) {
// ignore it
}
} else {
PendingIntent sentIntent = null;
PendingIntent deliveryIntent = null;
if (sentIntents != null && sentIntents.size() > 0) {
sentIntent = sentIntents.get(0);
}
if (deliveryIntents != null && deliveryIntents.size() > 0) {
deliveryIntent = deliveryIntents.get(0);
}
sendTextMessage(destinationAddress, scAddress, parts.get(0),
sentIntent, deliveryIntent);
}
}
如果短信的内容被划分成了多个部分,将进入icc.sendMultipartText(),即如下
try {
ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"));
if (iccISms != null) {
iccISms.sendMultipartText(ActivityThread.currentPackageName(),
destinationAddress, scAddress, parts,
sentIntents, deliveryIntents);
}
} catch (RemoteException ex) {
// ignore it
}
如果短信的内容只有一部分,则继续调用sendTextMessage(),即如下
PendingIntent sentIntent = null;
PendingIntent deliveryIntent = null;
if (sentIntents != null && sentIntents.size() > 0) {
sentIntent = sentIntents.get(0);
}
if (deliveryIntents != null && deliveryIntents.size() > 0) {
deliveryIntent = deliveryIntents.get(0);
}
sendTextMessage(destinationAddress, scAddress, parts.get(0),
sentIntent, deliveryIntent);
下面的流程主要针对sendTextMessage( )分析,sendMultipartText到此为止。
短信在发送之前会检查发送字符串是否超过最大长度,如果超过会被划分成几部分,对应这里的ArrayList<string> parts,
划分的具体实现对应smsManager.divideMessage(mMsgText)
/**
* Divide a message text into several fragments, none bigger than
* the maximum SMS message size.
*
* @param text the original message. Must not be null.
* @return an <code>ArrayList</code> of strings that, in order,
* comprise the original message
*
* @throws IllegalArgumentException if text is null
*/
public ArrayList<String> divideMessage(String text) {
if (null == text) {
throw new IllegalArgumentException("text is null");
}
return SmsMessage.fragmentText(text);
}
很明显这里调用SmsMessage.fragmentText()
SmsMessage的路径是frameworks/opt/telephony/src/java/android/telephony/SmsMessage.java
fragmentText的具体实现如下:
/**
* Divide a message text into several fragments, none bigger than
* the maximum SMS message text size.
*
* @param text text, must not be null.
* @return an <code>ArrayList</code> of strings that, in order,
* comprise the original msg text
*
* @hide
*/
public static ArrayList<String> fragmentText(String text) {
// This function is for MO SMS
TextEncodingDetails ted = (useCdmaFormatForMoSms()) ?
com.android.internal.telephony.cdma.SmsMessage.calculateLength(text, false) :
com.android.internal.telephony.gsm.SmsMessage.calculateLength(text, false);
// TODO(cleanup): The code here could be rolled into the logic
// below cleanly if these MAX_* constants were defined more
// flexibly...
int limit;
if (ted.codeUnitSize == SmsConstants.ENCODING_7BIT) {
int udhLength;
if (ted.languageTable != 0 && ted.languageShiftTable != 0) {
udhLength = GsmAlphabet.UDH_SEPTET_COST_TWO_SHIFT_TABLES;
} else if (ted.languageTable != 0 || ted.languageShiftTable != 0) {
udhLength = GsmAlphabet.UDH_SEPTET_COST_ONE_SHIFT_TABLE;
} else {
udhLength = 0;
}
if (ted.msgCount > 1) {
udhLength += GsmAlphabet.UDH_SEPTET_COST_CONCATENATED_MESSAGE;
}
if (udhLength != 0) {
udhLength += GsmAlphabet.UDH_SEPTET_COST_LENGTH;
}
limit = SmsConstants.MAX_USER_DATA_SEPTETS - udhLength;
} else {
if (ted.msgCount > 1) {
limit = SmsConstants.MAX_USER_DATA_BYTES_WITH_HEADER;
} else {
limit = SmsConstants.MAX_USER_DATA_BYTES;
}
}
int pos = 0; // Index in code units.
int textLen = text.length();
ArrayList<String> result = new ArrayList<String>(ted.msgCount);
while (pos < textLen) {
int nextPos = 0; // Counts code units.
if (ted.codeUnitSize == SmsConstants.ENCODING_7BIT) {
if (useCdmaFormatForMoSms() && ted.msgCount == 1) {
// For a singleton CDMA message, the encoding must be ASCII...
nextPos = pos + Math.min(limit, textLen - pos);
} else {
// For multi-segment messages, CDMA 7bit equals GSM 7bit encoding (EMS mode).
nextPos = GsmAlphabet.findGsmSeptetLimitIndex(text, pos, limit,
ted.languageTable, ted.languageShiftTable);
}
} else { // Assume unicode.
nextPos = pos + Math.min(limit / 2, textLen - pos);
}
if ((nextPos <= pos) || (nextPos > textLen)) {
Rlog.e(LOG_TAG, "fragmentText failed (" + pos + " >= " + nextPos + " or " +
nextPos + " >= " + textLen + ")");
break;
}
result.add(text.substring(pos, nextPos));
pos = nextPos;
}
return result;
}
3、sendText()的实现如下:
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"));
if (iccISms != null) {
iccISms.sendText(ActivityThread.currentPackageName(), destinationAddress,
scAddress, text, sentIntent, deliveryIntent);
}
} catch (RemoteException ex) {
// ignore it
}
}
这里使用aidl的方式远程调用isms服务进行后续的发送流程,即
iccISms.sendText()
,IccSmsInterfaceManagerProxy的路径是frameworks/opt/telephony/src/java/com/android/internal/telephony/IccSmsInterfaceManagerProxy.java
关于isms服务的注册,它是在初始化phone进程时注册的
public IccSmsInterfaceManagerProxy(Context context,
IccSmsInterfaceManager iccSmsInterfaceManager) {
this.mContext = context;
mIccSmsInterfaceManager = iccSmsInterfaceManager;
if(ServiceManager.getService("isms") == null) {
ServiceManager.addService("isms", this);
}
createWakelock();
}
iccISms.sendSms()的实现如下:
@Override
public void sendText(String callingPackage, String destAddr, String scAddr,
String text, PendingIntent sentIntent, PendingIntent deliveryIntent) {
mContext.enforceCallingPermission(
android.Manifest.permission.SEND_SMS,
"Sending SMS message");
if (mIccSmsInterfaceManager.isShortSMSCode(destAddr)) {
mIccSmsInterfaceManager.sendText(callingPackage, destAddr, scAddr, text,
sentIntent, deliveryIntent);
return;
}
ArrayList<String> parts = new ArrayList<String>();
parts.add(text);
ArrayList<PendingIntent> sentIntents = new ArrayList<PendingIntent>();
sentIntents.add(sentIntent);
ArrayList<PendingIntent> deliveryIntents = new ArrayList<PendingIntent>();
deliveryIntents.add(deliveryIntent);
broadcastOutgoingSms(callingPackage, destAddr, scAddr, false, parts, sentIntents,
deliveryIntents, -1);
}
检查发送短信的APP是否有SEND_SMS权限,再调用broadcastOutgoingSms()
private void broadcastOutgoingSms(String callingPackage, String destAddr, String scAddr,
boolean multipart, ArrayList<String> parts,
ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents,
int priority) {
Intent broadcast = new Intent(Intent.ACTION_NEW_OUTGOING_SMS);
broadcast.putExtra("destAddr", destAddr);
broadcast.putExtra("scAddr", scAddr);
broadcast.putExtra("multipart", multipart);
broadcast.putExtra("callingPackage", callingPackage);
broadcast.putExtra("callingUid", android.os.Binder.getCallingUid());
broadcast.putStringArrayListExtra("parts", parts);
broadcast.putParcelableArrayListExtra("sentIntents", sentIntents);
broadcast.putParcelableArrayListExtra("deliveryIntents", deliveryIntents);
broadcast.putExtra("priority", priority);
mContext.sendOrderedBroadcastAsUser(broadcast, UserHandle.OWNER,
android.Manifest.permission.INTERCEPT_SMS,
mReceiver, null, Activity.RESULT_OK, destAddr, null);
}
发送广播,Action为ACTION_NEW_OUTGOING_SMS,广播接收器就是参数中的mReceiver,mReceiver的定义如下:
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
// check if the message was aborted
if (getResultCode() != Activity.RESULT_OK) {
return;
}
String destAddr = getResultData();
String scAddr = intent.getStringExtra("scAddr");
String callingPackage = intent.getStringExtra("callingPackage");
ArrayList<String> parts = intent.getStringArrayListExtra("parts");
ArrayList<PendingIntent> sentIntents =
intent.getParcelableArrayListExtra("sentIntents");
ArrayList<PendingIntent> deliveryIntents =
intent.getParcelableArrayListExtra("deliveryIntents");
if (intent.getIntExtra("callingUid", 0) != 0) {
callingPackage = callingPackage + "\\" + intent.getIntExtra("callingUid", 0);
}
if (intent.getBooleanExtra("multipart", false)) {
mIccSmsInterfaceManager.sendMultipartText(callingPackage, destAddr, scAddr,
parts, sentIntents, deliveryIntents);
return;
}
PendingIntent sentIntent = null;
if (sentIntents != null && sentIntents.size() > 0) {
sentIntent = sentIntents.get(0);
}
PendingIntent deliveryIntent = null;
if (deliveryIntents != null && deliveryIntents.size() > 0) {
deliveryIntent = deliveryIntents.get(0);
}
String text = null;
if (parts != null && parts.size() > 0) {
text = parts.get(0);
}
mIccSmsInterfaceManager.sendText(callingPackage, destAddr, scAddr, text,
sentIntent, deliveryIntent);
}
};
这里调用mIccSmsInterfaceManager.sendText()继续发送流程
mIccSmsInterfaceManager对应的类是IccSmsInterfaceManager,路径是
framework/opt/telephony/src/java/com/android/internal/telephony/IccSmsInterfaceManager.java
mIccSmsInterfaceManager.sendText()的实现如下:
public void sendText(String callingPackage, String destAddr, String scAddr,
String text, PendingIntent sentIntent, PendingIntent deliveryIntent) {
int callingUid = Binder.getCallingUid();
String[] callingParts = callingPackage.split("\\\\");
if (callingUid == android.os.Process.PHONE_UID &&
callingParts.length > 1) {
callingUid = Integer.parseInt(callingParts[1]);
}
if (Binder.getCallingPid() != android.os.Process.myPid()) {
mPhone.getContext().enforceCallingPermission(
Manifest.permission.SEND_SMS,
"Sending SMS message");
}
if (Rlog.isLoggable("SMS", Log.VERBOSE)) {
log("sendText: destAddr=" + destAddr + " scAddr=" + scAddr +
" text='"+ text + "' sentIntent=" +
sentIntent + " deliveryIntent=" + deliveryIntent);
}
if (mAppOps.noteOp(AppOpsManager.OP_SEND_SMS, callingUid,
callingParts[0]) != AppOpsManager.MODE_ALLOWED) {
return;
}
mDispatcher.sendText(destAddr, scAddr, text, sentIntent, deliveryIntent);
}
这里调用mDispatcher.sendText()继续发送流程
mDispatcher对应的类是SmsDispatcher,源代码的路径是
framework/opt/telephony/src/java/com/android/internal/telephony/SMSDispatcher.java
SMSDispatcher是一个abstract类,继承它的子类有CdmaSMSDispatcher、GsmSMSDispatcher和IccSMSDispatcher,
这里的mDispatcher初始化如下:
protected IccSmsInterfaceManager(PhoneBase phone) {
mPhone = phone;
mContext = phone.getContext();
mAppOps = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
mDispatcher = new ImsSMSDispatcher(phone,
phone.mSmsStorageMonitor, phone.mSmsUsageMonitor);
}
mDispatcher.sendText()是一个abstract方法,所以是在IccSMSDispatcher中实现,代码如下:
@Override
protected void sendText(String destAddr, String scAddr, String text,
PendingIntent sentIntent, PendingIntent deliveryIntent) {
Rlog.d(TAG, "sendText");
if (isCdmaMo()) {
mCdmaDispatcher.sendText(destAddr, scAddr,
text, sentIntent, deliveryIntent);
} else {
mGsmDispatcher.sendText(destAddr, scAddr,
text, sentIntent, deliveryIntent);
}
}
这里根据sim卡的类型决定调用CdmaSMSDispatcher还是GsmSMSDispatcher,这里选择Gsm继续跟进。
mGsmDispatcher对应的类是GsmSMSDispatcher,源代码路径是
framework/opt/telephony/src/java/com/android/internal/telephony/GsmSMSDispatcher.java
mGsmDispatcher.sendText()的流程如下:
@Override
protected void sendText(String destAddr, String scAddr, String text,
PendingIntent sentIntent, PendingIntent deliveryIntent) {
SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu(
scAddr, destAddr, text, (deliveryIntent != null));
if (pdu != null) {
HashMap map = getSmsTrackerMap(destAddr, scAddr, text, pdu);
SmsTracker tracker = getSmsTracker(map, sentIntent, deliveryIntent,
getFormat());
sendRawPdu(tracker);
} else {
Rlog.e(TAG, "GsmSMSDispatcher.sendText(): getSubmitPdu() returned null");
}
}
这里构造了SubmitPdu和SmsTracker对象,然后执行sendRawPdu(),这个方法是在父类SMSDiapatcher中实现的,代码如下:
protected void sendRawPdu(SmsTracker tracker) {
...
// checkDestination() returns true if the destination is not a premium short code or the
// sending app is approved to send to short codes. Otherwise, a message is sent to our
// handler with the SmsTracker to request user confirmation before sending.
if (checkDestination(tracker)) {
// check for excessive outgoing SMS usage by this app
if (!mUsageMonitor.check(appInfo.packageName, SINGLE_PART_SMS)) {
sendMessage(obtainMessage(EVENT_SEND_LIMIT_REACHED_CONFIRMATION, tracker));
return;
}
int ss = mPhone.getServiceState().getState();
// if sms over IMS is not supported on data and voice is not available...
if (!isIms() && ss != ServiceState.STATE_IN_SERVICE) {
handleNotInService(ss, tracker.mSentIntent);
} else {
sendSms(tracker);
}
}
}
这里调用sendSms()继续发送流程,sendSms()是一个abstract方法,所以这里是在子类GsmSMSDispatcher中实现的,代码如下:
@Override
protected void sendSms(SmsTracker tracker) {
HashMap<String, Object> map = tracker.mData;
byte smsc[] = (byte[]) map.get("smsc");
byte pdu[] = (byte[]) map.get("pdu");
Message reply = obtainMessage(EVENT_SEND_SMS_COMPLETE, tracker);
if (tracker.mRetryCount > 0) {
Rlog.d(TAG, "sendSms: "
+ " mRetryCount=" + tracker.mRetryCount
+ " mMessageRef=" + tracker.mMessageRef
+ " SS=" + mPhone.getServiceState().getState());
// per TS 23.040 Section 9.2.3.6: If TP-MTI SMS-SUBMIT (0x01) type
// TP-RD (bit 2) is 1 for retry
// and TP-MR is set to previously failed sms TP-MR
if (((0x01 & pdu[0]) == 0x01)) {
pdu[0] |= 0x04; // TP-RD
pdu[1] = (byte) tracker.mMessageRef; // TP-MR
}
}
Rlog.d(TAG, "sendSms: "
+" isIms()="+isIms()
+" mRetryCount="+tracker.mRetryCount
+" mImsRetry="+tracker.mImsRetry
+" mMessageRef="+tracker.mMessageRef
+" SS=" +mPhone.getServiceState().getState());
// sms over gsm is used:
// if sms over IMS is not supported AND
// this is not a retry case after sms over IMS failed
// indicated by mImsRetry > 0
if (0 == tracker.mImsRetry && !isIms()) {
if (tracker.mRetryCount > 0) {
// per TS 23.040 Section 9.2.3.6: If TP-MTI SMS-SUBMIT (0x01) type
// TP-RD (bit 2) is 1 for retry
// and TP-MR is set to previously failed sms TP-MR
if (((0x01 & pdu[0]) == 0x01)) {
pdu[0] |= 0x04; // TP-RD
pdu[1] = (byte) tracker.mMessageRef; // TP-MR
}
}
mCi.sendSMS(IccUtils.bytesToHexString(smsc),
IccUtils.bytesToHexString(pdu), reply);
} else {
mCi.sendImsGsmSms(IccUtils.bytesToHexString(smsc),
IccUtils.bytesToHexString(pdu), tracker.mImsRetry,
tracker.mMessageRef, reply);
// increment it here, so in case of SMS_FAIL_RETRY over IMS
// next retry will be sent using IMS request again.
tracker.mImsRetry++;
}
}
这里最终调用mCi.sendSms()继续发送流程,
mCi对应的类是CommandInterface,CommandInterface是一个Interface,RIL是它的一个子类,
也就是说短信发送在此处会调用RIL.java,执行sendText()方法,代码如下:
public void
sendSMS (String smscPDU, String pdu, Message result) {
RILRequest rr
= RILRequest.obtain(RIL_REQUEST_SEND_SMS, result);
constructGsmSendSmsRilRequest(rr, smscPDU, pdu);
if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
}
程序交给send(RILRequest req)继续执行,代码如下:
protected void
send(RILRequest rr) {
Message msg;
if (mSocket == null) {
rr.onError(RADIO_NOT_AVAILABLE, null);
rr.release();
return;
}
msg = mSender.obtainMessage(EVENT_SEND, rr);
acquireWakeLock();
msg.sendToTarget();
}
接下来RIL会将pdu等信息打包,通过socket发送给下层处理,最终形成at指令发送短信。
如果短信发送成功,还记得在发送时,从GsmSmsDispatcher.java传递到RIL.java中的Message吗,在发送之后,RIL.java会回调此Message,这个Message如下
Message reply = obtainMessage(EVENT_SEND_SMS_COMPLETE, tracker);
What = EVENT_SEND_SMS_COMPLETE,Object = tricker。SmsDispacher.java本身是一个Handler,所以这个Message最终在SmsDispacher.java中处理,处理逻辑代码如下:
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case EVENT_SEND_SMS_COMPLETE:
// An outbound SMS has been successfully transferred, or failed.
handleSendComplete((AsyncResult) msg.obj);
break;
handleSendComplete的实现如下:
protected void handleSendComplete(AsyncResult ar) {
SmsTracker tracker = (SmsTracker) ar.userObj;
PendingIntent sentIntent = tracker.mSentIntent;
if (ar.result != null) {
tracker.mMessageRef = ((SmsResponse)ar.result).mMessageRef;
} else {
Rlog.d(TAG, "SmsResponse was null");
}
if (ar.exception == null) {
if (DBG) Rlog.d(TAG, "SMS send complete. Broadcasting intent: " + sentIntent);
if (SmsApplication.shouldWriteMessageForPackage(
tracker.mAppInfo.applicationInfo.packageName, mContext)) {
// Persist it into the SMS database as a sent message
// so the user can see it in their default app.
tracker.writeSentMessage(mContext);
}
if (tracker.mDeliveryIntent != null) {
// Expecting a status report. Add it to the list.
deliveryPendingList.add(tracker);
}
if (sentIntent != null) {
try {
if (mRemainingMessages > -1) {
mRemainingMessages--;
}
if (mRemainingMessages == 0) {
Intent sendNext = new Intent();
sendNext.putExtra(SEND_NEXT_MSG_EXTRA, true);
sentIntent.send(mContext, Activity.RESULT_OK, sendNext);
} else {
sentIntent.send(Activity.RESULT_OK);
}
} catch (CanceledException ex) {}
}
} else {
if (DBG) Rlog.d(TAG, "SMS send failed");
int ss = mPhone.getServiceState().getState();
if ( tracker.mImsRetry > 0 && ss != ServiceState.STATE_IN_SERVICE) {
// This is retry after failure over IMS but voice is not available.
// Set retry to max allowed, so no retry is sent and
// cause RESULT_ERROR_GENERIC_FAILURE to be returned to app.
tracker.mRetryCount = MAX_SEND_RETRIES;
Rlog.d(TAG, "handleSendComplete: Skipping retry: "
+" isIms()="+isIms()
+" mRetryCount="+tracker.mRetryCount
+" mImsRetry="+tracker.mImsRetry
+" mMessageRef="+tracker.mMessageRef
+" SS= "+mPhone.getServiceState().getState());
}
// if sms over IMS is not supported on data and voice is not available...
if (!isIms() && ss != ServiceState.STATE_IN_SERVICE) {
handleNotInService(ss, tracker.mSentIntent);
} else if ((((CommandException)(ar.exception)).getCommandError()
== CommandException.Error.SMS_FAIL_RETRY) &&
tracker.mRetryCount < MAX_SEND_RETRIES) {
// Retry after a delay if needed.
// TODO: According to TS 23.040, 9.2.3.6, we should resend
// with the same TP-MR as the failed message, and
// TP-RD set to 1. However, we don't have a means of
// knowing the MR for the failed message (EF_SMSstatus
// may or may not have the MR corresponding to this
// message, depending on the failure). Also, in some
// implementations this retry is handled by the baseband.
tracker.mRetryCount++;
Message retryMsg = obtainMessage(EVENT_SEND_RETRY, tracker);
sendMessageDelayed(retryMsg, SEND_RETRY_DELAY);
} else if (tracker.mSentIntent != null) {
int error = RESULT_ERROR_GENERIC_FAILURE;
if (((CommandException)(ar.exception)).getCommandError()
== CommandException.Error.FDN_CHECK_FAILURE) {
error = RESULT_ERROR_FDN_CHECK_FAILURE;
}
// Done retrying; return an error to the app.
try {
Intent fillIn = new Intent();
if (ar.result != null) {
fillIn.putExtra("errorCode", ((SmsResponse)ar.result).mErrorCode);
}
if (mRemainingMessages > -1) {
mRemainingMessages--;
}
if (mRemainingMessages == 0) {
fillIn.putExtra(SEND_NEXT_MSG_EXTRA, true);
}
tracker.mSentIntent.send(mContext, error, fillIn);
} catch (CanceledException ex) {}
}
}
}
至此就是短信发送的在framework中的大体流程
首先检查AsyncResult对象中是否存在异常,如果成功发送的信息,那么不存在异常,如果发送失败,那么是存在Exception的,会进行异常的相应的逻辑处理,大体流程相似,故本处介绍无异常时的流程逻辑。
if (SmsApplication.shouldWriteMessageForPackage(
tracker.mAppInfo.applicationInfo.packageName, mContext)) {
// Persist it into the SMS database as a sent message
// so the user can see it in their default app.
tracker.writeSentMessage(mContext);
}
这里判断发送短信的app是否是默认短信,如果不是则保存该条短信到TelephonyProvider中。
最后会发送一个广播,这个广播的intent是PendingIntent,是在Mms中构造的,SmsReceiverService.java会接受该广播并处理
,比如保存短信的状态,失败或者发送成功
发送流程大概就是这样了。