Android中,RIL用RILReciever接收SMS pdu,并根据不同的信息类型用相应函数来处理。因手机制式的差异,用GsmSmsDispatcher或CdmaSmsDispatcher来做各自的消息处理并分发。最后的分发是通过发送相应的Broadcast,所以,对感兴趣的消息处理,可以注册Receiver来监听相应的Broadcast,实现自己的SMS/MMS/Wap push,以及其他类型消息的接收处理。
RIL构造函数中,Receiver的初始化[在文件RIL.java中]
1 | mReceiver = newRILReceiver(); |
2 | mReceiverThread = new Thread(mReceiver, "RILReceiver" ); |
3 | mReceiverThread.start(); |
其中的类型
- mReceiver: RILReceiver
- mReceiverThread: Thread
RILReceiver实现了Runnable
![Android中SMS的接收处理](https://i-blog.csdnimg.cn/blog_migrate/f6b92e214be867a2d1004ceb7e13e4e7.gif)
关注RILReceiver线程的实现[在RILReceiver::run()中]
10 | l = newLocalSocketAddress(SOCKET_NAME_RIL, |
11 | LocalSocketAddress.Namespace.RESERVED); |
13 | } catch (IOException ex){ |
22 | InputStreamis = mSocket.getInputStream(); |
27 | length = readRilMessage(is, buffer); |
34 | p.unmarshall(buffer, 0 , length); |
40 | } catch (java.io.IOException ex) { |
42 | } catch (Throwable tr) { |
47 | }} catch (Throwable tr) { |
48 | Log.e(LOG_TAG, "Uncaught exception" , tr); |
RILReceiver线程不停的监听本地Socket,读到数据之后在processResponse()[Line#37]中处理。
01 | private void processResponse (Parcel p) { |
06 | if (type == RESPONSE_UNSOLICITED) { |
07 | processUnsolicited (p); |
08 | } else if (type == RESPONSE_SOLICITED) { |
12 | releaseWakeLockIfDone(); |
如果类型属于Unsolicited消息,则在processUnsolicited()中处理。收到的短信是属于Unsolicited信息,看它的实现。
processUnsolicited()中很长的switch… case语句中对收到短信的处理在case RIL_UNSOL_RESPONSE_NEW_SMS:
3 | sms = SmsMessage.newFromCMT(a); |
4 | if (mSMSRegistrant != null ) { |
5 | 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的接收处理](https://i-blog.csdnimg.cn/blog_migrate/93539010df54715c770ade1e9d21d8b4.gif)
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的处理:
03 | ar = (AsyncResult) msg.obj; |
05 | if (ar.exception != null ) { |
06 | Log.e(TAG, "Exception processing incoming SMS. Exception:" +ar.exception); |
10 | sms = (SmsMessage) ar.result; |
12 | int result = dispatchMessage(sms.mWrappedSmsMessage); |
13 | if (result != Activity.RESULT_OK) { |
16 | boolean handled = (result== Intents.RESULT_SMS_HANDLED); |
17 | notifyAndAcknowledgeLastIncomingSms(handled, result, null ); |
19 | } catch (RuntimeException ex) { |
20 | Log.e(TAG, "Exception dispatching message" , ex); |
21 | 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:”指定端口。
对长短信,调用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");