Android中SMS的接收处理

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

 

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

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

其中的类型

  • mReceiver: RILReceiver
  • mReceiverThread: Thread

 

RILReceiver实现了Runnable

Android中SMS的接收处理

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

01public void run() {
02    int retryCount= 0;
03 
04    try {for (;;) {
05        LocalSockets = null;
06        LocalSocketAddress l;
07 
08        try {
09            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]中处理。

01private void processResponse (Parcel p) {
02    int type;
03 
04    type = p.readInt();
05 
06     if(type == RESPONSE_UNSOLICITED) {
07        processUnsolicited (p);
08     }else if (type == RESPONSE_SOLICITED) {
09        processSolicited (p);
10     }
11 
12    releaseWakeLockIfDone();
13 }
 

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

 

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

1SmsMessage 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)。

 Android中SMS的接收处理

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

mCm.setOnNewSMS(this, EVENT_NEW_SMS, null);

 Android中SMS的接收处理

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

01SmsMessage sms;
02 
03ar = (AsyncResult) msg.obj;
04 
05if (ar.exception != null) {
06    Log.e(TAG, "Exception processing incoming SMS. Exception:" +ar.exception);
07    return;
08}
09 
10sms = (SmsMessage) ar.result;
11try {
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:”指定端口。

对长短信,调用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
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值