频道栏目
首页 > 程序开发 > 移动开发 > Android > 正文
android 短信接收流程分析——为更好的拦截短信做准备
2011-11-29 19:02:30      个评论      
收藏   我要投稿

 

观察360的短信拦截和QQ管家的短信拦截,发现先安装的就能先拦截到的短信,然后中断广播,之后谁都不能获取到短信。从这里可以推出系统大概有一个广播表,同等级的按安装先后顺序排放。目前的方法是在应用层调用framework API进行控制的。

 

为了能更好的了解android接收短信的流程,我进行了更深入的分析,从RIL的通信架构来分析当接收到短信的整个流程。从frameword里的RIL.java

clip_image002

文件可以看出发送短信和接收短信是通过Receiver和Sender架构,发送短信主要通过Sender框架,主要如下(图是从网上窃滴~):

image

上层函数调用Command Interface将请求消息发送到sender架构,由该架构将请求发送到RILD的架构。

目前主要分析接收短信走过的那些渠道,因此发送短信只是略微的说明一下。

接收短信流程如下(从发送消息到接收消息的处理流程)(图是从网上剽滴~):

clip_image002[6]

从上图右边那块(结合代码)可以看出短信接收是从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类里

clip_image004

该类做了一件重要的事:给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服务类来处理短信并保存短信。

 

作者 没有代码

点击复制链接 与好友分享!回本站首页
相关TAG标签 短信 流程
上一篇:Android自定义View研究(五)--View的大小
下一篇:在Android应用开发中遇到问题怎么办?
相关文章
图文推荐
点击排行

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站