[转载]android 短信接收流程分析——为更好的拦截短信做准备 – 没有代码 – 博客园.
观察360的短信拦截和QQ管家的短信拦截,发现先安装的就能先拦截到的短信,然后中断广播,之后谁都不能获取到短信。从这里可以推出系统大概有一个广播表,同等级的按安装先后顺序排放。目前的方法是在应用层调用framework API进行控制的。
为了能更好的了解Android接收短信的流程,我进行了更深入的分析,从RIL的通信架构来分析当接收到短信的整个流程。从frameword里的RIL.java
文件可以看出发送短信和接收短信是通过Receiver和Sender架构,发送短信主要通过Sender框架,主要如下(图是从网上窃滴~):
上层函数调用Command Interface将请求消息发送到sender架构,由该架构将请求发送到RILD的架构。
目前主要分析接收短信走过的那些渠道,因此发送短信只是略微的说明一下。
接收短信流程如下(从发送消息到接收消息的处理流程)(图是从网上剽滴~):
从 上图右边那块(结合代码)可以看出短信接收是从ril.cpp文件通过socket与RIL.java的socket交流,当ril.cpp收到短信后处 理完成后会通过socket发送字节流给上层的RIL.java,而在RIL.java中有Receiver架构(该架构主要是一条线程)在不断监听,
Receiver架构代码:
class RILReceiver implements Runnable {
byte[] buffer;
RILReceiver() {
buffer = new byte[RIL_MAX_COMMAND_BYTES];
}
public void
run() {
int retryCount = 0;
try {
for (;;) {
LocalSocket s = null;
LocalSocketAddress l;
try {
s = new LocalSocket();
l = new LocalSocketAddress(SOCKET_NAME_RIL,
LocalSocketAddress.Namespace.RESERVED);
s.connect(l);
} catch (IOException ex) {
try {
if (s != null) {
s.close();
}
} catch (IOException ex2) {
// ignore failure to close after failure to connect
}
// don’t print an error message after the the first time
// or after the 8th time
if (retryCount == 8) {
Log.e(LOG_TAG,
“Couldn’t find ‘” + SOCKET_NAME_RIL
+ “‘ socket after ” + retryCount
+ ” times, continuing to retry silently”);
} else if (retryCount > 0 && retryCount < 8) {
Log.i(LOG_TAG,
“Couldn’t find ‘” + SOCKET_NAME_RIL
+ “‘ socket; retrying after timeout”);
}
try {
Thread.sleep(SOCKET_OPEN_RETRY_MILLIS);
} catch (InterruptedException er) {
}
retryCount++;
continue;
}
retryCount = 0;
mSocket = s;
Log.i(LOG_TAG, “Connected to ‘” + SOCKET_NAME_RIL
+ “‘ socket”);
int length = 0;
try {
InputStream is = 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);
// Log.v(LOG_TAG, “Read packet: ” + length +
// ” bytes”);
processResponse(p);
p.recycle();
}
} catch (java.io.IOException ex) {
Log.i(LOG_TAG, “‘” + SOCKET_NAME_RIL
+ “‘ socket closed”,
ex);
} catch (Throwable tr) {
Log.e(LOG_TAG, “Uncaught exception read length=”
+ length +
“Exception:” + tr.toString());
}
Log.i(LOG_TAG, “Disconnected from ‘” + SOCKET_NAME_RIL
+ “‘ socket”);
setRadioState(RadioState.RADIO_UNAVAILABLE);
try {
mSocket.close();
} catch (IOException ex) {
}
mSocket = null;
RILRequest.resetSerial();
// Clear request list on close
synchronized (mRequestsList) {
for (int i = 0, sz = mRequestsList.size(); i < sz; i++) {
RILRequest rr = mRequestsList.get(i);
rr.onError(RADIO_NOT_AVAILABLE, null);
rr.release();
}
mRequestsList.clear();
}
}
} catch (Throwable tr) {
Log.e(LOG_TAG, “Uncaught exception”, tr);
}
}
}
因 此从代码可以看出获取到短信消息后经过一系列地分析然后提交给processResponse(p); 方法处理,处理过程中会有两种response,一种是主动上报,比如网络状态,短信,来电等都不需要经过请求,用unsolicited词语专门描述, 另一种才是真正意义上的response,也就是命令的响应用solicited描述。那接收短信就是属于unsolicited,跳到 processUnsolicited (Parcel p)方法,查看该方法可得出会继续触发以下方法mSMSRegistrant.notifyRegistrant(new AsyncResult(null, sms, null)); 追溯该方法对象的创建,最后发现该方法设置handler的源头是在:SMSDispatcher类里
该 类做了一件重要的事:给Command Interface设置handler的处理方法,就是当接收到短信后触发mSMSRegistrant.notifyRegistrant(new AsyncResult(null, sms, null));方法,然后回调调用之前传入的handler,接着在handler里面处理短信消息。
mCm.setOnNewSMS(this, EVENT_NEW_SMS, null);
mCm.setOnSmsStatus(this, EVENT_NEW_SMS_STATUS_REPORT, null);
mCm.setOnIccSmsFull(this, EVENT_ICC_FULL, null);
mCm.registerForOn(this, EVENT_RADIO_ON, null);
handler处理接收到的短信消息:
@Override
public void handleMessage(Message msg) {
AsyncResult ar;
switch (msg.what) {
case EVENT_NEW_SMS:
// A new SMS has been received by the device
if (Config.LOGD) {
Log.d(TAG, “New SMS Message Received”);
}
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 that message was broadcast for app(s) to
// handle.
// Any other result, we should 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);
}
break;
}
}
int result = dispatchMessage(sms.mWrappedSmsMessage); 该段会通过子类(GsmSMSDispatcher)的dispatchMessage方法处理。经一系列的判断处理最后普通短信将交给 dispatchPdus(pdus);这个方法处理。
protected void dispatchPdus(byte[][] pdus) {
Intent intent = new Intent(Intents.SMS_RECEIVED_ACTION);
intent.putExtra(“pdus”, pdus);
dispatch(intent, “Android.permission.RECEIVE_SMS”);
}
void dispatch(Intent intent, String permission) {
// Hold a wake lock for WAKE_LOCK_TIMEOUT seconds, enough to give any
// receivers time to take their own wake locks.
mWakeLock.acquire(WAKE_LOCK_TIMEOUT);
mContext.sendOrderedBroadcast(intent, permission, mResultReceiver,
this, Activity.RESULT_OK, null, null);
}
最 后,我们可以看出这个方法将短信通过顺序广播播放出去(action是SMS_RECEIVED_ACTION),无论广播是否被中断最后都会调用 mResultReceiver,这里会将已读或未读的状态告诉给对方。如果短信广播中间没有受到終止,那么接下来的流程 是:PrivilegedSmsReceiver类接收到android.provider.Telephony.SMS_RECEIVED的请求然后调 用 intent.setClass(context, SmsReceiverService.class); 启动SmsReceiverService服务类来处理短信并保存短信。
参考文章:
http://newfaction.net/2011/03/15/android-2-2-ril-java-part-of-the-code-profile.html
http://blog.csdn.net/maxleng/article/details/5593759
http://www.360doc.com/content/10/0625/11/496343_35127382.shtml