本文共 32685 字,大约阅读时间需要 108 分钟。
我们先来看最简单的流程入手分析,即收件人只有一个,而且不是长短信的情况。
一、地址有效性检测
当点击发送按钮时,触发onClick事件:
@ComposeMessageActivity.java public void onClick(View v) { if ((v == mSendButtonSms || v == mSendButtonMms) && isPreparedForSending()) { //确认发送 confirmSendMessageIfNeeded(); } else if ((v == mRecipientsPicker)) { launchMultiplePhonePicker(); } }
然后进行收件人地址信息的确认:
private void confirmSendMessageIfNeeded() { if (!isRecipientsEditorVisible()) { //当前的收件人编辑框不可见,说明所发送的对象已经存在短信的会话,也说明当前的收件人地址是ok的 sendMessage(true); return; } //判断是否为MMS boolean isMms = mWorkingMessage.requiresMms(); if (mRecipientsEditor.hasInvalidRecipient(isMms)) { //当前的收件人列表中包含无效地址 if (mRecipientsEditor.hasValidRecipient(isMms)) { //当前的收件人列表中有无效地址和有效地址,提示用户是否忽略,只发送有效的地址 String title = getResourcesString(R.string.has_invalid_recipient, mRecipientsEditor.formatInvalidNumbers(isMms)); new AlertDialog.Builder(this) .setTitle(title) .setMessage(R.string.invalid_recipient_message) .setPositiveButton(R.string.try_to_send, new SendIgnoreInvalidRecipientListener()) .setNegativeButton(R.string.no, new CancelSendingListener()) .show(); } else { //当前的收件人列表中的地址全部无效,取消发送,提示用户 new AlertDialog.Builder(this) .setTitle(R.string.cannot_send_message) .setMessage(R.string.cannot_send_message_reason) .setPositiveButton(R.string.yes, new CancelSendingListener()) .show(); } } else { //收件人地址都是有效的,发送 ContactList contacts = mRecipientsEditor.constructContactsFromInput(false); mDebugRecipients = contacts.serialize(); sendMessage(true); } }
经过地址有效性检测后,通过sendMessage()继续流程,这里传递的bCheckEcmMode参数代表是否检查当前Phone的状态,处于紧急状态时无法发送短信:
private void sendMessage(boolean bCheckEcmMode) { if (bCheckEcmMode) { //判断当前是否为紧急呼叫模式 String inEcm = SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE); if (Boolean.parseBoolean(inEcm)) { try { //紧急状态下,无法发送短彩信 startActivityForResult( new Intent(TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS, null), REQUEST_CODE_ECM_EXIT_DIALOG); return; } catch (ActivityNotFoundException e) { Log.e(TAG, "Cannot find EmergencyCallbackModeExitDialog", e); } } } //判断当前是否有短信正在发送 if (!mSendingMessage) { //重置收件人控件的监听器 removeRecipientsListeners(); //进入WorkingMessage处理流程 mWorkingMessage.send(mDebugRecipients); mSentMessage = true; mSendingMessage = true; addRecipientsListeners(); mScrollOnSend = true; // in the next onQueryComplete, scroll the list to the end. } // But bail out if we are supposed to exit after the message is sent. if (mSendDiscreetMode) { finish(); } }
二、创建短彩信的发送线程
在sendMessage()中经过对当前紧急服务的处理,然后判断如果当前没有短信正在发送,则通过WorkingMessage发送短信。这里的WorkingMessage是处理当前所编辑的信息的工具类,没有父类,在ComposeMessageActivity界面被创建时或者短信被发送出去时创建,主要负责区分短彩信的流程以及发送短信时UI的更新。@WorkingMessage.java public void send(final String recipientsInUI) { long origThreadId = mConversation.getThreadId(); removeSubjectIfEmpty(true /* notify */); prepareForSave(true /* notify */); //拿到当前的会话 final Conversation conv = mConversation; String msgTxt = mText.toString(); if (requiresMms() || addressContainsEmailToMms(conv, msgTxt)) { //彩信发送 if (MmsConfig.getUaProfUrl() == null) { String err = "WorkingMessage.send MMS sending failure. mms_config.xml is " + "missing uaProfUrl setting. uaProfUrl is required for MMS service, " + "but can be absent for SMS."; RuntimeException ex = new NullPointerException(err); Log.e(TAG, err, ex); // now, let's just crash. throw ex; } final Uri mmsUri = mMessageUri; final PduPersister persister = PduPersister.getPduPersister(mActivity); final SlideshowModel slideshow = mSlideshow; final CharSequence subject = mSubject; final boolean textOnly = mAttachmentType == TEXT; //彩信发送线程 new Thread(new Runnable() { @Override public void run() { final SendReq sendReq = makeSendReq(conv, subject); slideshow.prepareForSend(); sendMmsWorker(conv, mmsUri, persister, slideshow, sendReq, textOnly); updateSendStats(conv); } }, "WorkingMessage.send MMS").start(); } else { //短信发送流程 final String msgText = mText.toString(); new Thread(new Runnable() { @Override public void run() { preSendSmsWorker(conv, msgText, recipientsInUI); updateSendStats(conv); } }, "WorkingMessage.send SMS").start(); } // update the Recipient cache with the new to address, if it's different RecipientIdCache.updateNumbers(conv.getThreadId(), conv.getRecipients()); // Mark the message as discarded because it is "off the market" after being sent. mDiscarded = true; }
在上面的send流程中,WorkingMessage对短彩信进行分类,分别创建子线程进行发送,本节我们只关注短信流程,他是在preSendSmsWorker()中被发送的:
private void preSendSmsWorker(Conversation conv, String msgText, String recipientsInUI) { UserHappinessSignals.userAcceptedImeText(mActivity); //UI刷新 mStatusListener.onPreMessageSent(); //获取初始的线程ID long origThreadId = conv.getThreadId(); //获取分配的线程ID long threadId = conv.ensureThreadId(); String semiSepRecipients = conv.getRecipients().serialize(); // recipientsInUI can be empty when the user types in a number and hits send if (LogTag.SEVERE_WARNING && ((origThreadId != 0 && origThreadId != threadId) || (!semiSepRecipients.equals(recipientsInUI) && !TextUtils.isEmpty(recipientsInUI)))) { }else { //发送短信 sendSmsWorker(msgText, semiSepRecipients, threadId); //删除草稿 deleteDraftSmsMessage(threadId); } }
在上面的preSendSmsWorker中进行了四个处理:
1、更新UI(更新编辑框等控件);
2、获取当前发送的ThreadID;
3、发送短信;
4、删除草稿;
接下来我们继续来看发送的过程:
private void sendSmsWorker(String msgText, String semiSepRecipients, long threadId) { //获取当前发送的收件人地址 String[] dests = TextUtils.split(semiSepRecipients, ";"); //获取MessageSender对象,传递进去4个参数分别为:收件人、信息文本、当前的threadId、SimID。 MessageSender sender = new SmsMessageSender(mActivity, dests, msgText, threadId); try { //通过MessageSender发送出去 sender.sendMessage(threadId); // Make sure this thread isn't over the limits in message count Recycler.getSmsRecycler().deleteOldMessagesByThreadId(mActivity, threadId); } catch (Exception e) { Log.e(TAG, "Failed to send SMS message, threadId=" + threadId, e); } //更新UI mStatusListener.onMessageSent(); MmsWidgetProvider.notifyDatasetChanged(mActivity); }
经过上面WorkingMessage的sendSmsWorker过程,创建了MessageSender对象,并通过该对象的sendMessage()方法将信息发送出去,并在发送之后再次更新UI界面(正在发送中)。
三、通过SmsMessageSender拆分多个收件人
上面创建的MessageSender对象,继承自MessageSender接口,主要方法只有三个:public boolean sendMessage(long token) throws MmsException {}; private boolean queueMessage(long token) throws MmsException {}; private String getOutgoingServiceCenter(long threadId) {};
他的主要作用就是对当前收件人信息拆分后,把群发的短信构建成一个短信队列并保存在数据库中,然后通知SmsReceiverService将队列读取出来并发送出去。
下面来看其具体实现过程。@SmsMessageSender.java public boolean sendMessage(long token) throws MmsException { return queueMessage(token); } private boolean queueMessage(long token) throws MmsException { if ((mMessageText == null) || (mNumberOfDests == 0)) { //空信息不能发送 throw new MmsException("Null message body or dest."); } SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext); boolean requestDeliveryReport = prefs.getBoolean( MessagingPreferenceActivity.SMS_DELIVERY_REPORT_MODE, DEFAULT_DELIVERY_REPORT_MODE); //根据当前短信的收件人数目,遍历当前的发送队列 for (int i = 0; i < mNumberOfDests; i++) { try { //将当前要发送的短消息放入发送队列中 Sms.addMessageToUri(mContext.getContentResolver(), Uri.parse("content://sms/queued"), mDests[i], mMessageText, null, mTimestamp, true /* read */, requestDeliveryReport, mThreadId); } catch (SQLiteException e) { if (LogTag.DEBUG_SEND) { Log.e(TAG, "queueMessage SQLiteException", e); } SqliteWrapper.checkSQLiteException(mContext, e); } } //通知SmsReceiverService发送短信 mContext.sendBroadcast(new Intent(SmsReceiverService.ACTION_SEND_MESSAGE, null, mContext, SmsReceiver.class)); return false;}
在上面这个过程中,将收件人地址拆分后,生成一个短信队列放入"content://sms/queued"中,然后给SmsReceiver发送了通知,这里的SmsReceiver作用仅仅是将该通知转发给SmsReceiverService而已:
@SmsReceiver.java public void onReceive(Context context, Intent intent) { onReceiveWithPrivilege(context, intent, false); } protected void onReceiveWithPrivilege(Context context, Intent intent, boolean privileged) { if (!privileged && intent.getAction().equals(Intents.SMS_DELIVER_ACTION)) { return; } //将请求转交给SmsReceiverService来处理 intent.setClass(context, SmsReceiverService.class); intent.putExtra("result", getResultCode()); beginStartingService(context, intent); }
也就是说,SmsMessageSender将要发送的短信放入队列中之后,经过SmsReceiver将该消息发送给了SmsReceiverService, 这里的SmsReceiverService是负责短信的收发的Service。
下面来看SmsReceiverService对于发送短消息的处理过程。 这个Service被创建时,会创建一个子线程(HandlerThread)以及该线程的Handler对象(ServiceHandler):@SmsReceiverService.java public void onCreate() { //创建子线程处理各种消息 HandlerThread thread = new HandlerThread(TAG, Process.THREAD_PRIORITY_BACKGROUND); thread.start(); mServiceLooper = thread.getLooper(); mServiceHandler = new ServiceHandler(mServiceLooper); }
当该Service被启动时,就会对当前的请求进行处理:
public int onStartCommand(Intent intent, int flags, int startId) { mResultCode = intent != null ? intent.getIntExtra("result", 0) : 0; //通知Handler处理当前的请求 Message msg = mServiceHandler.obtainMessage(); msg.arg1 = startId; msg.obj = intent; mServiceHandler.sendMessage(msg); return Service.START_NOT_STICKY; }
然后看当前Handler的处理:
private final class ServiceHandler extends Handler { public ServiceHandler(Looper looper) { super(looper); } @Override public void handleMessage(Message msg) { int serviceId = msg.arg1; Intent intent = (Intent)msg.obj; if (intent != null && MmsConfig.isSmsEnabled(getApplicationContext())) { String action = intent.getAction(); int error = intent.getIntExtra("errorCode", 0); if (MESSAGE_SENT_ACTION.equals(intent.getAction())) { handleSmsSent(intent, error); } else if (SMS_DELIVER_ACTION.equals(action)) { handleSmsReceived(intent, error); } else if (ACTION_BOOT_COMPLETED.equals(action)) { handleBootCompleted(); } else if (TelephonyIntents.ACTION_SERVICE_STATE_CHANGED.equals(action)) { handleServiceStateChanged(intent); } else if (ACTION_SEND_MESSAGE.endsWith(action)) { //发送短信 handleSendMessage(); } else if (ACTION_SEND_INACTIVE_MESSAGE.equals(action)) { handleSendInactiveMessage(); } } SmsReceiver.finishStartingService(SmsReceiverService.this, serviceId); } }
从上面的case分支中我们看到,对于当前的发送短信的请求(ACTION_SEND_MESSAGE)将会通过handleSendMessage()来处理:
private void handleSendMessage() { if (!mSending) { //当前没有其他任务时就触发发送的操作 sendFirstQueuedMessage(); } } public synchronized void sendFirstQueuedMessage() { boolean success = true; final Uri uri = Uri.parse("content://sms/queued"); ContentResolver resolver = getContentResolver(); //从队列中拿到要发送的短信 Cursor c = SqliteWrapper.query(this, resolver, uri, SEND_PROJECTION, null, null, "date ASC"); if (c != null) { try { //发送队列中第一条短信 if (c.moveToFirst()) { String msgText = c.getString(SEND_COLUMN_BODY); String address = c.getString(SEND_COLUMN_ADDRESS); int threadId = c.getInt(SEND_COLUMN_THREAD_ID); int status = c.getInt(SEND_COLUMN_STATUS); int msgId = c.getInt(SEND_COLUMN_ID); Uri msgUri = ContentUris.withAppendedId(Sms.CONTENT_URI, msgId); //构建SmsSingleRecipientSender对象 SmsMessageSender sender = new SmsSingleRecipientSender(this, address, msgText, threadId, status == Sms.STATUS_PENDING, msgUri); try { //发送 sender.sendMessage(SendingProgressTokenManager.NO_TOKEN);; mSending = true; } catch (MmsException e) { mSending = false; messageFailedToSend(msgUri, SmsManager.RESULT_ERROR_GENERIC_FAILURE); success = false; sendBroadcast(new Intent(SmsReceiverService.ACTION_SEND_MESSAGE, null, this, SmsReceiver.class)); } } } finally { c.close(); } } if (success) { unRegisterForServiceStateChanges(); } }
我们看到,经过SmsReceiverService中Handler的处理,将数据库中的当前要发送的短信队列取出来,然后取出队列中第一个短消息任务,通过SmsSingleRecipientSender的sendMessage()方法发送出去。至此SmsReceiverService的流程就走完了,他的作用主要就是拿到队列中的第一条短消息,构建SmsSingleRecipientSender对象并发送出去。
四、通过SmsSingleRecipientSender拆分长短信
SmsSingleRecipientSender类继承自SmsMessageSender,他所提供的方法只有一个:
public boolean sendMessage(long token) throws MmsException {};
其处理内容就是对长短消息进行分割。然后注册两个广播(一个用于广播当前正在发送,另一个广播短信的送达状态报告),之后通过SmsManager发送出去。
@SmsSingleRecipientSender.java public boolean sendMessage(long token) throws MmsException { if (mMessageText == null) { throw new MmsException("Null message body or have multiple destinations."); } SmsManager smsManager = SmsManager.getDefault(); ArrayListmessages = 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); mDest = PhoneNumberUtils.stripSeparators(mDest); mDest = Conversation.verifySingleRecipient(mContext, mThreadId, mDest); } int messageCount = messages.size(); if (messageCount == 0) { 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 deliveryIntents = new ArrayList (messageCount); ArrayList sentIntents = new ArrayList (messageCount); for (int i = 0; i < messageCount; i++) { if (mRequestDeliveryReport && (i == (messageCount - 1))) { //所有短信被发送完毕后,在最后一条短信后面添加送达报告的Intent deliveryIntents.add(PendingIntent.getBroadcast( mContext, 0, new Intent( MessageStatusReceiver.MESSAGE_STATUS_RECEIVED_ACTION, mUri, mContext, MessageStatusReceiver.class), 0)); } else { deliveryIntents.add(null); } //对于拆分后的短消息,需要在每条信息发送完毕后发送该Intent,从而接着发送剩下的拆分短信 Intent intent = new Intent(SmsReceiverService.MESSAGE_SENT_ACTION, mUri, mContext, SmsReceiver.class); int requestCode = 0; if (i == messageCount -1) { //收到该附加数据说明当前的拆分短信已经发送完毕 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); } catch (Exception ex) { throw new MmsException("SmsMessageSender.sendMessage: caught " + ex + " from SmsManager.sendTextMessage()"); } return false; }
经过上面的准备过程,在通过SmsManager发送信息之前,还添加了两个Intent:SmsReceiverService.MESSAGE_SENT_ACTION和MessageStatusReceiver.MESSAGE_STATUS_RECEIVED_ACTION。这两个Intent的作用分别是:
MESSAGE_STATUS_RECEIVED_ACTION:当所有长短信(或短消息)发送完毕后,发送该Intent。 MESSAGE_SENT_ACTION:分割后的短消息,每发送一条,都会发送该Intent,当最后一条发送完毕后,将会在该Intent中附加EXTRA_MESSAGE_SENT_SEND_NEXT=true的数据。 具体细节在发送完毕后再分析。 接下来看SmsManager,这里的SmsManager是单例模型,通过其自己的getDefault()或者getSmsManagerForSubscriber()方法就可以得到该对象。@SmsManager.java public void sendMultipartTextMessage( String destinationAddress, String scAddress, ArrayListparts, ArrayList sentIntents, ArrayList 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 = getISmsServiceOrThrow(); iccISms.sendMultipartText(ActivityThread.currentPackageName(), destinationAddress, scAddress, parts, sentIntents, deliveryIntents); } catch (RemoteException ex) { } } 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); } }
在上面的流程中区分了长短信和普通短信的流程,我们目前只分析普通短消息,继续看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 = getISmsServiceOrThrow(); iccISms.sendText(ActivityThread.currentPackageName(), destinationAddress, scAddress, text, sentIntent, deliveryIntent); } catch (RemoteException ex) { } }
到这里,SmsMessage通过调用iccISms对象的sendText()方法将短信继续传递,而SmsMessage的流程就此结束。
五、发送单条短信
上面的iccISms对象是UiccSmsController的客户端:
private static ISms getISmsService() { return ISms.Stub.asInterface(ServiceManager.getService("isms")); }
所以接下来我们需要进入UiccSmsController的流程中分析:
@UiccSmsController.java public void sendText(String callingPackage, String destAddr, String scAddr, String text, PendingIntent sentIntent, PendingIntent deliveryIntent) { sendTextForSubscriber(getPreferredSmsSubscription(), callingPackage, destAddr, scAddr, text, sentIntent, deliveryIntent); } public void sendTextForSubscriber(long subId, String callingPackage, String destAddr, String scAddr, String text, PendingIntent sentIntent, PendingIntent deliveryIntent) { IccSmsInterfaceManager iccSmsIntMgr = getIccSmsInterfaceManager(subId); if (iccSmsIntMgr != null) { //通过IccSmsInterfaceManager发送短信 iccSmsIntMgr.sendText(callingPackage, destAddr, scAddr, text, sentIntent, deliveryIntent); } else { } }
在上面的UiccSmsController中将任务交给IccSmsInterfaceManager来继续处理。
IccSmsInterfaceManager这个类没有父类,他在创建PhoneProxy的时候进行初始化,其作用是把请求发送给相应的处理者。比如对于sendText()将会转交给ImsSMSDispatcher来实现。@IccSmsInterfaceManager.java public void sendText(String callingPackage, String destAddr, String scAddr, String text, PendingIntent sentIntent, PendingIntent deliveryIntent) { //是否声明了发短信的权限 mPhone.getContext().enforceCallingPermission( Manifest.permission.SEND_SMS, "Sending SMS message"); //该操作是否被用户允许 if (mAppOps.noteOp(AppOpsManager.OP_SEND_SMS, Binder.getCallingUid(), callingPackage) != AppOpsManager.MODE_ALLOWED) { return; } //调用ImsSMSDispatcher发送 destAddr = filterDestAddress(destAddr); mDispatcher.sendText(destAddr, scAddr, text, sentIntent, deliveryIntent, null, callingPackage); }
在上面这个过程中,先进行两级权限检查,然后通过ImsSMSDispatcher发送信息。
SMSDispatcher总共派生出三个子类:CdmaSMSDispatcher、GsmSMSDispatcher、ImsSMSDispatcher,在IccSmsInterfaceManager创建时只创建ImsSMSDispatcher,而在ImsSMSDispatcher创建过程中会对创建其他两种制式的SMSDispatcher,IccSmsInterfaceManager把请求发送给ImsSMSDispatcher后,由ImsSMSDispatcher根据当前网络状态选择使用CdmaSMSDispatcher还是GsmSMSDispatcher。@ImsSMSDispatcher.java protected void sendText(String destAddr, String scAddr, String text, PendingIntent sentIntent, PendingIntent deliveryIntent, Uri messageUri, String callingPkg) { //根据当前网络类型发送,我们只分析GSM if (isCdmaMo()) { mCdmaDispatcher.sendText(destAddr, scAddr, text, sentIntent, deliveryIntent, messageUri, callingPkg); } else { mGsmDispatcher.sendText(destAddr, scAddr, text, sentIntent, deliveryIntent, messageUri, callingPkg); }}
在上面的过程中,根据当前网络环境使用不同的SMSDispatcher,对于GSM网络来说,当前使用的是GsmSMSDispatcher对象。
这是Framework层与RILJ最接近的对象,他将请求发送给RILJ。@GsmSMSDispatcher.java protected void sendText(String destAddr, String scAddr, String text, PendingIntent sentIntent, PendingIntent deliveryIntent, Uri messageUri, String callingPkg) { //对短信内容进行编码 SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu( scAddr, destAddr, text, (deliveryIntent != null)); if (pdu != null) { if (messageUri == null) { if (SmsApplication.shouldWriteMessageForPackage(callingPkg, mContext)) { //写入发件箱 messageUri = writeOutboxMessage( getSubId(), destAddr, text, deliveryIntent != null, callingPkg); } } else { //移到发件箱 moveToOutbox(getSubId(), messageUri, callingPkg); } HashMap map = getSmsTrackerMap(destAddr, scAddr, text, pdu); //发送 SmsTracker tracker = getSmsTracker(map, sentIntent, deliveryIntent, getFormat(), messageUri, false); sendRawPdu(tracker); } else { } }
在上面的过程中,对短消息内容进行编码,然后把短消息写入(或移入)发件箱,然后利用当前的发地址、收地址、文本、附加Intent等信息创建SmsTracker对象,然后调用sendRawPdu(),这个方法是在GsmSMSDispatcher的父类SMSDispatcher中实现的:
@SMSDispatcher.java protected void sendRawPdu(SmsTracker tracker) { HashMap map = tracker.mData; byte pdu[] = (byte[]) map.get("pdu"); if (mSmsSendDisabled) { tracker.onFailed(mContext, RESULT_ERROR_NO_SERVICE, 0/*errorCode*/); return; } if (pdu == null) { tracker.onFailed(mContext, RESULT_ERROR_NULL_PDU, 0/*errorCode*/); return; } PackageManager pm = mContext.getPackageManager(); String[] packageNames = pm.getPackagesForUid(Binder.getCallingUid()); if (packageNames == null || packageNames.length == 0) { // Refuse to send SMS if we can't get the calling package name. tracker.onFailed(mContext, RESULT_ERROR_GENERIC_FAILURE, 0/*errorCode*/); return; } // Get package info via packagemanager PackageInfo appInfo; try { // XXX this is lossy- apps can share a UID appInfo = pm.getPackageInfo(packageNames[0], PackageManager.GET_SIGNATURES); } catch (PackageManager.NameNotFoundException e) { Rlog.e(TAG, "Can't get calling app package info: refusing to send SMS"); tracker.onFailed(mContext, RESULT_ERROR_GENERIC_FAILURE, 0/*errorCode*/); return; } // 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; } //发送 sendSms(tracker); }
这里会对要发送的信息以及当前环境进行检测,然后进入sendSms()流程,这个方法又回到了GsmSMSDispatcher中实现
@GsmSMSDispatcher.java protected void sendSms(SmsTracker tracker) { HashMapmap = tracker.mData; byte pdu[] = (byte[]) map.get("pdu"); 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 } } // Send SMS via the carrier app. BroadcastReceiver resultReceiver = new SMSDispatcherReceiver(tracker); Intent intent = new Intent(Intents.SMS_SEND_ACTION); String carrierPackage = getCarrierAppPackageName(intent); if (carrierPackage != null) { intent.setPackage(carrierPackage); intent.putExtra("pdu", pdu); intent.putExtra("smsc", (byte[]) map.get("smsc")); intent.putExtra("format", getFormat()); if (tracker.mSmsHeader != null && tracker.mSmsHeader.concatRef != null) { SmsHeader.ConcatRef concatRef = tracker.mSmsHeader.concatRef; intent.putExtra("concat.refNumber", concatRef.refNumber); intent.putExtra("concat.seqNumber", concatRef.seqNumber); intent.putExtra("concat.msgCount", concatRef.msgCount); } intent.addFlags(Intent.FLAG_RECEIVER_NO_ABORT); Rlog.d(TAG, "Sending SMS by carrier app."); mContext.sendOrderedBroadcast(intent, android.Manifest.permission.RECEIVE_SMS, AppOpsManager.OP_RECEIVE_SMS, resultReceiver, null, Activity.RESULT_CANCELED, null, null); } else { //发送 sendSmsByPstn(tracker); } }
然后来看sendSmsByPstn():
protected void sendSmsByPstn(SmsTracker tracker) { int ss = mPhone.getServiceState().getState(); if (!isIms() && ss != ServiceState.STATE_IN_SERVICE) { tracker.onFailed(mContext, getNotInServiceError(ss), 0/*errorCode*/); return; } //拿到SmsTracker中保存的信息 HashMapmap = tracker.mData; byte smsc[] = (byte[]) map.get("smsc"); byte[] pdu = (byte[]) map.get("pdu"); Message reply = obtainMessage(EVENT_SEND_SMS_COMPLETE, tracker); if (0 == tracker.mImsRetry && !isIms()) { if (tracker.mRetryCount > 0) { if (((0x01 & pdu[0]) == 0x01)) { pdu[0] |= 0x04; // TP-RD pdu[1] = (byte) tracker.mMessageRef; // TP-MR } } if (tracker.mRetryCount == 0 && tracker.mExpectMore) { //调用RILJ发送短信 mCi.sendSMSExpectMore(IccUtils.bytesToHexString(smsc), IccUtils.bytesToHexString(pdu), reply); } else { mCi.sendSMS(IccUtils.bytesToHexString(smsc), IccUtils.bytesToHexString(pdu), reply); } } else { //通过IMS发送短信 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++; } }
在上面的发送之前,将SmsTracker中的内容解析出来,通过RILJ发送出去。并且注册了该请求的回应消息EVENT_SEND_SMS_COMPLETE,用于处理短信接收时的流程。
以上就是普通单收件人,短信的发送流程。
整个过程的流程图如下:
转载地址:https://liwangjiang.blog.csdn.net/article/details/86176236 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!