您的位置:首页 > 移动开发 > Android开发

深度分析:Android4.3下MMS发送到附件为音频文件(音频为系统内置音频)的彩信给自己,添加音频-发送彩信-接收彩信-下载音频附件-预览-播放(三,接收彩信<1,接收短信>)

2014-06-11 09:41 891 查看
在Android中,彩信的接收分为两部分。彩信通知通过短信的方式接收。彩信数据的下载在应用层中处理。

接收短信(!前提是发送彩信而不是短信):

分析代码之前,首先分享一张在网络上很流行的顺序图。





调用 Ril.java类中内部类RILReceiver的run()方法,代码如下《TAG 1-1》:

 public void

        run() {

            int retryCount = 0;

            String rilSocket = "rild";

            try {for (;;) {

                LocalSocket s = null;

                LocalSocketAddress l;

                if (mInstanceId == null || mInstanceId == 0 ) {

                    rilSocket = SOCKET_NAME_RIL[0];

                } else {

                    rilSocket = SOCKET_NAME_RIL[mInstanceId];

                }

                try {

                    s = new LocalSocket();

                    l = new LocalSocketAddress(rilSocket,

                            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) {

                        Rlog.e (RILJ_LOG_TAG,

                            "Couldn't find '" + rilSocket

                            + "' socket after " + retryCount

                            + " times, continuing to retry silently");

                    } else if (retryCount > 0 && retryCount < 8) {

                        Rlog.i (RILJ_LOG_TAG,

                            "Couldn't find '" + rilSocket

                            + "' socket; retrying after timeout");

                    }

                    try {

                        Thread.sleep(SOCKET_OPEN_RETRY_MILLIS);

                    } catch (InterruptedException er) {

                    }

                    retryCount++;

                    continue;

                }

                retryCount = 0;

                mSocket = s;

                Rlog.i(RILJ_LOG_TAG, "Connected to '" + rilSocket + "' 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);

                        //Rlog.v(RILJ_LOG_TAG, "Read packet: " + length + " bytes");

                        processResponse(p);

                        p.recycle();

                    }

                } catch (java.io.IOException ex) {

                    Rlog.i(RILJ_LOG_TAG, "'" + rilSocket + "' socket closed",

                          ex);

                } catch (Throwable tr) {

                    Rlog.e(RILJ_LOG_TAG, "Uncaught exception read length=" + length +

                        "Exception:" + tr.toString());

                }

                Rlog.i(RILJ_LOG_TAG, "Disconnected from '" + rilSocket

                      + "' socket");

                setRadioState (RadioState.RADIO_UNAVAILABLE);

                try {

                    mSocket.close();

                } catch (IOException ex) {

                }

                mSocket = null;

                RILRequest.resetSerial();

                // Clear request list on close

                clearRequestList(RADIO_NOT_AVAILABLE, false);

            }} catch (Throwable tr) {

                Rlog.e(RILJ_LOG_TAG,"Uncaught exception", tr);

            }

            /* We're disconnected so we don't know the ril version */

            notifyRegistrantsRilConnectionChanged(-1);

        }

从上述代码《TAG 1-1》中,RILReceiver接收到短信后,会转到processResponse()--> processUnsolicited()进行处理.其事件类型为RIL_UNSOL_RESPONSE_NEW_SMS/RIL_UNSOL_RESPONSE_CDMA_NEW_SMS ,先调用responseString()从Parcel中获取数据,再使用newFromCMT()方法获取SmsMessage对象《TAG1-2》;

    private void

    processResponse (Parcel p) {

        int type;

        type = p.readInt();

        if (type == RESPONSE_UNSOLICITED) {

            processUnsolicited (p);

        } else if (type == RESPONSE_SOLICITED) {

            processSolicited (p);

        }

        releaseWakeLockIfDone();

    }

private void
    processUnsolicited (Parcel p) {
        int response;

        Object ret;

        response = p.readInt();

        try {switch(response) {

/*

 cat libs/telephony/ril_unsol_commands.h \

 | egrep "^ *{RIL_" \

 | sed -re 's/\{([^,]+),[^,]+,([^}]+).+/case \1: \2(rr, p); break;/'

*/

            case RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED: ret =  responseVoid(p); break;

            case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED: ret =  responseVoid(p); break;

            case RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED: ret =  responseVoid(p); break;
            case RIL_UNSOL_RESPONSE_NEW_SMS: ret =  responseString(p); break;

            case RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT: ret =  responseString(p); break;

            case RIL_UNSOL_RESPONSE_NEW_SMS_ON_SIM: ret =  responseInts(p); break;

            case RIL_UNSOL_ON_USSD: ret =  responseStrings(p); break;

            case RIL_UNSOL_NITZ_TIME_RECEIVED: ret =  responseString(p); break;

            case RIL_UNSOL_SIGNAL_STRENGTH: ret = responseSignalStrength(p); break;

            case RIL_UNSOL_DATA_CALL_LIST_CHANGED: ret = responseDataCallList(p);break;

            case RIL_UNSOL_SUPP_SVC_NOTIFICATION: ret = responseSuppServiceNotification(p); break;

            case RIL_UNSOL_STK_SESSION_END: ret = responseVoid(p); break;

            case RIL_UNSOL_STK_PROACTIVE_COMMAND: ret = responseString(p); break;

            case RIL_UNSOL_STK_EVENT_NOTIFY: ret = responseString(p); break;

            case RIL_UNSOL_STK_CALL_SETUP: ret = responseInts(p); break;

            case RIL_UNSOL_SIM_SMS_STORAGE_FULL: ret =  responseVoid(p); break;

            case RIL_UNSOL_SIM_REFRESH: ret =  responseSimRefresh(p); break;

            case RIL_UNSOL_CALL_RING: ret =  responseCallRing(p); break;

            case RIL_UNSOL_RESTRICTED_STATE_CHANGED: ret = responseInts(p); break;

            case RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED:  ret =  responseVoid(p); break;

            case RIL_UNSOL_RESPONSE_CDMA_NEW_SMS:  ret =  responseCdmaSms(p); break;

            case RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS:  ret =  responseRaw(p); break;

            case RIL_UNSOL_CDMA_RUIM_SMS_STORAGE_FULL:  ret =  responseVoid(p); break;

            case RIL_UNSOL_ENTER_EMERGENCY_CALLBACK_MODE: ret = responseVoid(p); break;

            case RIL_UNSOL_CDMA_CALL_WAITING: ret = responseCdmaCallWaiting(p); break;

            case RIL_UNSOL_CDMA_OTA_PROVISION_STATUS: ret = responseInts(p); break;

            case RIL_UNSOL_CDMA_INFO_REC: ret = responseCdmaInformationRecord(p); break;

            case RIL_UNSOL_OEM_HOOK_RAW: ret = responseRaw(p); break;

            case RIL_UNSOL_RINGBACK_TONE: ret = responseInts(p); break;

            case RIL_UNSOL_RESEND_INCALL_MUTE: ret = responseVoid(p); break;

            case RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED: ret = responseInts(p); break;

            case RIL_UNSOl_CDMA_PRL_CHANGED: ret = responseInts(p); break;

            case RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE: ret = responseVoid(p); break;

            case RIL_UNSOL_RIL_CONNECTED: ret = responseInts(p); break;

            case RIL_UNSOL_VOICE_RADIO_TECH_CHANGED: ret =  responseInts(p); break;

            case RIL_UNSOL_CELL_INFO_LIST: ret = responseCellInfoList(p); break;

            case RIL_UNSOL_RESPONSE_IMS_NETWORK_STATE_CHANGED: ret =  responseVoid(p); break;

            case RIL_UNSOL_UICC_SUBSCRIPTION_STATUS_CHANGED: ret =  responseInts(p); break;

            case RIL_UNSOL_ON_SS: ret =  responseSsData(p); break;

            case RIL_UNSOL_STK_CC_ALPHA_NOTIFY: ret =  responseString(p); break;

        //dewen.feng@20140426 add     hongxing add

            case RIL_UNSOL_FACTORY_AT_TEST: ret = responseRaw(p); break;

            default:

                throw new RuntimeException("Unrecognized unsol response: " + response);

            //break; (implied)

        }} catch (Throwable tr) {

            Rlog.e(RILJ_LOG_TAG, "Exception processing unsol response: " + response +

                "Exception:" + tr.toString());

            return;

        }

        switch(response) {

            case RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED:

                /* has bonus radio state int */

                RadioState newState = getRadioStateFromInt(p.readInt());

                if (RILJ_LOGD) unsljLogMore(response, newState.toString());

                switchToRadioState(newState);

            break;

            case RIL_UNSOL_RESPONSE_IMS_NETWORK_STATE_CHANGED:

                if (RILJ_LOGD) unsljLog(response);

                mImsNetworkStateChangedRegistrants

                    .notifyRegistrants(new AsyncResult(null, null, null));

            break;

            case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED:

                if (RILJ_LOGD) unsljLog(response);

                mCallStateRegistrants

                    .notifyRegistrants(new AsyncResult(null, null, null));

            break;

            case RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED:

                if (RILJ_LOGD) unsljLog(response);

                mVoiceNetworkStateRegistrants

                    .notifyRegistrants(new AsyncResult(null, null, null));

            break;
            case RIL_UNSOL_RESPONSE_NEW_SMS: {

                if (RILJ_LOGD) unsljLog(response);

                // FIXME this should move up a layer

                String a[] = new String[2];

                a[1] = (String)ret;

                SmsMessage sms;

                sms = SmsMessage.newFromCMT(a);

                if (mGsmSmsRegistrant != null) {

                    mGsmSmsRegistrant

                        .notifyRegistrant(new AsyncResult(null, sms, null));

                }

            break;

            }


            case RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT:

                if (RILJ_LOGD) unsljLogRet(response, ret);

                if (mSmsStatusRegistrant != null) {

                    mSmsStatusRegistrant.notifyRegistrant(

                            new AsyncResult(null, ret, null));

                }

            break;

            case RIL_UNSOL_RESPONSE_NEW_SMS_ON_SIM:

                if (RILJ_LOGD) unsljLogRet(response, ret);

                int[] smsIndex = (int[])ret;

                if(smsIndex.length == 1) {

                    if (mSmsOnSimRegistrant != null) {

                        mSmsOnSimRegistrant.

                                notifyRegistrant(new AsyncResult(null, smsIndex, null));

                    }

                } else {

                    if (RILJ_LOGD) riljLog(" NEW_SMS_ON_SIM ERROR with wrong length "

                            + smsIndex.length);

                }

            break;

            case RIL_UNSOL_ON_USSD:

                String[] resp = (String[])ret;

                if (resp.length < 2) {

                    resp = new String[2];

                    resp[0] = ((String[])ret)[0];

                    resp[1] = null;

                }

                if (RILJ_LOGD) unsljLogMore(response, resp[0]);

                if (mUSSDRegistrant != null) {

                    mUSSDRegistrant.notifyRegistrant(

                        new AsyncResult (null, resp, null));

                }

            break;

            case RIL_UNSOL_NITZ_TIME_RECEIVED:

                if (RILJ_LOGD) unsljLogRet(response, ret);

                // has bonus long containing milliseconds since boot that the NITZ

                // time was received

                long nitzReceiveTime = p.readLong();

                Object[] result = new Object[2];

                result[0] = ret;

                result[1] = Long.valueOf(nitzReceiveTime);

                boolean ignoreNitz = SystemProperties.getBoolean(

                        TelephonyProperties.PROPERTY_IGNORE_NITZ, false);

                if (ignoreNitz) {

                    if (RILJ_LOGD) riljLog("ignoring UNSOL_NITZ_TIME_RECEIVED");

                } else {

                    if (mNITZTimeRegistrant != null) {

                        mNITZTimeRegistrant

                            .notifyRegistrant(new AsyncResult (null, result, null));

                    } else {

                        // in case NITZ time registrant isnt registered yet

                        mLastNITZTimeInfo = result;

                    }

                }

            break;

            case RIL_UNSOL_SIGNAL_STRENGTH:

                // Note this is set to "verbose" because it happens

                // frequently

                if (RILJ_LOGV) unsljLogvRet(response, ret);

                if (mSignalStrengthRegistrant != null) {

                    mSignalStrengthRegistrant.notifyRegistrant(

                                        new AsyncResult (null, ret, null));

                }

            break;

            case RIL_UNSOL_DATA_CALL_LIST_CHANGED:

                if (RILJ_LOGD) unsljLogRet(response, ret);

                mDataNetworkStateRegistrants.notifyRegistrants(new AsyncResult(null, ret, null));

            break;

            case RIL_UNSOL_SUPP_SVC_NOTIFICATION:

                if (RILJ_LOGD) unsljLogRet(response, ret);

                if (mSsnRegistrant != null) {

                    mSsnRegistrant.notifyRegistrant(

                                        new AsyncResult (null, ret, null));

                }

                break;

            case RIL_UNSOL_STK_SESSION_END:

                if (RILJ_LOGD) unsljLog(response);

                if (mCatSessionEndRegistrant != null) {

                    mCatSessionEndRegistrant.notifyRegistrant(

                                        new AsyncResult (null, ret, null));

                }

                break;

            case RIL_UNSOL_STK_PROACTIVE_COMMAND:

                if (RILJ_LOGD) unsljLogRet(response, ret);

                if (mCatProCmdRegistrant != null) {

                    mCatProCmdRegistrant.notifyRegistrant(

                                        new AsyncResult (null, ret, null));

                }

                break;

            case RIL_UNSOL_STK_EVENT_NOTIFY:

                if (RILJ_LOGD) unsljLogRet(response, ret);

                if (mCatEventRegistrant != null) {

                    mCatEventRegistrant.notifyRegistrant(

                                        new AsyncResult (null, ret, null));

                }

                break;

            case RIL_UNSOL_STK_CALL_SETUP:

                if (RILJ_LOGD) unsljLogRet(response, ret);

                if (mCatCallSetUpRegistrant != null) {

                    mCatCallSetUpRegistrant.notifyRegistrant(

                                        new AsyncResult (null, ret, null));

                }

                break;

            case RIL_UNSOL_SIM_SMS_STORAGE_FULL:

                if (RILJ_LOGD) unsljLog(response);

                if (mIccSmsFullRegistrant != null) {

                    mIccSmsFullRegistrant.notifyRegistrant();

                }

                break;

            case RIL_UNSOL_SIM_REFRESH:

                if (RILJ_LOGD) unsljLogRet(response, ret);

                if (mIccRefreshRegistrants != null) {

                    mIccRefreshRegistrants.notifyRegistrants(

                            new AsyncResult (null, ret, null));

                }

                break;

            case RIL_UNSOL_CALL_RING:

                if (RILJ_LOGD) unsljLogRet(response, ret);

                if (mRingRegistrant != null) {

                    mRingRegistrant.notifyRegistrant(

                            new AsyncResult (null, ret, null));

                }

                break;

            case RIL_UNSOL_RESTRICTED_STATE_CHANGED:

                if (RILJ_LOGD) unsljLogvRet(response, ret);

                if (mRestrictedStateRegistrant != null) {

                    mRestrictedStateRegistrant.notifyRegistrant(

                                        new AsyncResult (null, ret, null));

                }

                break;

            case RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED:

                if (RILJ_LOGD) unsljLog(response);

                if (mIccStatusChangedRegistrants != null) {

                    mIccStatusChangedRegistrants.notifyRegistrants();

                }

                break;

            case RIL_UNSOL_RESPONSE_CDMA_NEW_SMS:

                if (RILJ_LOGD) unsljLog(response);

                SmsMessage sms = (SmsMessage) ret;

                if (mCdmaSmsRegistrant != null) {

                    mCdmaSmsRegistrant

                        .notifyRegistrant(new AsyncResult(null, sms, null));

                }

                break;

            case RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS:

                if (RILJ_LOGD) unsljLog(response);

                if (mGsmBroadcastSmsRegistrant != null) {

                    mGsmBroadcastSmsRegistrant

                        .notifyRegistrant(new AsyncResult(null, ret, null));

                }

                break;

            case RIL_UNSOL_CDMA_RUIM_SMS_STORAGE_FULL:

                if (RILJ_LOGD) unsljLog(response);

                if (mIccSmsFullRegistrant != null) {

                    mIccSmsFullRegistrant.notifyRegistrant();

                }

                break;

            case RIL_UNSOL_ENTER_EMERGENCY_CALLBACK_MODE:

                if (RILJ_LOGD) unsljLog(response);

                if (mEmergencyCallbackModeRegistrant != null) {

                    mEmergencyCallbackModeRegistrant.notifyRegistrant();

                }

                break;

            case RIL_UNSOL_CDMA_CALL_WAITING:

                if (RILJ_LOGD) unsljLogRet(response, ret);

                if (mCallWaitingInfoRegistrants != null) {

                    mCallWaitingInfoRegistrants.notifyRegistrants(

                                        new AsyncResult (null, ret, null));

                }

                break;

            case RIL_UNSOL_CDMA_OTA_PROVISION_STATUS:

                if (RILJ_LOGD) unsljLogRet(response, ret);

                if (mOtaProvisionRegistrants != null) {

                    mOtaProvisionRegistrants.notifyRegistrants(

                                        new AsyncResult (null, ret, null));

                }

                break;

            case RIL_UNSOL_CDMA_INFO_REC:

                ArrayList<CdmaInformationRecords> listInfoRecs;

                try {

                    listInfoRecs = (ArrayList<CdmaInformationRecords>)ret;

                } catch (ClassCastException e) {

                    Rlog.e(RILJ_LOG_TAG, "Unexpected exception casting to listInfoRecs", e);

                    break;

                }

                for (CdmaInformationRecords rec : listInfoRecs) {

                    if (RILJ_LOGD) unsljLogRet(response, rec);

                    notifyRegistrantsCdmaInfoRec(rec);

                }

                break;

            case RIL_UNSOL_OEM_HOOK_RAW:

                if (RILJ_LOGD) unsljLogvRet(response, IccUtils.bytesToHexString((byte[]) ret));

                ByteBuffer oemHookResponse = ByteBuffer.wrap((byte[]) ret);

                oemHookResponse.order(ByteOrder.nativeOrder());

                if (isQcUnsolOemHookResp(oemHookResponse)) {

                    Rlog.d(RILJ_LOG_TAG, "OEM ID check Passed");

                    processUnsolOemhookResponse(oemHookResponse);

                } else if (mUnsolOemHookRawRegistrant != null) {

                    Rlog.d(RILJ_LOG_TAG, "External OEM message, to be notified");

                    mUnsolOemHookRawRegistrant.notifyRegistrant(new AsyncResult(null, ret, null));

                }

                break;

                

            //dewen.feng @20140426 add hongxing add

            case RIL_UNSOL_FACTORY_AT_TEST:

        Rlog.d(RILJ_LOG_TAG, "##########RIL_UNSOL_FACTORY_AT_TEST################");

                if (RILJ_LOGD) unsljLogvRet(response, IccUtils.bytesToHexString((byte[])ret));

                ByteBuffer factoryAtResponse = ByteBuffer.wrap((byte[])ret);

                factoryAtResponse.order(ByteOrder.nativeOrder());

                processFactoryAtResponse(factoryAtResponse);

                break;

            //end

            

            case RIL_UNSOL_RINGBACK_TONE:

                if (RILJ_LOGD) unsljLogvRet(response, ret);

                if (mRingbackToneRegistrants != null) {

                    boolean playtone = (((int[])ret)[0] == 1);

                    mRingbackToneRegistrants.notifyRegistrants(

                                        new AsyncResult (null, playtone, null));

                }

                break;

            case RIL_UNSOL_RESEND_INCALL_MUTE:

                if (RILJ_LOGD) unsljLogRet(response, ret);

                if (mResendIncallMuteRegistrants != null) {

                    mResendIncallMuteRegistrants.notifyRegistrants(

                                        new AsyncResult (null, ret, null));

                }

                break;

            case RIL_UNSOL_VOICE_RADIO_TECH_CHANGED:

                if (RILJ_LOGD) unsljLogRet(response, ret);

                if (mVoiceRadioTechChangedRegistrants != null) {

                    mVoiceRadioTechChangedRegistrants.notifyRegistrants(

                            new AsyncResult(null, ret, null));

                }

                break;

            case RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED:

                if (RILJ_LOGD) unsljLogRet(response, ret);

                if (mCdmaSubscriptionChangedRegistrants != null) {

                    mCdmaSubscriptionChangedRegistrants.notifyRegistrants(

                                        new AsyncResult (null, ret, null));

                }

                break;

            case RIL_UNSOL_ON_SS:

                if (RILJ_LOGD) unsljLogRet(response, ret);

                if (mSsRegistrant != null) {

                    mSsRegistrant.notifyRegistrant(

                                        new AsyncResult (null, ret, null));

                }

                break;

            case RIL_UNSOL_STK_CC_ALPHA_NOTIFY:

                if (RILJ_LOGD) unsljLogRet(response, ret);

                if (mCatCcAlphaRegistrant != null) {

                    mCatCcAlphaRegistrant.notifyRegistrant(

                                        new AsyncResult (null, ret, null));

                }

                break;

            case RIL_UNSOl_CDMA_PRL_CHANGED:

                if (RILJ_LOGD) unsljLogRet(response, ret);

                if (mCdmaPrlChangedRegistrants != null) {

                    mCdmaPrlChangedRegistrants.notifyRegistrants(

                                        new AsyncResult (null, ret, null));

                }

                break;

            case RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE:

                if (RILJ_LOGD) unsljLogRet(response, ret);

                if (mExitEmergencyCallbackModeRegistrants != null) {

                    mExitEmergencyCallbackModeRegistrants.notifyRegistrants(

                                        new AsyncResult (null, null, null));

                }

                break;

            case RIL_UNSOL_RIL_CONNECTED: {

                if (RILJ_LOGD) unsljLogRet(response, ret);

                // Initial conditions

                setRadioPower(false, null);

                setPreferredNetworkType(mPreferredNetworkType, null);

                setCdmaSubscriptionSource(mCdmaSubscription, null);

                setCellInfoListRate(Integer.MAX_VALUE, null);

                notifyRegistrantsRilConnectionChanged(((int[])ret)[0]);

                break;

            }

            case RIL_UNSOL_CELL_INFO_LIST: {

                if (RILJ_LOGD) unsljLogRet(response, ret);

                if (mRilCellInfoListRegistrants != null) {

                    mRilCellInfoListRegistrants.notifyRegistrants(

                                        new AsyncResult (null, ret, null));

                }

                break;

            }

            case RIL_UNSOL_UICC_SUBSCRIPTION_STATUS_CHANGED: {

                if (RILJ_LOGD) unsljLogRet(response, ret);

                if (mSubscriptionStatusRegistrants != null) {

                    mSubscriptionStatusRegistrants.notifyRegistrants(

                                        new AsyncResult (null, ret, null));

                }

                break;

            }

        }

    }

上述代码《TAG1-2》中,调用Registrant.java类中的mSMSRegistrant的notifyRegistrant()方法设置消息类型(what属性为EVENT_NEW_SMS),internalNotifyRegistrant()-->h.sendMessage(msg),并转到SMSDispatcher进行处理。代码如下:

    internalNotifyRegistrant (Object result, Throwable exception)

    {

        Handler h = getHandler();

        if (h == null) {

            clear();

        } else {

            Message msg = Message.obtain();

            msg.what = what;

            

            msg.obj = new AsyncResult(userObj, result, exception);

            

            h.sendMessage(msg);

        }
    }                 

调用SMSDispatcher类中的<! GSM><EVENT_NEW_SMS>handlerMessage()  -->得到AsyncResult的对象ar

 public void handleMessage(Message msg) {

        AsyncResult ar;

        switch (msg.what) {

        case EVENT_NEW_SMS:

            // A new SMS has been received by the device

            if (DBG) Rlog.d(TAG, "New SMS Message Received");

            SmsMessage sms;

            ar = (AsyncResult) msg.obj;

            if (ar.exception != null) {

                Rlog.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) {

                Rlog.e(TAG, "Exception dispatching message", ex);

                notifyAndAcknowledgeLastIncomingSms(false, Intents.RESULT_SMS_GENERIC_ERROR, null);

            }

            break;

调用GSMSmsDispatcher.java类中的dispatchMessage() 方法再调用SMSDispatcher.javadispatchNormalMessage()方法,,  首先获取<SmsHeader smsHeader = sms.getUserDataHeader();>。如果 if ((smsHeader == null) || (smsHeader.concatRef == null))成立,而且 if (smsHeader != null && smsHeader.portAddrs
!= null) 成立,则调用<WapPushOverSms.java> dispatchWapPdu(),再调用<SMSDispatcher.java>  mSmsDispatcher.dispatch(intent, permission, appOp)<其中permission为android.permission.RECEIVE_MMS> ------>sendOrderedBroadcast();这里的Action为Intents.WAP_PUSH_RECEIVED_ACTION。接下来进入彩信的接收,由PushReceiver开始。


public int dispatchWapPdu(byte[] pdu, String address) {


        if (DBG) Rlog.d(LOG_TAG, "Rx: " + IccUtils.bytesToHexString(pdu));

        int index = 0;

        int transactionId = pdu[index++] & 0xFF;

        int pduType = pdu[index++] & 0xFF;

        int headerLength = 0;

        if ((pduType != WspTypeDecoder.PDU_TYPE_PUSH) &&

                (pduType != WspTypeDecoder.PDU_TYPE_CONFIRMED_PUSH)) {

            if (DBG) Rlog.w(LOG_TAG, "Received non-PUSH WAP PDU. Type = " + pduType);

            return Intents.RESULT_SMS_HANDLED;

        }

        pduDecoder = new WspTypeDecoder(pdu);

        /**

         * Parse HeaderLen(unsigned integer).

         * From wap-230-wsp-20010705-a section 8.1.2

         * The maximum size of a uintvar is 32 bits.

         * So it will be encoded in no more than 5 octets.

         */

        if (pduDecoder.decodeUintvarInteger(index) == false) {

            if (DBG) Rlog.w(LOG_TAG, "Received PDU. Header Length error.");

            return Intents.RESULT_SMS_GENERIC_ERROR;

        }

        headerLength = (int)pduDecoder.getValue32();

        index += pduDecoder.getDecodedDataLength();

        int headerStartIndex = index;

        /**

         * Parse Content-Type.

         * From wap-230-wsp-20010705-a section 8.4.2.24

         *

         * Content-type-value = Constrained-media | Content-general-form

         * Content-general-form = Value-length Media-type

         * Media-type = (Well-known-media | Extension-Media) *(Parameter)

         * Value-length = Short-length | (Length-quote Length)

         * Short-length = <Any octet 0-30>   (octet <= WAP_PDU_SHORT_LENGTH_MAX)

         * Length-quote = <Octet 31>         (WAP_PDU_LENGTH_QUOTE)

         * Length = Uintvar-integer

         */

        if (pduDecoder.decodeContentType(index) == false) {

            if (DBG) Rlog.w(LOG_TAG, "Received PDU. Header Content-Type error.");

            return Intents.RESULT_SMS_GENERIC_ERROR;

        }

        String mimeType = pduDecoder.getValueString();

        long binaryContentType = pduDecoder.getValue32();

        index += pduDecoder.getDecodedDataLength();

        byte[] header = new byte[headerLength];

        System.arraycopy(pdu, headerStartIndex, header, 0, header.length);

        byte[] intentData;

        if (mimeType != null && mimeType.equals(WspTypeDecoder.CONTENT_TYPE_B_PUSH_CO)) {

            intentData = pdu;

        } else {

            int dataIndex = headerStartIndex + headerLength;

            intentData = new byte[pdu.length - dataIndex];

            System.arraycopy(pdu, dataIndex, intentData, 0, intentData.length);

        }

        /**

         * Seek for application ID field in WSP header.

         * If application ID is found, WapPushManager substitute the message

         * processing. Since WapPushManager is optional module, if WapPushManager

         * is not found, legacy message processing will be continued.

         */

        if (pduDecoder.seekXWapApplicationId(index, index + headerLength - 1)) {

            index = (int) pduDecoder.getValue32();

            pduDecoder.decodeXWapApplicationId(index);

            String wapAppId = pduDecoder.getValueString();

            if (wapAppId == null) {

                wapAppId = Integer.toString((int) pduDecoder.getValue32());

            }

            String contentType = ((mimeType == null) ?

                                  Long.toString(binaryContentType) : mimeType);

            if (DBG) Rlog.v(LOG_TAG, "appid found: " + wapAppId + ":" + contentType);

            try {

                boolean processFurther = true;

                IWapPushManager wapPushMan = mWapConn.getWapPushManager();

                if (wapPushMan == null) {

                    if (DBG) Rlog.w(LOG_TAG, "wap push manager not found!");

                } else {

                    Intent intent = new Intent();

                    intent.putExtra("transactionId", transactionId);

                    intent.putExtra("pduType", pduType);

                    intent.putExtra("header", header);

                    intent.putExtra("data", intentData);

                    intent.putExtra("contentTypeParameters",

                            pduDecoder.getContentParameters());

                    intent.putExtra(MSimConstants.SUBSCRIPTION_KEY,

                            mSmsDispatcher.mPhone.getSubscription());

                    if (!TextUtils.isEmpty(address)){

                        intent.putExtra("address", address);

                    }

                    int procRet = wapPushMan.processMessage(wapAppId, contentType, intent);

                    if (DBG) Rlog.v(LOG_TAG, "procRet:" + procRet);

                    if ((procRet & WapPushManagerParams.MESSAGE_HANDLED) > 0

                        && (procRet & WapPushManagerParams.FURTHER_PROCESSING) == 0) {

                        processFurther = false;

                    }

                }

                if (!processFurther) {

                    return Intents.RESULT_SMS_HANDLED;

                }

            } catch (RemoteException e) {

                if (DBG) Rlog.w(LOG_TAG, "remote func failed...");

            }

        }

        if (DBG) Rlog.v(LOG_TAG, "fall back to existing handler");

        if (mimeType == null) {

            if (DBG) Rlog.w(LOG_TAG, "Header Content-Type error.");

            return Intents.RESULT_SMS_GENERIC_ERROR;

        }

        String permission;

        int appOp;

        if (mimeType.equals(WspTypeDecoder.CONTENT_TYPE_B_MMS)) {

            permission = android.Manifest.permission.RECEIVE_MMS;

            appOp = AppOpsManager.OP_RECEIVE_MMS;

        } else {

            permission = android.Manifest.permission.RECEIVE_WAP_PUSH;

            appOp = AppOpsManager.OP_RECEIVE_WAP_PUSH;

        }

        Intent intent = new Intent(Intents.WAP_PUSH_RECEIVED_ACTION);

        intent.setType(mimeType);

        intent.putExtra("transactionId", transactionId);

        intent.putExtra("pduType", pduType);

        intent.putExtra("header", header);

        intent.putExtra("data", intentData);

        intent.putExtra("contentTypeParameters", pduDecoder.getContentParameters());

        intent.putExtra(MSimConstants.SUBSCRIPTION_KEY, mSmsDispatcher.mPhone.getSubscription());

        if (!TextUtils.isEmpty(address)){

            intent.putExtra("address", address);

        }

        mSmsDispatcher.dispatch(intent, permission, appOp);

        return Activity.RESULT_OK;

    }

    public void dispatch(Intent intent, String permission, int appOp) {

        // 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, appOp, mResultReceiver,

                this, Activity.RESULT_OK, null, null);

    }

                  GSM和CDMA的短信接收有很大一部分是相同的,只是CDMA由于标准定义的不同,需要进行一些其他的处理,因为工作上没有对这部分进行测试,这里不作研究了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐