灯火互联
管理员
管理员
  • 注册日期2011-07-27
  • 发帖数41778
  • QQ
  • 火币41290枚
  • 粉丝1086
  • 关注100
  • 终身成就奖
  • 最爱沙发
  • 忠实会员
  • 灌水天才奖
  • 贴图大师奖
  • 原创先锋奖
  • 特殊贡献奖
  • 宣传大使奖
  • 优秀斑竹奖
  • 社区明星
阅读:4116回复:0

Android中SMS的接收处理

楼主#
更多 发布于:2012-09-06 13:42


在解析WAPPUSH 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中]
[java]
mReceiver = newRILReceiver();
mReceiverThread =new Thread(mReceiver, "RILReceiver");
mReceiverThread.start();
其中的类型
mReceiver: RILReceiver
mReceiverThread: Thread

RILReceiver实现了Runnable




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

[java] 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);
    }
}
        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]中处理。

[java] private void processResponse (Parcel p) {
    int type;

    type = p.readInt();

     if(type == RESPONSE_UNSOLICITED) {
        processUnsolicited (p);
     }else if (type == RESPONSE_SOLICITED) {
        processSolicited (p);
     }

    releaseWakeLockIfDone();
}
   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:
[java] SmsMessage sms;

sms = SmsMessage.newFromCMT(a);
if (mSMSRegistrant != null) {
     mSMSRegistrant.notifyRegistrant(new AsyncResult(null, sms, null));
}
              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)。




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




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

[java] 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);
}
           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()的具体实现在GsmSMSDispatcher或CdmaSMSDispatcher中。

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");



喜欢0 评分0
游客

返回顶部