Android短信发送流程之多收件人发送(原)

       前面的《 Android短信发送流程之长短信发送 》中介绍了长短信对于普通短信的区别,而对于多收件人的情况,在SmsMessageSender的queueMessage()方法中我们了解到,发送之前,将多收件人的短信进行拆分,放入"content://sms/queued"队列中,在接下来的流程中,将会在SmsReceiverService中通过sendFirstQueuedMessage()方法取出队列中的第一条短信并发送,那么,队列中的其他消息是如何被发送出去的呢?
        我们从第一条短信发送完毕后的流程来寻找答案。
        由于在GsmSMSDispatcher向RILJ发送消息时所注册的回应消息是EVENT_SEND_SMS_COMPLETE,所以当短信发送成功时,就会收到该消息的回应。
        在SMSDispatcher中对该回应进行处理:
[java]  view plain  copy
  1. @SMSDispatcher.java  
  2. public void handleMessage(Message msg) {  
  3.     switch (msg.what) {  
  4.         case EVENT_SEND_SMS_COMPLETE:  
  5.             //发送成功  
  6.             handleSendComplete((AsyncResult) msg.obj);  
  7.             break;  
  8.         default:  
  9.             Rlog.e(TAG, "handleMessage() ignoring message of unexpected type " + msg.what);  
  10.     }  
  11. }  
        然后进入handleSendComplete()方法中处理:
[java]  view plain  copy
  1. protected void handleSendComplete(AsyncResult ar) {  
  2.     SmsTracker tracker = (SmsTracker) ar.userObj;  
  3.     PendingIntent sentIntent = tracker.mSentIntent;  
  4.   
  5.   
  6.     if (ar.result != null) {  
  7.         tracker.mMessageRef = ((SmsResponse)ar.result).mMessageRef;  
  8.     } else {  
  9.     }  
  10.   
  11.   
  12.     if (ar.exception == null) {  
  13.         //发送成功  
  14.         if (tracker.mDeliveryIntent != null) {  
  15.             //将当前短信的tracker保存  
  16.             deliveryPendingList.add(tracker);  
  17.         }  
  18.         //回调到SmsTracker内部  
  19.         tracker.onSent(mContext);  
  20.     } else {  
  21.         //发送失败  
  22.     }  
  23. }  
        在上面的过程中,对短信发送的结果进行区分,如果失败,将会根据失败原因通知SmsTracker,如果成功,将会进入SmsTracker中继续处理:
[java]  view plain  copy
  1. public void onSent(Context context) {  
  2.     boolean isSinglePartOrLastPart = true;  
  3.     if (mUnsentPartCount != null) {  
  4.         //判断是否已经将长短新最后一条发送完毕  
  5.         isSinglePartOrLastPart = mUnsentPartCount.decrementAndGet() == 0;  
  6.     }  
  7.     if (isSinglePartOrLastPart) {  
  8.         //当前所有短信发送完毕,更新数据库状态  
  9.         boolean success = true;  
  10.         if (mAnyPartFailed != null && mAnyPartFailed.get()) {  
  11.             success = false;  
  12.         }  
  13.         if (success) {  
  14.             setMessageFinalState(context, Sms.MESSAGE_TYPE_SENT);  
  15.         } else {  
  16.             setMessageFinalState(context, Sms.MESSAGE_TYPE_FAILED);  
  17.         }  
  18.     }  
  19.     //把发送短信之前保存在SmsTracker中的Intent取出来发送出去,通知短信已经发送成功。  
  20.     if (mSentIntent != null) {  
  21.         try {  
  22.             // Extra information to send with the sent intent  
  23.             Intent fillIn = new Intent();  
  24.             if (mMessageUri != null) {  
  25.                 // Pass this to SMS apps so that they know where it is stored  
  26.                 fillIn.putExtra("uri", mMessageUri.toString());  
  27.             }  
  28.             if (mUnsentPartCount != null && isSinglePartOrLastPart) {  
  29.                 // Is multipart and last part  
  30.                 fillIn.putExtra(SEND_NEXT_MSG_EXTRA, true);  
  31.             }  
  32.             mSentIntent.send(context, Activity.RESULT_OK, fillIn);  
  33.         } catch (CanceledException ex) {  
  34.             Rlog.e(TAG, "Failed to send result");  
  35.         }  
  36.     }  
  37. }  
        由于此时无论是长短信还是普通短信,都已经发送完毕(只发送了一个收件人),因此isSinglePartOrLastPart的判定将会是true,从而更新数据库中该短信的状态,然后再将发送时附加在SmsTracker中的mSentIntent取出来并发送出去,同时指定返回结果为“Activity.RESULT_OK”。
        而这里的mSentIntent就是在SmsSingleRecipientSender中指定的,我们再来回顾以下当时的状态:
[java]  view plain  copy
  1. @SmsSingleRecipientSender.java  
  2. public boolean sendMessage(long token) throws MmsException {  
  3.     if (mMessageText == null) {  
  4.         throw new MmsException("Null message body or have multiple destinations.");  
  5.     }  
  6.     SmsManager smsManager = SmsManager.getDefault();  
  7.     ArrayList<String> messages = null;  
  8.     //拆分长短信  
  9.     if ((MmsConfig.getEmailGateway() != null) && (Mms.isEmailAddress(mDest) || MessageUtils.isAlias(mDest))) {  
  10.         //彩信  
  11.         String msgText;  
  12.         msgText = mDest + " " + mMessageText;  
  13.         mDest = MmsConfig.getEmailGateway();  
  14.         messages = smsManager.divideMessage(msgText);  
  15.     } else {  
  16.         //短信  
  17.         messages = smsManager.divideMessage(mMessageText);  
  18.         mDest = PhoneNumberUtils.stripSeparators(mDest);  
  19.         mDest = Conversation.verifySingleRecipient(mContext, mThreadId, mDest);  
  20.     }  
  21.     int messageCount = messages.size();  
  22.   
  23.   
  24.     if (messageCount == 0) {  
  25.         throw new MmsException("SmsMessageSender.sendMessage: divideMessage returned " + "empty messages. Original message is \"" + mMessageText + "\"");  
  26.     }  
  27.   
  28.   
  29.     boolean moved = Sms.moveMessageToFolder(mContext, mUri, Sms.MESSAGE_TYPE_OUTBOX, 0);  
  30.     if (!moved) {  
  31.         throw new MmsException("SmsMessageSender.sendMessage: couldn't move message " + "to outbox: " + mUri);  
  32.     }  
  33.     ArrayList<PendingIntent> deliveryIntents =  new ArrayList<PendingIntent>(messageCount);  
  34.     ArrayList<PendingIntent> sentIntents = new ArrayList<PendingIntent>(messageCount);  
  35.     for (int i = 0; i < messageCount; i++) {  
  36.         if (mRequestDeliveryReport && (i == (messageCount - 1))) {  
  37.             //所有短信被发送完毕后,在最后一条短信后面添加送达报告的Intent  
  38.             deliveryIntents.add(PendingIntent.getBroadcast(  
  39.                         mContext, 0,  
  40.                         new Intent(  
  41.                             MessageStatusReceiver.MESSAGE_STATUS_RECEIVED_ACTION,  
  42.                             mUri,  
  43.                             mContext,  
  44.                             MessageStatusReceiver.class),  
  45.                         0));  
  46.         } else {  
  47.             deliveryIntents.add(null);  
  48.         }  
  49.         //对于拆分后的短消息,需要在每条信息发送完毕后发送该Intent,从而接着发送剩下的拆分短信  
  50.         Intent intent  = new Intent(SmsReceiverService.MESSAGE_SENT_ACTION,  
  51.                 mUri,  
  52.                 mContext,  
  53.                 SmsReceiver.class);  
  54.   
  55.   
  56.         int requestCode = 0;  
  57.         if (i == messageCount -1) {  
  58.             //收到该附加数据说明当前的拆分短信已经发送完毕  
  59.             requestCode = 1;  
  60.             intent.putExtra(SmsReceiverService.EXTRA_MESSAGE_SENT_SEND_NEXT, true);  
  61.         }  
  62.         sentIntents.add(PendingIntent.getBroadcast(mContext, requestCode, intent, 0));  
  63.     }  
  64.     try {  
  65.         //发送  
  66.         smsManager.sendMultipartTextMessage(mDest, mServiceCenter, messages, sentIntents, deliveryIntents);  
  67.     } catch (Exception ex) {  
  68.         throw new MmsException("SmsMessageSender.sendMessage: caught " + ex + " from SmsManager.sendTextMessage()");  
  69.     }  
  70.     return false;  
  71. }  
        从这里我们看到,当前的mSentIntent发送对象是SmsReceiver,内容是MESSAGE_SENT_ACTION,而且包含了附加数据EXTRA_MESSAGE_SENT_SEND_NEXT=true,并且SmsTracker发送该Intent时传送的结果是“Activity.RESULT_OK”。
        由于SmsReceiver会把所有Intent转交给SmsReceiverService处理,我们直接来看SmsReceiverService的处理:
[java]  view plain  copy
  1. @SmsReceiverService.java  
  2. public void handleMessage(Message msg) {  
  3.     int serviceId = msg.arg1;  
  4.     Intent intent = (Intent)msg.obj;  
  5.     if (intent != null && MmsConfig.isSmsEnabled(getApplicationContext())) {  
  6.         String action = intent.getAction();  
  7.         int error = intent.getIntExtra("errorCode"0);  
  8.   
  9.   
  10.         if (MESSAGE_SENT_ACTION.equals(intent.getAction())) {  
  11.             //处理  
  12.             handleSmsSent(intent, error);  
  13.         } else if (SMS_DELIVER_ACTION.equals(action)) {  
  14.             handleSmsReceived(intent, error);  
  15.         } else if (ACTION_BOOT_COMPLETED.equals(action)) {  
  16.             handleBootCompleted();  
  17.         } else if (TelephonyIntents.ACTION_SERVICE_STATE_CHANGED.equals(action)) {  
  18.             handleServiceStateChanged(intent);  
  19.         } else if (ACTION_SEND_MESSAGE.endsWith(action)) {  
  20.             handleSendMessage();  
  21.         } else if (ACTION_SEND_INACTIVE_MESSAGE.equals(action)) {  
  22.             handleSendInactiveMessage();  
  23.         }  
  24.     }  
  25.     SmsReceiver.finishStartingService(SmsReceiverService.this, serviceId);  
  26. }  
        对于当前的Intent,将会在handleSmsSent()中处理:
[java]  view plain  copy
  1. private void handleSmsSent(Intent intent, int error) {  
  2.     Uri uri = intent.getData();  
  3.     mSending = false;  
  4.     //EXTRA_MESSAGE_SENT_SEND_NEXT表示是否是长短新的最后一条  
  5.     boolean sendNextMsg = intent.getBooleanExtra(EXTRA_MESSAGE_SENT_SEND_NEXT, false);  
  6.     if (mResultCode == Activity.RESULT_OK) {  
  7.         //将已经发送成功的短信移入发件箱,更新其状态为已发送  
  8.         if (!Sms.moveMessageToFolder(this, uri, Sms.MESSAGE_TYPE_SENT, error)) {  
  9.             Log.e(TAG, "handleSmsSent: failed to move message " + uri + " to sent folder");  
  10.         }  
  11.         if (sendNextMsg) {  
  12.             //继续发送其他收件人  
  13.             sendFirstQueuedMessage();  
  14.         }  
  15.         // Update the notification for failed messages since they may be deleted.  
  16.         MessagingNotification.nonBlockingUpdateSendFailedNotification(this);  
  17.     } else if ((mResultCode == SmsManager.RESULT_ERROR_RADIO_OFF) ||  
  18.             (mResultCode == SmsManager.RESULT_ERROR_NO_SERVICE)) {  
  19.         // We got an error with no service or no radio. Register for state changes so  
  20.         // when the status of the connection/radio changes, we can try to send the  
  21.         // queued up messages.  
  22.         registerForServiceStateChanges();  
  23.         // We couldn't send the message, put in the queue to retry later.  
  24.         Sms.moveMessageToFolder(this, uri, Sms.MESSAGE_TYPE_QUEUED, error);  
  25.         mToastHandler.post(new Runnable() {  
  26.             public void run() {  
  27.                 Toast.makeText(SmsReceiverService.this, getString(R.string.message_queued),  
  28.                     Toast.LENGTH_SHORT).show();  
  29.             }  
  30.         });  
  31.     } else if (mResultCode == SmsManager.RESULT_ERROR_FDN_CHECK_FAILURE) {  
  32.         messageFailedToSend(uri, mResultCode);  
  33.         mToastHandler.post(new Runnable() {  
  34.             public void run() {  
  35.                 Toast.makeText(SmsReceiverService.this, getString(R.string.fdn_check_failure),  
  36.                     Toast.LENGTH_SHORT).show();  
  37.             }  
  38.         });  
  39.     } else {  
  40.         messageFailedToSend(uri, error);  
  41.         if (sendNextMsg) {  
  42.             sendFirstQueuedMessage();  
  43.         }  
  44.     }  
  45. }  
        由于当前resultCode=OK,并且sendNextMsg=true,首先会通过Sms.moveMessageToFolder()操作将发送成功的短信从"content://sms/queued"队列移动到"content://sms/sent"队列。
        然后在sendFirstQueuedMessage()中继续处理:
[java]  view plain  copy
  1. public synchronized void sendFirstQueuedMessage() {  
  2.     boolean success = true;  
  3.     final Uri uri = Uri.parse("content://sms/queued");  
  4.     ContentResolver resolver = getContentResolver();  
  5.     Cursor c = SqliteWrapper.query(this, resolver, uri, SEND_PROJECTION, nullnull"date ASC");   // date ASC so we send out in  
  6.     if (c != null) {  
  7.         try {  
  8.             if (c.moveToFirst()) {  
  9.                 //从队列中取出第一个并发送  
  10.                 String msgText = c.getString(SEND_COLUMN_BODY);  
  11.                 String address = c.getString(SEND_COLUMN_ADDRESS);  
  12.                 int threadId = c.getInt(SEND_COLUMN_THREAD_ID);  
  13.                 int status = c.getInt(SEND_COLUMN_STATUS);  
  14.   
  15.   
  16.                 int msgId = c.getInt(SEND_COLUMN_ID);  
  17.                 Uri msgUri = ContentUris.withAppendedId(Sms.CONTENT_URI, msgId);  
  18.   
  19.   
  20.                 SmsMessageSender sender = new SmsSingleRecipientSender(this,  
  21.                         address, msgText, threadId, status == Sms.STATUS_PENDING,  
  22.                         msgUri);  
  23.                 try {  
  24.                     sender.sendMessage(SendingProgressTokenManager.NO_TOKEN);;  
  25.                     mSending = true;  
  26.                 } catch (MmsException e) {  
  27.                     mSending = false;  
  28.                     messageFailedToSend(msgUri, SmsManager.RESULT_ERROR_GENERIC_FAILURE);  
  29.                     success = false;  
  30.                     // Sending current message fails. Try to send more pending messages  
  31.                     // if there is any.  
  32.                     sendBroadcast(new Intent(SmsReceiverService.ACTION_SEND_MESSAGE,  
  33.                                 null,  
  34.                                 this,  
  35.                                 SmsReceiver.class));  
  36.                 }  
  37.             }  
  38.         } finally {  
  39.             c.close();  
  40.         }  
  41.     }  
  42.     if (success) {  
  43.         // We successfully sent all the messages in the queue. We don't need to  
  44.         // be notified of any service changes any longer.  
  45.         unRegisterForServiceStateChanges();  
  46.     }  
  47. }  
        在上面的过程中,检测发送队列中是否有未发送的短信,对于多收件人的情况,由于我们之前只发送出去了第一条短信,而且已经将已发送的短信从该队列移出,因此此时的队列中只有其他收件人的短信,然后取出其中的一条,再次进入发送通道,接下来的流程和之前的相同。

        这就是多收件人的发送流程。


Source: http://blog.csdn.net/u010961631/article/details/50272753

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值