mWorkingMessage中具體發送短信的工作在preSendSmsWorker方法里面 private void preSendSmsWorker(Conversation conv, String msgText, String recipientsInUI, int subId, boolean hasBeenSplit) { // just do a regular send. We’re already on a non-ui thread so no need to fire // off another thread to do this work. /// M: Code analyze 047, For new feature ALPS00316567, add a parameter for msim . @{ sendSmsWorker是最主要的類,做了實際的發送工作,但他里面不是立即發送短信,而是發送短信的請求封裝成SmsMessageSender, sendSmsWorker(msgText, semiSepRecipients, threadId, subId)? /// @} … } . SmsReceiverService SmsMessageSender******************************************* 將待發送的短信存儲到數據庫表格中,content://sms/queued 然后再啟動服務SmsReceiverService,讓服務去單個發送每一條短信,SmsReceiverService重待發送短信表格中取出一條短信,然后交由 SmsSingleRecipientSender去發送。
MessageSender sender = new SmsMessageSender(mActivity, dests, msgText, threadId, subId)?短信發送處理public boolean sendMessage(long token) throws MmsException {
號碼處理,將其中的空格去除。得到有效的發送號碼。
生成2個廣播1.發送報告廣播,2.發送短信廣播
最終調用系統接口SmsManager smsManager = SmsManager.getSmsManagerForSubscriptionId(mSubId)?
SmsManager***************************************************************************************************publicvoidsendMultipartTextMessage(String destinationAddress, String scAddress, ArrayList<String> parts,ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents) {if (parts.size() > 1) {try {ISms iccISms = ISms.Stub.asInterface(ServiceManager.getService("isms"))?if (iccISms != null) {iccISms.sendMultipartText(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)?}
****************************************************************************
ISms.Stub.asInterface(ServiceManager.getService("isms"))?,這個的服務類型有多種,
發送彩信********************************************************************************************
sendMmsWorker(spliter.getMMSConversation(),mmsUri, persister, slideshow, sendReq, subId)?
/// M: Code analyze 047, For new feature ALPS00316567, add a parameter for msim . @{privatevoidsendSmsWorker(String msgText, String semiSepRecipients, long threadId, int subId) {/// @}String[] dests = TextUtils.split(semiSepRecipients, "?")?if (LogTag.VERBOSE || Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {Log.d(LogTag.TRANSACTION, "sendSmsWorker sending message: recipients=" +semiSepRecipients + ", threadId=" + threadId)?}MessageSender sender = new SmsMessageSender(mActivity, dests, msgText, threadId, subId)?try {sender.sendMessage(threadId)?// Make sure this thread isn't over the limits in message countRecycler.getSmsRecycler().deleteOldMessagesByThreadId(mActivity, threadId)?} catch (Exception e) {Log.e(TAG, "Failed to send SMS message, threadId=" + threadId, e)?}mStatusListener.onMessageSent()?MmsWidgetProvider.notifyDatasetChanged(mActivity)?} public boolean sendMessage(long token) throws MmsException {// In order to send the message one by one, instead of sending now, the message will split,// and be put into the queue along with each destinationsreturn queueMessage(token)?}private boolean queueMessage(long token) throws MmsException {/// M:MmsLog.v(MmsApp.TXN_TAG, "queueMessage()")?if ((mMessageText == null) || mMessageText.isEmpty() || (mNumberOfDests == 0)) {// Don't try to send an empty message.thrownew MmsException("Null message body or dest.")?}SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext)?boolean requestDeliveryReport = prefs.getBoolean(mSubId + "_" + SmsPreferenceActivity.SMS_DELIVERY_REPORT_MODE,DEFAULT_DELIVERY_REPORT_MODE)?MmsLog.d(MmsApp.TXN_TAG, "SMS DR request=" + requestDeliveryReport)?/// @}Uri smsUri = null?//star os add by liuweibolong timeStamp = System.currentTimeMillis()?for (int i = 0? i < mNumberOfDests? i++) {try {if (LogTag.DEBUG_SEND) {Log.v(TAG, "queueMessage mDests[i]: " + mDests[i] + " mThreadId: " + mThreadId)?}smsUri = mOpSmsMessageSender.queueMessage(mNumberOfDests,//star os modify by liuweibomContext.getContentResolver(), mDests[i], mMessageText, mTimestamp,requestDeliveryReport, mThreadId, mSubId, -timeStamp)?if (smsUri == null) {smsUri=Sms.addMessageToUri(mSubId,//star os modify by liuweibomContext.getContentResolver(),Uri.parse("content://sms/queued"), mDests[i],mMessageText, null, mTimestamp,true/* read */,requestDeliveryReport,mThreadId)?}//star os add start by liuweiboIntent sentIt = new Intent("delay_send_sms", null, mContext,SmsReceiver.class)?long msgId = Integer.valueOf(smsUri.toString().substring(14))?sentIt.putExtra("message_id", msgId)?mContext.sendBroadcast(sentIt)?//star os add end by liuweibo} catch (SQLiteException e) {if (LogTag.DEBUG_SEND) {Log.e(TAG, "queueMessage SQLiteException", e)?}SqliteWrapper.checkSQLiteException(mContext, e)?}}// Notify the SmsReceiverService to send the message out//star os del start by liuweibo/*mContext.sendBroadcast(new Intent(SmsReceiverService.ACTION_SEND_MESSAGE,null,mContext,SmsReceiver.class))?*///star os del end by liuweiboreturnfalse?}
/frameworks/opt/telephony/src/java/android/telephony/SmsManager.java
sendStoredMultimediaMessage
/*** Send a system stored MMS message** This is used for sending a previously sent, but failed-to-send, message or* for sending a text message that has been stored as a draft.** @param messageUri the URI of the stored message* @param configOverrides the carrier-specific messaging configuration values to override for* sending the message.* @param sentIntent ifnot NULL this <code>PendingIntent</code> is* broadcast when the message is successfully sent, or failed* @throws IllegalArgumentException if messageUri is empty* {@hide}*/
public void sendStoredMultimediaMessage(Uri messageUri, Bundle configOverrides,
PendingIntent sentIntent) {
if (messageUri == null) {
thrownew IllegalArgumentException("Empty message URI");
}
try {
IMms iMms = IMms.Stub.asInterface(ServiceManager.getService("imms"));
if (iMms != null) {
iMms.sendStoredMessage(
getSubscriptionId(), ActivityThread.currentPackageName(), messageUri,
configOverrides, sentIntent);
}
} catch (RemoteException ex) {
// ignore it
}
}
短信接收***********************************************************************************
首先系統發出android.provider.Telephony.Sms.Intents.SMS_DELIVER_ACTION廣播,然后SmsReceiver接收,接收后啟動
service SmsReceiverService處理
/*** In the delivering state, the inbound SMS is processed and stored in the raw table.* The message is acknowledged before we exit this state. If there is a message to broadcast,* transition to {@link WaitingState} state to send the ordered broadcast and wait for the* results. When all messages have been processed, the halting state will release the wakelock.*/privateclassDeliveringStateextendsState {****@OverridepublicbooleanprocessMessage(Message msg) {log("DeliveringState.processMessage:" + msg.what)?log("DeliveringState.processMessage:" + msg.what)?switch (msg.what) {case EVENT_BROADCAST_SMS:// if any broadcasts were sent, transition to waiting stateInboundSmsTracker inboundSmsTracker = (InboundSmsTracker) msg.obj?if (processMessagePart(inboundSmsTracker)) {transitionTo(mWaitingState)?} else {// if event is sent from SmsBroadcastUndelivered.broadcastSms(), and// processMessagePart() returns false, the state machine will be stuck in// DeliveringState until next message is received. Send message to// transition to idle to avoid that so that wakelock can be releasedlog("No broadcast sent on processing EVENT_BROADCAST_SMS in Delivering " +"state. Return to Idle state")?sendMessage(EVENT_RETURN_TO_IDLE)?}return HANDLED?****privatebooleanprocessMessagePart(InboundSmsTracker tracker) {****dispatchSmsDeliveryIntent(pdus, tracker.getFormat(), destPort, resultReceiver,IConcatenatedSmsFwkExt.UPLOAD_FLAG_NONE)?/privatevoiddispatchSmsDeliveryIntent(byte[][] pdus, String format, int destPort,BroadcastReceiver resultReceiver, int longSmsUploadFlag) {// MTK-ENDIntent intent = new Intent()?intent.putExtra("pdus", pdus)?intent.putExtra("format", format)?if (destPort == -1) {intent.setAction(Intents.SMS_DELIVER_ACTION)?***dispatchIntent(intent, android.Manifest.permission.RECEIVE_SMS,AppOpsManager.OP_RECEIVE_SMS, options, resultReceiver, UserHandle.SYSTEM)?
-------------------------------------------publicvoiddispatchIntent(Intent intent, String permission, int appOp,Bundle opts, BroadcastReceiver resultReceiver, UserHandle user) {intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT)?******mContext.sendOrderedBroadcastAsUser(intent, user, permission, appOp, opts,resultReceiver, getHandler(), Activity.RESULT_OK, null, null)?
到這里,消息廣播就發送出去了。
將PDU數據插入到raw表中/*** Insert a message PDU intothe raw table so we can acknowledge it immediately.* If the device crashes beforethe broadcast to listeners completes, it will be delivered* fromthe raw table onthe next device boot. For single-part messages, the deleteWhere* and deleteWhereArgs fields ofthe tracker will be setto delete the correct row after* the ordered broadcast completes.** @param tracker the tracker to add tothe raw table* @returntrueon success? falseon failure towriteto database*/private int addTrackerToRawTable(InboundSmsTracker tracker, boolean deDup) {