Android短信接收过程源码分析

来源:互联网 发布:电影极度寒冷知乎 编辑:程序博客网 时间:2024/05/08 16:11

一、GsmSMSDispatcher注册监听过程

        在《Framework层中的RIL》一文中我们介绍过,Framework与应用层中的Phone对象其实就是用GSMPhone对象生成的PhoneProxy对象(CDMA制式不谈)。可以简单的理解为Phone就是GSMPhone对象
        而GSMPhone又是Framework中与RIL层沟通的对象,因此我们从GSMPhone开始入手分析。
[java] view plain copy
  1. @GSMPhone.java  
  2. public GSMPhone (Context context, CommandsInterface ci, PhoneNotifier notifier, boolean unitTestMode) {  
  3.     //调用父类PhoneBase的构造函数,在内部实现一下赋值:phone.mCM=ci=RILJ  
  4.     super(notifier, context, ci, unitTestMode);  
  5.   
  6.     //初始化GsmSMSDispatcher,用于派发短消息  
  7.     mSMS = new GsmSMSDispatcher(this, mSmsStorageMonitor, mSmsUsageMonitor);  
  8. }  
        上面看到,在GSMPhone的构造函数中,创建了GsmSMSDispatcher对象,这个对象是干什么用的呢?
        其实在对SMS的处理上,不同的制式也有不同的处理方法,与Phone对象类似,SMS同样抽象出来了一个SMSDispatcher类,他把各个制式对于SMS的处理中相同的部分抽象出来,而对于制式中不同的部分派生出了GsmSMSDispatcher子类和CdmaSMSDispatcher子类
        而我们主要关注GsmSMSDispatcher子类:
[java] view plain copy
  1. @GsmSMSDispatcher.java  
  2. public GsmSMSDispatcher(PhoneBase phone, SmsStorageMonitor storageMonitor, SmsUsageMonitor usageMonitor) {  
  3.     super(phone, storageMonitor, usageMonitor);  
  4.     mDataDownloadHandler = new UsimDataDownloadHandler(mCm);  
  5.     //监测3个与SMS有关的状态  
  6.     mCm.setOnNewGsmSms(this, EVENT_NEW_SMS, null);  
  7.     mCm.setOnSmsStatus(this, EVENT_NEW_SMS_STATUS_REPORT, null);  
  8.     mCm.setOnNewGsmBroadcastSms(this, EVENT_NEW_BROADCAST_SMS, null);  
  9. }  
        从上面可以看到,GsmSMSDispatcher的作用主要检测三种短消息事件。而上面的mCm是在其父类SMSDispatcher中进行初始化的:
[html] view plain copy
  1. @SMSDispatcher.java  
  2. protected SMSDispatcher(PhoneBase phone, SmsStorageMonitor storageMonitor, SmsUsageMonitor usageMonitor) {  
  3.     mPhone = phone;  
  4.     //phone是GSMPhone,而phone的mCm就是RILJ  
  5.     mCm = phone.mCM;  
  6. }  
        因此,在GsmSMSDispatcher构造函数中通过mCM.setOnNewGsmSms注册的监听器其实调用的是RILJ中的方法,而这个方法其实存在RILJ的父类BaseCommands中:
[java] view plain copy
  1. @BaseCommands.java  
  2. public void setOnNewGsmSms(Handler h, int what, Object obj) {  
  3.     mGsmSmsRegistrant = new Registrant (h, what, obj);  
  4. }  

        上面的过程,简单来说就是,在GSMPhone的构造函数中,创建了GsmSMSDispatcher的对象用于接收短消息,而GsmSMSDispatcher的初始化过程就是通过GSMPhone对象找到了RILJ(的父类),并把自己所关注的三种RIL层消息注册给RILJ,等待RILJ接收到短信时通知GsmSMSDispatcher


二、RILJ通知GsmSMSDispatcher过程

        下面我们来看,当有短消息上来时,RILJ如何把消息派发下去。
        我们在《Framework层中的RIL》一文中分析过,在RILJ中有两个独立的线程,一个用于向RILC发送数据(RILSender),一个用于接收RILC层上报的数据(RILReceiver)。当有新消息来时,一定会通过RILReceiver发送数据,而他又是通过processResponse处理数据的:
[java] view plain copy
  1. @RIL.java  
  2. private void processResponse (Parcel p) {  
  3.     int type;  
  4.     type = p.readInt();  
  5.     //新消息是属于URC消息  
  6.     if (type == RESPONSE_UNSOLICITED) {  
  7.         processUnsolicited (p);  
  8.     } else if (type == RESPONSE_SOLICITED) {  
  9.     }  
  10. }  
[java] view plain copy
  1. private void processUnsolicited (Parcel p) {  
  2.     switch(response) {  
  3.         case RIL_UNSOL_RESPONSE_NEW_SMS:   
  4.             {  
  5.                 String a[] = new String[2];  
  6.                 a[1] = (String)ret;  
  7.                 SmsMessage sms;  
  8.                 sms = SmsMessage.newFromCMT(a);  
  9.                 if (mGsmSmsRegistrant != null) {  
  10.                     //通过RILJ中的mGsmSmsRegistrant通知他的注册者,也就是GsmSMSDispatcher对象  
  11.                     mGsmSmsRegistrant.notifyRegistrant(new AsyncResult(null, sms, null));  
  12.                 }  
  13.                 break;  
  14.             }  
  15.     }          
  16. }  
        我们继续看notifyRegistrant的过程:
[java] view plain copy
  1. @Registrant.java  
  2. public void notifyRegistrant(AsyncResult ar)  
  3. {  
  4.     internalNotifyRegistrant (ar.result, ar.exception);  
  5. }  
  6. void internalNotifyRegistrant (Object result, Throwable exception)  
  7. {  
  8.     Handler h = getHandler();  
  9.     if (h == null) {  
  10.         clear();  
  11.     } else {  
  12.         Message msg = Message.obtain();  
  13.         msg.what = what;  
  14.         msg.obj = new AsyncResult(userObj, result, exception);  
  15.         h.sendMessage(msg);  
  16.     }  
  17. }  

        看来,RILJ对注册客户端的通知是通过sendMessage的方式实现的


三、SMSDispatcher把短信通知发送到系统广播的过程

        在这一步中,SMSDispatcher将把短信转换为Intent,并通过sendOrderedBroadcast发送到系统中
        上面分析到了sendMessage,还记得当初是GsmSMSDispatcher通过GSMPhone找到了RILJ,并为自己注册了三种关于SMS的监听。
[java] view plain copy
  1. mCm.setOnNewGsmSms(this, EVENT_NEW_SMS, null);  
  2. mCm.setOnSmsStatus(this, EVENT_NEW_SMS_STATUS_REPORT, null);  
  3. mCm.setOnNewGsmBroadcastSms(this, EVENT_NEW_BROADCAST_SMS, null);  
        当前既然有了新的消息,RILJ通过sendMessage的方式发送的Message就会发送给GsmSMSDispatcher,而这个通知是在GsmSMSDispatcher的父类SMSDispatcher中被处理的:
[java] view plain copy
  1. @SMSDispatcher.java  
  2. public void handleMessage(Message msg) {  
  3.     switch (msg.what) {  
  4.         case EVENT_NEW_SMS:  
  5.             //新消息的处理  
  6.             SmsMessage sms;  
  7.             ar = (AsyncResult) msg.obj;  
  8.             sms = (SmsMessage) ar.result;  
  9.             int result = dispatchMessage(sms.mWrappedSmsMessage);  
  10.             break;  
  11.   
  12.         case EVENT_SEND_SMS_COMPLETE: //发送完成  
  13.         case EVENT_STOP_SENDING://停止发送  
  14.     }  
  15. }  
        继续看dispatchMessage的过程,这个过程又进入到了子类GsmSMSDispatcher中处理:
[java] view plain copy
  1. @GsmSMSDispatcher.java  
  2. public int dispatchMessage(SmsMessageBase smsb) {  
  3.     SmsMessage sms = (SmsMessage) smsb;  
  4.   
  5.     if (mSmsReceiveDisabled) {  
  6.         //设备不支持短消息  
  7.         return Intents.RESULT_SMS_HANDLED;  
  8.     }  
  9.   
  10.     boolean handled = false;  
  11.     if (sms.isMWISetMessage()) {  
  12.         //新来语音信箱的短信通知  
  13.         mPhone.setVoiceMessageWaiting(1, -1);  // line 1: unknown number of msgs waiting  
  14.         handled = sms.isMwiDontStore();  
  15.     } else if (sms.isMWIClearMessage()) {  
  16.         //清除语音信箱的短信通知  
  17.         mPhone.setVoiceMessageWaiting(10);   // line 1: no msgs waiting  
  18.         handled = sms.isMwiDontStore();  
  19.     }  
  20.   
  21.     if (!mStorageMonitor.isStorageAvailable() && sms.getMessageClass() != SmsConstants.MessageClass.CLASS_0) {  
  22.         //存储不够,发送提示  
  23.         return Intents.RESULT_SMS_OUT_OF_MEMORY;  
  24.     }  
  25.     //普通短信处理  
  26.     return dispatchNormalMessage(smsb);  
  27. }  
        上面对一些特殊条件进行处理,比如设备不支持短消息,或者接收到的消息是语音信箱提示、设备存储空间不足等,然后就进入普通消息的处理流程,而这个处理过程又进入了父类中:
[java] view plain copy
  1. @SMSDispatcher.java  
  2. protected int dispatchNormalMessage(SmsMessageBase sms) {  
  3.     SmsHeader smsHeader = sms.getUserDataHeader();  
  4.   
  5.     if ((smsHeader == null) || (smsHeader.concatRef == null)) {  
  6.         byte[][] pdus = new byte[1][];  
  7.         pdus[0] = sms.getPdu();  
  8.   
  9.         if (smsHeader != null && smsHeader.portAddrs != null) {  
  10.             if (smsHeader.portAddrs.destPort == SmsHeader.PORT_WAP_PUSH) {  
  11.                 // GSM-style WAP indication  
  12.                 //Wap push 信息的分发  
  13.                 return mWapPush.dispatchWapPdu(sms.getUserData());  
  14.             } else {  
  15.                 // The message was sent to a port, so concoct a URI for it.  
  16.                 dispatchPortAddressedPdus(pdus, smsHeader.portAddrs.destPort);  
  17.             }  
  18.         } else {  
  19.             //普通短消息处理  
  20.             dispatchPdus(pdus);  
  21.         }  
  22.         return Activity.RESULT_OK;  
  23.     } else {  
  24.         SmsHeader.ConcatRef concatRef = smsHeader.concatRef;  
  25.         SmsHeader.PortAddrs portAddrs = smsHeader.portAddrs;  
  26.         return processMessagePart(sms.getPdu(), sms.getOriginatingAddress(),  
  27.                 concatRef.refNumber, concatRef.seqNumber, concatRef.msgCount,  
  28.                 sms.getTimestampMillis(), (portAddrs != null ? portAddrs.destPort : -1), false);  
  29.     }  
  30. }  
        这里看到,对于普通短消息,是通过dispatchPdus()接口分发出去的:
[java] view plain copy
  1. protected void dispatchPdus(byte[][] pdus) {  
  2.     //发送SMS_RECEIVED_ACTION的Intent  
  3.     Intent intent = new Intent(Intents.SMS_RECEIVED_ACTION);  
  4.     intent.putExtra("pdus", pdus);  
  5.     intent.putExtra("format", getFormat());  
  6.     //接收这个消息需要RECEIVE_SMS_PERMISSION的权限  
  7.     dispatch(intent, RECEIVE_SMS_PERMISSION);  
  8. }  
        继续往下看:
[java] view plain copy
  1. public void dispatch(Intent intent, String permission) {  
  2.     mWakeLock.acquire(WAKE_LOCK_TIMEOUT);  
  3.     //向系统中发送有序的广播,并且添加接收权限  
  4.     mContext.sendOrderedBroadcast(intent, permission, mResultReceiver, this, Activity.RESULT_OK, nullnull);  
  5. }  

        由此,Framework就通过SMSDispatcher将短消息用Broadcast的形式发送到了系统中


四、总体流程图

        现在贴出以上过程的流程图。

原创粉丝点击