android 信息(mms)開發(三) -- 發短信

   當你在編輯界面ComposeMessageActivity.java按下發送按鈕的那一刻,就開始信息的發送之路。當然發短信和發彩信並不完全一樣,會用兩篇文章別說明,不過最後的圖是畫在一起的。

       從ComposeMessageActivity.java的onclick()開始,在這裏對聯繫人的個數是有個判斷的,這個函數 isPreparedForSending(),這個判斷之後會通過confirmSendMessageIfNeeded()檢查聯繫人是否有效,如包含無效聯繫人會有對話框提示的,還是比較友好的。這裏要注意的是源碼判斷少於3個數字的聯繫人是非法的,並且數字號碼是否合法的判斷方法也不是很嚴密,4.0的代碼貌似把多選聯繫人的功能加上去,這個方法  launchMultiplePhonePicker(),對應代碼如下。

      

  public void onClick(View v) {
        if ((v == mSendButtonSms || v == mSendButtonMms) && isPreparedForSending()) {
            confirmSendMessageIfNeeded();
        } else if ((v == mRecipientsPicker)) {
            launchMultiplePhonePicker();
        }
    }

       檢查聯繫人之後接下來執行WorkingMessage.java的send()方法,在send()方法裏會判斷是發短信還是發彩信(彩信條件:有主題、圖片、音頻、視頻、幻燈片和含中文多於670個字或多於1350個字的純英文信息),短信和彩信在這裏分家了,兩個線程分別負責發送短信和彩信,本來就不是一個東西,早點分開有好處。先看短信
 

private void sendSmsWorker(String msgText, String semiSepRecipients, long threadId) {//文本內容,收件人,會話ID
        String[] dests = TextUtils.split(semiSepRecipients, ";");
        MessageSender sender = new SmsMessageSender(mActivity, dests, msgText, threadId);//運行時綁定,這算是多態的一個應用吧。
        try {
            sender.sendMessage(threadId);
            // Make sure this thread isn't over the limits in message count
            Recycler.getSmsRecycler().deleteOldMessagesByThreadId(mActivity, threadId);
        } catch (Exception e) {
            Log.e(TAG, "Failed to send SMS message, threadId=" + threadId, e);
        }
        mStatusListener.onMessageSent();
    }

       接下來要走進發送隊列了SmsMessageSender.java的sendMessage.java,按收件人個數把短信寫入數據庫,uri是這個Uri.parse("content://sms/queued"),這裏代碼可以體現出短信和彩信發送區別,短信有多少個收件人發多少條,彩信多少個收件人都是一條,不一樣哦,那麼收件人多的時候短信和彩信用哪個啊?不知道大家有沒有看這個類的這個函數getOutgoingServiceCenter(),它是本意是從收到信息裏找出短信中心,如果沒有收到的信息怎麼辦?沒有短信中心不行的,實際上這個不用擔心了,一般下面的模塊會處理的。
       到了短信的關鍵服務SmsReceiverService.java,關鍵的原因是因爲發送接收都在這裏,這是必經之路,發送是要走sendFirstQueuedMessage(),發送成功或失敗的消息handleSmsSent()這個函數處理,實際發送是在SmsSingleRecipientSender.java這個類裏,在這處理會把長短信分段,這個代碼:

    messages = smsManager.divideMessage(mMessageText)
        處理完長短信,發送信息執行下面代碼,這個代碼後我們就要離開packages層了。
    smsManager.sendMultipartTextMessage(mDest, mServiceCenter, messages, sentIntents, deliveryIntents);

        Framework層 SmsManager.java的sendMultipartTextMessage()方法、sendTextMessage()和sendDataMessage()方法負責發送,前兩個發普通短信,最後一個發端口短信比如以短信形式發vcard。再向下跟GsmSMSDispatcher.java的sendText()方法,在個方法裏開始編碼了,看貼出的代碼:

protected void sendText(String destAddr, String scAddr, String text,
            PendingIntent sentIntent, PendingIntent deliveryIntent) {
        SmsMessage.SubmitPdu pdu = SmsMessage.getSubmitPdu(
                scAddr, destAddr, text, (deliveryIntent != null));
        if (pdu != null) {
            sendRawPdu(pdu.encodedScAddress, pdu.encodedMessage, sentIntent, deliveryIntent);
        } else {
            Log.e(TAG, "GsmSMSDispatcher.sendText(): getSubmitPdu() returned null");
        }
    }


還在這個類裏sendSms()方法,這裏調用的Ril.java的方法,終於到ril了。
  

  protected void sendSms(SmsTracker tracker) {
        HashMap<String, Object> map = tracker.mData;
 
        byte smsc[] = (byte[]) map.get("smsc");
        byte pdu[] = (byte[]) map.get("pdu");
 
        Message reply = obtainMessage(EVENT_SEND_SMS_COMPLETE, tracker);
        mCm.sendSMS(IccUtils.bytesToHexString(smsc), IccUtils.bytesToHexString(pdu), reply);
    }


Ril.java的方法,看好那個TAG,RIL_REQUEST_SEND_SMS這個我們會在Referece-ril.c的代碼中找到它,當然這是源碼,不同的vendor廠商可能會根據自己的需要修改的

 public void  sendSMS (String smscPDU, String pdu, Message result) {
        RILRequest rr
                = RILRequest.obtain(RIL_REQUEST_SEND_SMS, result);
        rr.mp.writeInt(2);
        rr.mp.writeString(smscPDU);
        rr.mp.writeString(pdu);
 
        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
        send(rr);
    }


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章