android sms接收流程
2013-12-09 15:16
176 查看
在解析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 plaincopy
mReceiver = newRILReceiver();
mReceiverThread =new Thread(mReceiver, "RILReceiver");
mReceiverThread.start();
其中的类型
mReceiver: RILReceiver
mReceiverThread: Thread
RILReceiver实现了Runnable
关注RILReceiver线程的实现[在RILReceiver::run()中]
[java]
view plaincopy
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]
view plaincopy
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]
view plaincopy
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]
view plaincopy
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");
Android中,RIL用RILReciever接收SMS pdu,并根据不同的信息类型用相应函数来处理。因手机制式的差异,用GsmSmsDispatcher或CdmaSmsDispatcher来做各自的消息处理并分发。最后的分发是通过发送相应的Broadcast,所以,对感兴趣的消息处理,可以注册Receiver来监听相应的Broadcast,实现自己的SMS/MMS/Wap push,以及其他类型消息的接收处理。
RIL构造函数中,Receiver的初始化[在文件RIL.java中]
[java]
view plaincopy
mReceiver = newRILReceiver();
mReceiverThread =new Thread(mReceiver, "RILReceiver");
mReceiverThread.start();
其中的类型
mReceiver: RILReceiver
mReceiverThread: Thread
RILReceiver实现了Runnable
关注RILReceiver线程的实现[在RILReceiver::run()中]
[java]
view plaincopy
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]
view plaincopy
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]
view plaincopy
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]
view plaincopy
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");
相关文章推荐
- 关于android 4.4短信(sms)接收流程-状态机篇
- android中Mms学习笔记——短信(sms)接收流程(三)
- [Android][KK][SMS]Frameworks学习——接收短信流程分析
- android MMS/SMS 收发流程分析(接收发送)
- 【SMS】android 短信接收流程分析——-拦截短信示例代码
- Android Mms专题之:接收信息流程
- Android Mms之短信接收流程--从Framework到App
- android安全问题(七) 抢先接收广播 - 内因篇之广播发送流程
- Android中广播注册与接收流程
- 真机无法接收到android.provider.Telephony.SMS_RECEIVED的问题
- Android Mms之短信接收流程--从Framework到App
- [Android][KK][SMS]Frameworks学习——发送短信流程分析
- Android中SMS的接收处理
- Android中SMS的接收处理
- android中Mms学习笔记——短信(sms)发送流程(二)
- Android Mms之:接收信息流程(图文详解)
- Android Mms专题之:接收信息流程
- Android Mms之:接收信息流程(图文详解)
- android安全问题(七) 抢先接收广播 - 内因篇之广播发送流程
- android SMS 接收到短信后自动回复