田海立

2012-02-22

在解析WAP PUSH over SMS时,看了一下Android里SMS接收的流程,并按照自己需要的流程记录,其他分支的详细处理并未讲述。PDU数据的encode/decode也并未在本文中进行解析,有兴趣的读者可以到相应的代码处自己解读一下。

Android中,RIL用RILReciever接收SMS pdu,并根据不同的信息类型用相应函数来处理。因手机制式的差异,用GsmSmsDispatcher或CdmaSmsDispatcher来做各自的消息处理并分发。最后的分发是通过发送相应的Broadcast,所以,对感兴趣的消息处理,可以注册Receiver来监听相应的Broadcast,实现自己的SMS/MMS/Wap push,以及其他类型消息的接收处理。

RIL构造函数中,Receiver的初始化[在文件RIL.java中]

        mReceiver = newRILReceiver();        mReceiverThread =new Thread(mReceiver, "RILReceiver");        mReceiverThread.start();

其中的类型

  • mReceiver: RILReceiver
  • mReceiverThread: Thread

RILReceiver实现了Runnable

Android中SMS的接收处理_第1张图片

关注RILReceiver线程的实现[在RILReceiver::run()中]

        public void run() {            int retryCount= 0;            try {for (;;) {                LocalSockets = null;                LocalSocketAddress l;                try {                    s = newLocalSocket();                    l = newLocalSocketAddress(SOCKET_NAME_RIL,                           LocalSocketAddress.Namespace.RESERVED);                    s.connect(l);                } catch (IOException ex){                    // 。。。                }                retryCount= 0;                mSocket =s;                int length= 0;                try {                    InputStreamis = mSocket.getInputStream();                    for(;;) {                       Parcel p;                        length = readRilMessage(is, buffer);                        if(length < 0) {                           // End-of-stream reached                           break;                        }                        p =Parcel.obtain();                       p.unmarshall(buffer, 0, length);                       p.setDataPosition(0);                         processResponse(p);                       p.recycle();                    }                } catch(java.io.IOException ex) {                    // …                } catch(Throwable tr) {                    // …                }                // …            }} catch(Throwable tr) {               Log.e(LOG_TAG,"Uncaught exception", tr);            }        }

RILReceiver线程不停的监听本地Socket,读到数据之后在processResponse()[Line#37]中处理。

   private void processResponse (Parcel p) {       int type;        type = p.readInt();         if(type == RESPONSE_UNSOLICITED) {           processUnsolicited (p);        }else if (type == RESPONSE_SOLICITED) {           processSolicited (p);        }        releaseWakeLockIfDone();    }

如果类型属于Unsolicited消息,则在processUnsolicited()中处理。收到的短信是属于Unsolicited信息,看它的实现。

processUnsolicited()中很长的switch… case语句中对收到短信的处理在case RIL_UNSOL_RESPONSE_NEW_SMS:

              SmsMessage sms;                sms = SmsMessage.newFromCMT(a);               if (mSMSRegistrant != null) {                   mSMSRegistrant.notifyRegistrant(new AsyncResult(null, sms, null));               }

这里的SmsMessage是android.telephony.SmsMessage。newFromCMT()中会根据电话类型(GSM/CDMA)选择具体的SmsMessage进行封装(因为Rational Rose中,同一工程中,不同包内的类也不允许同名,com.android.internal.telephony.gsm.SmsMessage用gsm.SmsMessage代替;com.android.internal.telephony.cdma.SmsMessage用cdma.SmsMessage代替。实际类型都是SmsMessage)。

Android中SMS的接收处理_第2张图片

mSMSRegistrant是RIL父类的成员。通过setOnNewSMS()/unSetOnNewSMS()设置和取消设置。SMSDispatcher的构造函数中注册了SMS的Registrant

mCm.setOnNewSMS(this, EVENT_NEW_SMS, null);

Android中SMS的接收处理_第3张图片

所以,调用mSMSRegistrant.notifyRegistrant(newAsyncResult(null, sms, null))之后,执行的是SMSDispatcher中Handler在handleMessage()中对EVENT_NEW_SMS的处理:

           SmsMessage sms;            ar = (AsyncResult) msg.obj;            if (ar.exception != null) {               Log.e(TAG, "Exception processing incoming SMS. Exception:" +ar.exception);               return;           }           sms = (SmsMessage) ar.result;           try {               int result = dispatchMessage(sms.mWrappedSmsMessage);               if (result != Activity.RESULT_OK) {                    // RESULT_OK means thatmessage was broadcast for app(s) to handle.                    // Any other result, weshould ack here.                    boolean handled = (result== Intents.RESULT_SMS_HANDLED);                   notifyAndAcknowledgeLastIncomingSms(handled, result, null);               }           } catch (RuntimeException ex) {               Log.e(TAG, "Exception dispatching message", ex);               notifyAndAcknowledgeLastIncomingSms(false,Intents.RESULT_SMS_GENERIC_ERROR, null);           }

SMSDispatcher是一个abstract的类,dispatchMessage()的具体实现在GsmSMSDispatcherCdmaSMSDispatcher中。

GsmSMSDispatcher::dispatchMessage()中,会对Class 0类型的短信,有目标端口的短信,和长短信做处理。

目标端口为WAPPUSH的信息,则调用mWapPush.dispatchWapPdu(sms.getUserData(),pdus)让WAPPUSH来处理;其它未知的端口,则用“sms://localhost:<port>”指定端口。

对长短信,调用processMessagePart()进行组合处理。

1)有目标端口且目标端口是WAP PUSH(SmsHeader.PORT_WAP_PUSH)的信息,用WapPushOverSms::dispatchWapPdu()来处理:

根据不同的contentType:

-> dispatchWapPdu_PushCO();

-> dispatchWapPdu_MMS();

-> dispatchWapPdu_default()

2)有目标地址且目标端口不是WAP PUSH的信息,在SMSDispatcher::dispatchPortAddressedPdus()中处理:

Uri uri =Uri.parse("sms://localhost:" + port);

Intent intent= new Intent(Intents.DATA_SMS_RECEIVED_ACTION, uri);

intent.putExtra("pdus", pdus);

dispatch(intent, "android.permission.RECEIVE_SMS");

3)通常的无目标地址的信息(普通短信),在SMSDispatcher::dispatchPdus()中处理:

Intent intent= new Intent(Intents.SMS_RECEIVED_ACTION);

intent.putExtra("pdus", pdus);

dispatch(intent, "android.permission.RECEIVE_SMS");


更多相关文章

  1. Android如何判断当前网络类型(联网,2g,3g,wifi等)
  2. Android Q (十七) Android Q 行为变更:以 Android Q 为目标平台的
  3. 转android 模拟器中做端口重定向
  4. android中自定义数据类型在两个activity间的传递
  5. 解决adb connect 连接Android设备报错:由于目标计算机积极拒绝,无
  6. android 获取SIM卡的类型··

随机推荐

  1. Android package属性、package name和App
  2. android 输入对话框 确认对话框
  3. adb通过wifi连接android设备的方法
  4. android字体大小多屏幕适配
  5. android 虚拟按键源码流程分析
  6. android SimpleOnGestureListener详解
  7. Android(安卓)自定义对话框
  8. Android 模拟器 HAXM硬件加速安装
  9. 关于服务端设置了IPV6时,Android请求网络
  10. android 自定义权限问题