Android短信发送流程之多收件人发送(原)
2015-12-12 08:54
525 查看
前面的《Android短信发送流程之长短信发送》中介绍了长短信对于普通短信的区别,而对于多收件人的情况,在SmsMessageSender的queueMessage()方法中我们了解到,发送之前,将多收件人的短信进行拆分,放入"content://sms/queued"队列中,在接下来的流程中,将会在SmsReceiverService中通过sendFirstQueuedMessage()方法取出队列中的第一条短信并发送,那么,队列中的其他消息是如何被发送出去的呢?
我们从第一条短信发送完毕后的流程来寻找答案。
由于在GsmSMSDispatcher向RILJ发送消息时所注册的回应消息是EVENT_SEND_SMS_COMPLETE,所以当短信发送成功时,就会收到该消息的回应。
在SMSDispatcher中对该回应进行处理:
而这里的mSentIntent就是在SmsSingleRecipientSender中指定的,我们再来回顾以下当时的状态:
由于SmsReceiver会把所有Intent转交给SmsReceiverService处理,我们直接来看SmsReceiverService的处理:
然后在sendFirstQueuedMessage()中继续处理:
这就是多收件人的发送流程。
我们从第一条短信发送完毕后的流程来寻找答案。
由于在GsmSMSDispatcher向RILJ发送消息时所注册的回应消息是EVENT_SEND_SMS_COMPLETE,所以当短信发送成功时,就会收到该消息的回应。
在SMSDispatcher中对该回应进行处理:
@SMSDispatcher.java public void handleMessage(Message msg) { switch (msg.what) { case EVENT_SEND_SMS_COMPLETE: //发送成功 handleSendComplete((AsyncResult) msg.obj); break; default: Rlog.e(TAG, "handleMessage() ignoring message of unexpected type " + msg.what); } }然后进入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 { } if (ar.exception == null) { //发送成功 if (tracker.mDeliveryIntent != null) { //将当前短信的tracker保存 deliveryPendingList.add(tracker); } //回调到SmsTracker内部 tracker.onSent(mContext); } else { //发送失败 } }在上面的过程中,对短信发送的结果进行区分,如果失败,将会根据失败原因通知SmsTracker,如果成功,将会进入SmsTracker中继续处理:
public void onSent(Context context) { boolean isSinglePartOrLastPart = true; if (mUnsentPartCount != null) { //判断是否已经将长短新最后一条发送完毕 isSinglePartOrLastPart = mUnsentPartCount.decrementAndGet() == 0; } if (isSinglePartOrLastPart) { //当前所有短信发送完毕,更新数据库状态 boolean success = true; if (mAnyPartFailed != null && mAnyPartFailed.get()) { success = false; } if (success) { setMessageFinalState(context, Sms.MESSAGE_TYPE_SENT); } else { setMessageFinalState(context, Sms.MESSAGE_TYPE_FAILED); } } //把发送短信之前保存在SmsTracker中的Intent取出来发送出去,通知短信已经发送成功。 if (mSentIntent != null) { try { // Extra information to send with the sent intent Intent fillIn = new Intent(); if (mMessageUri != null) { // Pass this to SMS apps so that they know where it is stored fillIn.putExtra("uri", mMessageUri.toString()); } if (mUnsentPartCount != null && isSinglePartOrLastPart) { // Is multipart and last part fillIn.putExtra(SEND_NEXT_MSG_EXTRA, true); } mSentIntent.send(context, Activity.RESULT_OK, fillIn); } catch (CanceledException ex) { Rlog.e(TAG, "Failed to send result"); } } }由于此时无论是长短信还是普通短信,都已经发送完毕(只发送了一个收件人),因此isSinglePartOrLastPart的判定将会是true,从而更新数据库中该短信的状态,然后再将发送时附加在SmsTracker中的mSentIntent取出来并发送出去,同时指定返回结果为“Activity.RESULT_OK”。
而这里的mSentIntent就是在SmsSingleRecipientSender中指定的,我们再来回顾以下当时的状态:
@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(); 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); 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<PendingIntent> deliveryIntents = new ArrayList<PendingIntent>(messageCount); ArrayList<PendingIntent> sentIntents = new ArrayList<PendingIntent>(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; }从这里我们看到,当前的mSentIntent发送对象是SmsReceiver,内容是MESSAGE_SENT_ACTION,而且包含了附加数据EXTRA_MESSAGE_SENT_SEND_NEXT=true,并且SmsTracker发送该Intent时传送的结果是“Activity.RESULT_OK”。
由于SmsReceiver会把所有Intent转交给SmsReceiverService处理,我们直接来看SmsReceiverService的处理:
@SmsReceiverService.java 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); }对于当前的Intent,将会在handleSmsSent()中处理:
private void handleSmsSent(Intent intent, int error) { Uri uri = intent.getData(); mSending = false; //EXTRA_MESSAGE_SENT_SEND_NEXT表示是否是长短新的最后一条 boolean sendNextMsg = intent.getBooleanExtra(EXTRA_MESSAGE_SENT_SEND_NEXT, false); if (mResultCode == Activity.RESULT_OK) { //将已经发送成功的短信移入发件箱,更新其状态为已发送 if (!Sms.moveMessageToFolder(this, uri, Sms.MESSAGE_TYPE_SENT, error)) { Log.e(TAG, "handleSmsSent: failed to move message " + uri + " to sent folder"); } if (sendNextMsg) { //继续发送其他收件人 sendFirstQueuedMessage(); } // Update the notification for failed messages since they may be deleted. MessagingNotification.nonBlockingUpdateSendFailedNotification(this); } else if ((mResultCode == SmsManager.RESULT_ERROR_RADIO_OFF) || (mResultCode == SmsManager.RESULT_ERROR_NO_SERVICE)) { // We got an error with no service or no radio. Register for state changes so // when the status of the connection/radio changes, we can try to send the // queued up messages. registerForServiceStateChanges(); // We couldn't send the message, put in the queue to retry later. Sms.moveMessageToFolder(this, uri, Sms.MESSAGE_TYPE_QUEUED, error); mToastHandler.post(new Runnable() { public void run() { Toast.makeText(SmsReceiverService.this, getString(R.string.message_queued), Toast.LENGTH_SHORT).show(); } }); } else if (mResultCode == SmsManager.RESULT_ERROR_FDN_CHECK_FAILURE) { messageFailedToSend(uri, mResultCode); mToastHandler.post(new Runnable() { public void run() { Toast.makeText(SmsReceiverService.this, getString(R.string.fdn_check_failure), Toast.LENGTH_SHORT).show(); } }); } else { messageFailedToSend(uri, error); if (sendNextMsg) { sendFirstQueuedMessage(); } } }由于当前resultCode=OK,并且sendNextMsg=true,首先会通过Sms.moveMessageToFolder()操作将发送成功的短信从"content://sms/queued"队列移动到"content://sms/sent"队列。
然后在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"); // date ASC so we send out in 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); 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; // Sending current message fails. Try to send more pending messages // if there is any. sendBroadcast(new Intent(SmsReceiverService.ACTION_SEND_MESSAGE, null, this, SmsReceiver.class)); } } } finally { c.close(); } } if (success) { // We successfully sent all the messages in the queue. We don't need to // be notified of any service changes any longer. unRegisterForServiceStateChanges(); } }在上面的过程中,检测发送队列中是否有未发送的短信,对于多收件人的情况,由于我们之前只发送出去了第一条短信,而且已经将已发送的短信从该队列移出,因此此时的队列中只有其他收件人的短信,然后取出其中的一条,再次进入发送通道,接下来的流程和之前的相同。
这就是多收件人的发送流程。
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories