1、短信应用包路径为packages/apps/Mms,查看配置文件AndroidManifest.xml文件,可以找到MMs应用的入口,就是ConversationList.java。
图7.1查看短信的入口
2、在默认的Android虚拟设备启动时,进入ConversationList.java显示短信的会话列表界面,不会有任何短信会话。
在ConversationList.java显示的短信会话列表界面,点击屏幕左下角的“新建短信”,进入短信编辑界面。此按钮的响应事件是ConversationList类中的createNewMessage(),他最主要的作用就是启动ComposeMessageActivity类的Activity。
图7.2启动ComposeMessageActivity类
- 在ComposeMessageActivity类里面,可以编辑短信的标题、内容等。当我们编辑好了,点击发送,会响应当前类里面的onClick方法,在onclick方法里面会调用confirmSendMessageIfNeeded()方法。(在10390行处)
图7.31发送短信调用confirmSendMessageIfNeeded()
confirmSendMessageIfNeeded()方法:
图7.32获取isMms,调用sendMsimMessage()、sendMessage()
sendMsimmessage()方法:
图7.33 sendMsimmessage()调用sendMessage()方法
confirmSendMessageIfNeeded()有两大作用:
- 获取编辑内容是短信还是彩信的标志isMms,并根据此标志判断输入的是短信接收方的地址是否正确,如果不正确弹出相应的信息提示。
- 调用当前类中的sendMessage方法中的处理逻辑,sendMessage方法最关键的是调用mWorkingMessage.send()继续发起发送短信的请求调用。
mWorkingMessage是WorkingMessage类型,当前编辑的短信内容被抽象成了WorkingMessage类,他实现了当前编辑的短信信息涉及的所有行为和操作,其中包含:发送当前信息、为当前信息增加主题或者附件、设置当前信息的类型(短信或者彩信)、保存草稿、丢弃当前信息、设置当前信息所属的会话等。
图7.4 sendMessage方法调用mWorkingMessage.send()
接着看一下WorkingMessage的send()
……
// 准备往磁盘中写
//短信和彩信分开处理,if中处理发送彩信,else中处理发送短信
//准备发送彩信所需要的参数如:mmsUri、persister、slideshow等
//启动线程完成发送短信的操作,目的是不影响界面的返回。
sendMmsWorker(…)//调用sendMmsWorker返回继续发送短信的请求;
updateSendStates()//更新Conversation列表的界面显示。
//启动线程发送短信的操作,目的是不影响界面的返回;
sendMmsWorker(…)//调用sendMmsWorker返回继续发送短信的请求;
图7.5 WorkingMessage处理短信发送
总结:WorkingMessage类应该看作发送短信的起点,在发送短信的时候首先调用其send方法。他的if…else分别处理发送彩信、短信,如果发送短信,将当前类中的preSendSmsWorker方法继续调用sendSmsWork方法,而sendSmsWork方法中的处理逻辑主要分为两步:
- 创建SmsMessageSender对象sender
- 调用sender.sendMessage继续发起发短信的请求。
图7.6 preSendSmsWorker方法调用sendSmsWork()
图7.7 sendSmsWork()创建SmsMessageSender对象sender,调用sender.sendMessage
- SmsMessageSender类,短信发送处理。
图7.8 sender.sendMessage()调用queueMessage()
……
//循环处理多个短信接收方
……
//调用Telephony Framework层中的addMessageToUri静态方法,记录待发送的短信的内容(将需要发送的短信内容保存到数据库)
//数据库操作异常
//发送ACTION_SEND_MESSAGE广播,SmsReceiver类中的onReceiver方法会接收。
图7.9发送ACTION_SEND_MESSAGE广播
6、SmsReceiver类中的onReceiver方法接受广播。
图7.10调用onReceiveWithPrivilege()
onReceiveWithPrivilege()方法详细作用:
图7.11启动SmsReceiverService
通过AIDL启动SmsReceiverService,进入SmsReceiverService类的onStartCommand方法。
7、SmsReceiverService
进入SmsReceiverService类的onStartCommand方法。此方法通过mServiceHandler对象,在当前类中进行Handler消息的发送和接收处理。在handleMessage方法中,根据Action请求的不同类型,分为4个分支,在短信发送请求的过程中,进入ACTION_SEND_MESSAGE分支调用handleSendMessage方法,而handleSendMessage方法会继续调用sendFirstQueuedMessage方法继续传递发送短信的请求。
图12 SmsReceiverService类的onStartCommand(),执行mServiceHandler.sendMessage(msg)将消息发给自己,然后去自己的handleMessage()处理
接着会进入自己的handleMessage处理,接收到的消息是第5步发送ACTION_SEND_MESSAGE广播,然后会调用handleSendMessage()方法。
图13 handleMessage处理调用handleSendMessage()
看一下handleSendMessage(),handleSendMessage()继续调用sendFirstQueuedMessage()继续传递发送短信的请求。
图14 handleSendMessage()调用sendFirstQueuedMessage()
sendFirstQueuedMessage()方法的处理逻辑是从数据库中读取等待发送的短信的内容,根据短信内容创建SmsSingleRecipientSender对象,并调用其sendMessage方法,继续发出发送短信的请求。
//从数据库中获取要发送的短信的内容
……
//根据短信的内容创建SmsSingleRecipientSender对象
//调用他的sendMessage方法
图15数据库中获取短信内容,调用SmsSingleRecipientSender对象的sendMessage
8、SmsSingleRecipientSender类:
查看SmsSingleRecipientSender对象的sendMessage()方法:
……
//获取SmsManager对象,SmsManager位于Telephony framework层
//根据彩信内容拆分出单个或者多个彩信
//根据短信内容长短拆分出单个或者多个短信
//验证拆分出来的短信个数是否正常,以及异常处理
//通过sms类的静态方法调用,将即将发送的短信保存到发件箱中
//deliveryIntents和sentIntents两个list增加对应的Intent对象
//调用Telephony Frameworks层中的方法,继续发起短信发送请求
图16 SmsSingleRecipientSender对象的sendMessage()方法
总结:SmsSingleRecipientSender对象的sendMessage()方法
- 调用SmsManager对象的divideMessage方法,完成短信的拆分;国内短信中的内容超过160byte,将会进行拆分;
- 调用Sms类中的静态方法moveMessageToFolder,将即将发送的短信移动到发件箱;
- deliveryIntents用于短信发送状态报告的回调Intent,sentIntent作为短信发送结果的回调intent;
- 调用SmsManager对象的sendMultipartTextMessage方法,完成单挑或者多条短信的发送。
- SmsManager类
SmsManager类在TelePhony Framework层提供短信操作的相关接口供应用层调用。该类提供了短信的拆分、发送、将短信复制到SIM卡上、从SIM卡上删除短信、小区广播等操作接口。
1) 首先获取SmsManager对象并调用它的getDefault方法;其次,调用SmsManager对象的divideMessage方法完成短信的拆分、调用SmsManager对象的sendMultipartTextMessage方法完成短信的发送。
注意:是Telephony目录下的,不是Telephony gsm目录下的SmsManager。
图17 调用sendMultipartTextMessageInternal()
2) sendMultipartTextMessageInternal()方法介绍:
//判断短信的长度
//获取IccSmsInterfaceManager服务,调IccSmsInterfaceManager服务发送短信接口
//获取单个的deliveryIntent和sentIntent
图18 sendMultipartTextMessage间接调IccSmsInterfaceManager服务发送短信接口
3)IccSmsInterfaceManager服务发送短信接口:这里拿发送多条短息举例,单条短信发送与其相似。
UiccSmsController.java的sendMultipartTextForSubscriber方法,该方法会调用IccSmsInterfaceManager服务发送短信接口。
图18该方法会调用IccSmsInterfaceManager服务发送短信接口,并调用他发送短信的方法
IccSmsInterfaceManager服务发送短信接口:
图19获取短信发送接口
图20调mDispatcher的方法发送短信
mDispatcher对象是SMSDispatcher类型的,字面理解“短信分发器”,他的创建与Tracker对象的创建时机一样,均是在Phone对象创建时同时构造。
总结:
SmsManager对象接收到sendMultipartTextMessage方法调用,分别处理长短信发送和普通短信发送;最后是调用RIL对象提供的sendSMS方法,完成短信发送的RIL请求调用。
短信发送到短信中心之后,RIL会向SMSDispatcher发起EVENT_SEND_SMS_COMPLETE类型的消息通知,SMSDispatcher对象最终调用handleSendComplete方法响应短信发送的返回结果。
-
- SMSDispatcher类
SMSDispatcher的sendText与sendMultipartText处理逻辑一样,可以分为两步:
1)将短信内容构造为SubmitPdu;
2)调用mCm.sendSMS方法向RIL发起短信发送请求。
SMSDispatcher短信分发器从调用sendText与sendMultipartText,到最后与RIL的交互,在这期间还会调用sendRawPdu、sendSms方法。
图21 mCi是RIL对象
mCi是RIL对象。至此短信传到了RIL层,短信请求从应用层分多个步骤传到Java Frameworks层,最后是Java Frameworks框架层拆分短信、创建PDU对象等操作,最终会调用RIL对象中发送短信的方法,将短信发送的请求转换为对应的RIL请求调用。
短信发送成功会保存对应的tracker对象到deliveryPendingList,在处理短信状态报告的同时会发出sentIntent的广播通知。短信发送失败有3次短信重发的处理机制。
图22保存对应的tracker对象到deliveryPendingList
图23调用onSent()发出sentIntent的广播通知
总结:短信发送成功决定性因素:
手机Modem将短信成功发送到短信中心;
短信中心成功发送短信到短信接收方。
-
- 短信发送状态处理机制
在与RIL交互的时候,将RIL请求处理的结果CallBack回调handler消息对象作为参数传递给RIL对象,RIL发起短信发送的AT命令,Modem将短信发送出去并将结果告诉RIL,RIL接收到response后将使用对应的handler对象发送消息通知进行回调;
1)接着查看GsmSMSDispatcher对象中的sendSms方法,向RIL发出短信发送请求。
图24sendSms方法调用sendSmsByPstn()
sendSmsByPstn()方法中
//创建回调的handler消息对象,消息类型为EVENT_SEND_SMS_COMPLETE
Message reply = obtainMessage(EVENT_SEND_SMS_COMPLETE, tracker);
//调用RI了对象的发送短信请求方法
mCi.sendSMS(……);
图25 tracker会保存在replay里面,传给RIL
看一下tracker
图26
2)SMSDispatcher会接收RIL对象发起的CallBack通知,在handleMessage中处理消息类型为EVEVT_SEND_SMS_COMPLETE消息。然后handleMessage会调用handlesendComplete方法处理。
总结:
1)SmsTracker对象在SMSDispatcher中创建,并传递给RIL,最后RIL对象会发出EVEVT_SEND_SMS_COMPLETE消息,该消息中仍然保存了SMSTracker对象,可见他是一直存在在SMSDispatcher与RIL对象的短信发送的请求的返回过程中。
2)通过SMSTracker对象获取sentIntent,并发出广播通知,根据sentIntent的创建过程,找到在SmsReceiver类中的onReceive方法接收此广播,然后启动SmsReceiverService服务,并在handleSmsSent方法中最终处理发送短信的返回结果。
3)短信如果发送失败,会有三次重发的机制,在SMSDispatcher类中的handleSendComplete方法中处理。