android 信息(mms)的故事(三) -- 发短信

来源:互联网 发布:网页游戏源码下载 编辑:程序博客网 时间:2024/04/27 19:28

        当你在编辑界面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);    }
到这里,发短信的流程基本上结束了,当然这里还很多细节没有展开,比如短信的编码,别急,后面我会写的



原创粉丝点击