Android短信接收过程源码分析

xiaoxiao2021-02-28  158

一、GsmSMSDispatcher注册监听过程

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

        上面的过程,简单来说就是,在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 @RIL.java   private void processResponse (Parcel p) {       int type;       type = p.readInt();       //新消息是属于URC消息       if (type == RESPONSE_UNSOLICITED) {           processUnsolicited (p);       } else if (type == RESPONSE_SOLICITED) {       }   }   [java]  view plain  copy private void processUnsolicited (Parcel p) {       switch(response) {           case RIL_UNSOL_RESPONSE_NEW_SMS:                {                   String a[] = new String[2];                   a[1] = (String)ret;                   SmsMessage sms;                   sms = SmsMessage.newFromCMT(a);                   if (mGsmSmsRegistrant != null) {                       //通过RILJ中的mGsmSmsRegistrant通知他的注册者,也就是GsmSMSDispatcher对象                       mGsmSmsRegistrant.notifyRegistrant(new AsyncResult(null, sms, null));                   }                   break;               }       }           }           我们继续看notifyRegistrant的过程: [java]  view plain  copy @Registrant.java   public void notifyRegistrant(AsyncResult ar)   {       internalNotifyRegistrant (ar.result, ar.exception);   }   void internalNotifyRegistrant (Object result, Throwable exception)   {       Handler h = getHandler();       if (h == null) {           clear();       } else {           Message msg = Message.obtain();           msg.what = what;           msg.obj = new AsyncResult(userObj, result, exception);           h.sendMessage(msg);       }   }  

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

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

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

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

四、总体流程图

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

转载请注明原文地址: https://www.6miu.com/read-21459.html

最新回复(0)