Android中SMS的接收处理

原作者地址:http://blog.csdn.net/thl789/article/details/7284383


在解析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中]

[java]  view plain copy
  1. mReceiver = newRILReceiver();  
  2. mReceiverThread =new Thread(mReceiver, "RILReceiver");  
  3. mReceiverThread.start();  

其中的类型

  • mReceiver: RILReceiver
  • mReceiverThread: Thread

 

RILReceiver实现了Runnable

RILReceiver

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

[java]  view plain copy
  1. public void run() {  
  2.     int retryCount= 0;  
  3.   
  4.     try {for (;;) {  
  5.         LocalSockets = null;  
  6.         LocalSocketAddress l;  
  7.   
  8.         try {  
  9.             s = newLocalSocket();  
  10.             l = newLocalSocketAddress(SOCKET_NAME_RIL,  
  11.                    LocalSocketAddress.Namespace.RESERVED);  
  12.             s.connect(l);  
  13.         } catch (IOException ex){  
  14.             // 。。。  
  15.         }  
  16.   
  17.         retryCount= 0;  
  18.         mSocket =s;  
  19.         int length= 0;  
  20.   
  21.         try {  
  22.             InputStreamis = mSocket.getInputStream();  
  23.   
  24.             for(;;) {  
  25.                Parcel p;  
  26.   
  27.                length = readRilMessage(is, buffer);  
  28.                 if(length < 0) {  
  29.                    // End-of-stream reached  
  30.                    break;  
  31.                 }  
  32.   
  33.                 p =Parcel.obtain();  
  34.                p.unmarshall(buffer, 0, length);  
  35.                p.setDataPosition(0);  
  36.   
  37.                 processResponse(p);  
  38.                p.recycle();  
  39.             }  
  40.         } catch(java.io.IOException ex) {  
  41.             // …  
  42.         } catch(Throwable tr) {  
  43.             // …  
  44.         }  
  45.   
  46.         // …  
  47.     }} catch(Throwable tr) {  
  48.        Log.e(LOG_TAG,"Uncaught exception", tr);  
  49.     }  
  50. }  

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

[java]  view plain copy
  1. private void processResponse (Parcel p) {  
  2.     int type;  
  3.   
  4.     type = p.readInt();  
  5.   
  6.      if(type == RESPONSE_UNSOLICITED) {  
  7.         processUnsolicited (p);  
  8.      }else if (type == RESPONSE_SOLICITED) {  
  9.         processSolicited (p);  
  10.      }  
  11.   
  12.     releaseWakeLockIfDone();  
  13.  }  
 

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

 

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

[java]  view plain copy
  1. SmsMessage sms;  
  2.   
  3.  sms = SmsMessage.newFromCMT(a);  
  4.  if (mSMSRegistrant != null) {  
  5.      mSMSRegistrant.notifyRegistrant(new AsyncResult(null, sms, null));  
  6.  }  

这里的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)。

 SmsMessage

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

mCm.setOnNewSMS(this, EVENT_NEW_SMS, null);

 Regstrant 

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

[java]  view plain copy
  1. SmsMessage sms;  
  2.   
  3. ar = (AsyncResult) msg.obj;  
  4.   
  5. if (ar.exception != null) {  
  6.     Log.e(TAG, "Exception processing incoming SMS. Exception:" +ar.exception);  
  7.     return;  
  8. }  
  9.   
  10. sms = (SmsMessage) ar.result;  
  11. try {  
  12.     int result = dispatchMessage(sms.mWrappedSmsMessage);  
  13.     if (result != Activity.RESULT_OK) {  
  14.          // RESULT_OK means thatmessage was broadcast for app(s) to handle.  
  15.          // Any other result, weshould ack here.  
  16.          boolean handled = (result== Intents.RESULT_SMS_HANDLED);  
  17.         notifyAndAcknowledgeLastIncomingSms(handled, result, null);  
  18.     }  
  19. catch (RuntimeException ex) {  
  20.     Log.e(TAG, "Exception dispatching message", ex);  
  21.     notifyAndAcknowledgeLastIncomingSms(false,Intents.RESULT_SMS_GENERIC_ERROR, null);  
  22. }  

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

 


版权声明:本文为博主原创文章,未经博主允许不得转载。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值