Android 4.2短信发送流程小记

Android 4.2短信发送流程。

1.      ComposeMessageActivity接收用户输入并且响应用户点击事件。

函数调用顺序confirmSendMessageIfNeeded() ->sendMessage()

sendMessage中会调用到WorkingMessage的send方法。

2.      WorkingMessage的send方法会对此时消息做判断,如果包含Email或是MMS则启动彩信发送程序发送SendReq请求向MMSC. 彩信流程将会在以后介绍。

如果send方法判定为短信,则会new新线程。

3.      在新建线程中会调用preSendSmsWorker函式。

preSendSmsWorker其实只做以下几件事:

a.      调用MessageStatusListener的onPreMessageSent方法通知UI线程更新状态。

b.      调用sendSmsWorker函数去发送短信,参数包含了消息体接收人,所属线程id(此为消息所属会话线程ID,并非操作系统中的线程ID,个人感觉名字起的有待商榷)

4.      sendSmsWorker函数中会创建SmsMessageSender实例并调用其sendMessage函式。

5.      SmsMessageSender的sendMessage其实只是调用了自己的queueMessage。

queueMessage顾名思意将消息入队。其实就是调用Framework中Telephony.java的addMessageToUri将消息插入至SMS数据库(数据库的实现在smsprovider.java)

其中主要填写以下字段:

a.      SUB_ID: 用于双卡标识

b.      ADDRESS: 发送地址

c.      DATE: 发送时间

d.      READ: 是否已读

e.      SUBJECT: 短信么有

f.       BODY:消息体

g.      STATUS:分为STATUS_COMPLETE,STATUS_PENDING,STATUS_FAILED,STATUS_NONE,此时会写为STATUS_PENDING。

h.      THREAD_ID: 会话线程ID.

值得注意的是STATUS与smsprovider在insert时会加入的TYPE, TYPE 中包含了MESSAGE_TYPE_INBOX, MESSAGE_TYPE_SENT, MESSAGE_TYPE_QUEUED, MESSAGE_TYPE_OUTBOX等等。此时我们是MESSAGE_TYPE_QUEUED类型。

6.      此时我们从Framework中回到app中。继续看queueMessage函式做了啥,在把数据加入队列后会发送广播消息ACTION_SEND_MESSAGE。此消息由SmsReceiver.java去接收.

7.      SmsReceiver.java接到消息都干了啥呢?其实他么干啥事,就去startservice.这也是我们编写android程序时常用的方法,在receiver中启动服务。毕竟大家都知道receiver中最好不处理长时间的数据,因为如果时间太长会阻塞UI线程并触发ANR.

8.      SmsReceiverService的handleMessage会接收到ACTION_SEND_MESSAGE,此时会调用handleSendMessage,它会判断是否在发送状态,如果不在发送中则会调用sendFirstQueuedMessage去发送队列中的消息。

此队列就是我们之前调用framework的addMessageToUri函式插入的消息的队列。

9.      取到队列中的消息后我们会构造SmsSingleRecipientSender实例,SmsSingleRecipientSender用于单笔消息的发送。SmsSingleRecipientSender的sendMessage函式将被调用。

10.  sendMessage()主要做了以下几件事:

a.      如果目的地址为EMail地址,则会调用MmsConfig的getEmailGateway()取得预配置的SMS Email发送网关地址作为发送目的地址。

b.      修改数据库中消息的TYPE,由MESSAGE_TYPE_QUEUED至MESSAGE_TYPE_OUTBOX。

c.      调用SmsManager的sendMultipartTextMessage去发送消息,如果是双卡会调用MSimSmsManager的sendMultipartTextMessage,此代码应该是高通进行修改的(个人看法)。MSimSmsManager主要加入了subscription参数以便区别哪张卡。此时单卡多卡会出现很多区别,使用的isms服务也存在区别。

11.  sendMessage()调用MSimSmsManager的sendMultipartTextMessage后将会向ServiceManager取得"isms_msim"服务(单卡时为”isms”).

如果为长短信则会调用MSimIccSmsInterfaceManagerProxy的sendMultipartText函式去根据subscription取得相应的MSimIccSmsInterfaceManager,并调用其sendMultipartText。

如果是普通短信则会最终调用到MSimIccSmsInterfaceManager的sendText。

12.  无论是sendMultipartText或sendText都会调用到ImsSMSDispatcher的相应函式,并且都会判断其发送方式CDMA或GSM. 两者的实例类为CdmaSMSDispatcher和GsmSMSDispatcher。

如果是发送长短信,则会调用到SMSDispatcher基类的sendMultipartText。主要是调用sendNewSubmitPdu函式去逐个发送,此函式被CdmaSMSDispatcher和GsmSMSDispatcher分别实现。

在sendNewSubmitPdu函式中会调用sendRawPdu函式,后会调用CdmaSMSDispatcher或GsmSMSDispatcher的sendSms函式,这里将会调用到Ril的sendSMS.

13.  Ril中将组装RILRequest,并发送至ril层。

14.  当RIL发送成功后processSolicited将接收到RIL_REQUEST_SEND_SMS的response.此时会触发消息并由SMSDispatcher的handleMessage接收,消息名为EVENT_SEND_SMS_COMPLETE,此时会调用handleSendComplete函式并把结果传入(AsyncResult)。

以下几件事会被handleSendComplete执行:

a.      如果发现mDeliveryIntent不等于空则表明需要传送报告,所以会将SmsTracker加入deliveryPendingList以等待传送报告回执。

b.      如果返回的exception不存在,则说明发送时未出现异常,所以会发送intent至SmsReceiver。(可能这里会感觉Ril怎么能知道通知谁并用什么action呢?其实都是得益于发送时传入的deliveryIntents与sentIntents,这个可以查看SmsSingleRecipientSender的sendMessage,每当你发送时都会事先构造好回执的intent.)SmsReceiverService收到MESSAGE_SENT_ACTION后会触发下一个队列中消息的发送。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值