美文网首页
发送短信流程一

发送短信流程一

作者: 坠叶飘香 | 来源:发表于2019-05-20 23:16 被阅读0次

    1.send

    packages\apps\Mms\src\com\android\mms\data\WorkingMessage.java

    public void send(final String recipientsInUI) {
            long origThreadId = mConversation.getThreadId();
            removeSubjectIfEmpty(true /* notify */);
    
            // Get ready to write to disk.
            prepareForSave(true /* notify */);
    
            // We need the recipient list for both SMS and MMS.
            final Conversation conv = mConversation;
            String msgTxt = mText.toString();
    
            if (requiresMms() || addressContainsEmailToMms(conv, msgTxt)) {
              //彩信
            } else {
                // Same rules apply as above.
                final String msgText = mText.toString();
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        preSendSmsWorker(conv, msgText, recipientsInUI);
    
                        updateSendStats(conv);
                    }
                }, "WorkingMessage.send SMS").start();
            }
    
            // update the Recipient cache with the new to address, if it's different
            RecipientIdCache.updateNumbers(conv.getThreadId(), conv.getRecipients());
    
            // Mark the message as discarded because it is "off the market" after being sent.
            mDiscarded = true;
        }
    

    2. preSendSmsWorker

    packages\apps\Mms\src\com\android\mms\data\WorkingMessage.java

    private void preSendSmsWorker(Conversation conv, String msgText, String recipientsInUI) {
            // If user tries to send the message, it's a signal the inputted text is what they wanted.
            UserHappinessSignals.userAcceptedImeText(mActivity);
            //把内容编辑框,联系人输入框,mWorkingMessage等恢复原样
            mStatusListener.onPreMessageSent();
    
            long origThreadId = conv.getThreadId();
    
            // Make sure we are still using the correct thread ID for our recipient set.
            long threadId = conv.ensureThreadId(); //最终通过Threads.getOrCreateThreadId创建/查询threadId
    
            String semiSepRecipients = conv.getRecipients().serialize();
    
            // recipientsInUI can be empty when the user types in a number and hits send
            if (LogTag.SEVERE_WARNING && ((origThreadId != 0 && origThreadId != threadId) ||
                   (!semiSepRecipients.equals(recipientsInUI) && !TextUtils.isEmpty(recipientsInUI)))) {
            }else {
                // just do a regular send. We're already on a non-ui thread so no need to fire
                // off another thread to do this work.
                sendSmsWorker(msgText, semiSepRecipients, threadId);
    
                // Be paranoid and clean any draft SMS up.
                deleteDraftSmsMessage(threadId); //删除数据库的草稿
            }
        }
    

    3.sendSmsWorker

    private void sendSmsWorker(String msgText, String semiSepRecipients, long threadId) {
            String[] dests = TextUtils.split(semiSepRecipients, ";");
            if (LogTag.VERBOSE || Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {
                Log.d(LogTag.TRANSACTION, "sendSmsWorker sending message: recipients=" +
                        semiSepRecipients + ", threadId=" + threadId);
            }
            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);
            }
            
            //1.重新查询信息列表
            mStatusListener.onMessageSent();
    
            MmsWidgetProvider.notifyDatasetChanged(mActivity);
    }
    

    4.sendMessage

    packages\apps\Mms\src\com\android\mms\transaction\SmsMessageSender.java

    public boolean sendMessage(long token) throws MmsException {
            // In order to send the message one by one, instead of sending now, the message will split,
            // and be put into the queue along with each destinations
            return queueMessage(token);
    }
    

    5.queueMessage

    packages\apps\Mms\src\com\android\mms\transaction\SmsMessageSender.java

    private boolean queueMessage(long token) throws MmsException {
            if ((mMessageText == null) || (mNumberOfDests == 0)) {
                // Don't try to send an empty message.
                throw new MmsException("Null message body or dest.");
            }
    
            SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(mContext);
            boolean requestDeliveryReport = prefs.getBoolean(
                    MessagingPreferenceActivity.SMS_DELIVERY_REPORT_MODE,
                    DEFAULT_DELIVERY_REPORT_MODE);
            //几个收件人,就会存入几条信息(MESSAGE_TYPE_QUEUED = 6)
            for (int i = 0; i < mNumberOfDests; i++) {
                try {
                    if (LogTag.DEBUG_SEND) {
                        Log.v(TAG, "queueMessage mDests[i]: " + mDests[i] + " mThreadId: " + mThreadId);
                    }
                    Sms.addMessageToUri(mContext.getContentResolver(),
                            Uri.parse("content://sms/queued"), mDests[i],
                            mMessageText, null, mTimestamp,
                            true /* read */,
                            requestDeliveryReport,
                            mThreadId);
                } catch (SQLiteException e) {
                    if (LogTag.DEBUG_SEND) {
                        Log.e(TAG, "queueMessage SQLiteException", e);
                    }
                    SqliteWrapper.checkSQLiteException(mContext, e);
                }
            }
            //发送广播
            // Notify the SmsReceiverService to send the message out
            mContext.sendBroadcast(new Intent(SmsReceiverService.ACTION_SEND_MESSAGE,
                    null,
                    mContext,
                    SmsReceiver.class));
            return false;
    }
    

    6.onReceive

    packages\apps\Mms\src\com\android\mms\transaction\SmsReceiver.java

    public void onReceive(Context context, Intent intent) {
      onReceiveWithPrivilege(context, intent, false);
    }
    

    7.onReceiveWithPrivilege

    packages\apps\Mms\src\com\android\mms\transaction\SmsReceiver.java

    protected void onReceiveWithPrivilege(Context context, Intent intent, boolean privileged) {
            // If 'privileged' is false, it means that the intent was delivered to the base
            // no-permissions receiver class.  If we get an SMS_RECEIVED message that way, it
            // means someone has tried to spoof the message by delivering it outside the normal
            // permission-checked route, so we just ignore it.
            if (!privileged && intent.getAction().equals(Intents.SMS_DELIVER_ACTION)) {
                return;
            }
    
            intent.setClass(context, SmsReceiverService.class);
            intent.putExtra("result", getResultCode());
            beginStartingService(context, intent);
    }
    

    8.beginStartingService

    packages\apps\Mms\src\com\android\mms\transaction\SmsReceiver.java

    public static void beginStartingService(Context context, Intent intent) {
            synchronized (mStartingServiceSync) {
                if (mStartingService == null) {
                    PowerManager pm =
                        (PowerManager)context.getSystemService(Context.POWER_SERVICE);
                    //PARTIAL_WAKE_LOCK:保持CPU 运转,屏幕和键盘灯有可能是关闭的。
                    mStartingService = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
                            "StartingAlertService");
                    mStartingService.setReferenceCounted(false);
                }
                mStartingService.acquire();
                context.startService(intent);
            }
    }
    

    9.handleSendMessage

    packages\apps\Mms\src\com\android\mms\transaction\SmsReceiverService.java

    private void handleSendMessage() {
      if (!mSending) {
        sendFirstQueuedMessage();
      }
    }
    

    10.sendFirstQueuedMessage

    packages\apps\Mms\src\com\android\mms\transaction\SmsReceiverService.java

    public synchronized void sendFirstQueuedMessage() {
            boolean success = true;
            // get all the queued messages from the database
            final Uri uri = Uri.parse("content://sms/queued");
            ContentResolver resolver = getContentResolver();
            //按照时间降序查询所有待发送的短信
            Cursor c = SqliteWrapper.query(this, resolver, uri,
                            SEND_PROJECTION, null, null, "date ASC");   // date ASC so we send out in
                                                                        // same order the user tried
                                                                        // to send messages.
            if (c != null) {
                try {
                    if (c.moveToFirst()) {
                        String msgText = c.getString(SEND_COLUMN_BODY);
                        String address = c.getString(SEND_COLUMN_ADDRESS);
                        int threadId = c.getInt(SEND_COLUMN_THREAD_ID);
                        int status = c.getInt(SEND_COLUMN_STATUS);
    
                        int msgId = c.getInt(SEND_COLUMN_ID);
                        Uri msgUri = ContentUris.withAppendedId(Sms.CONTENT_URI, msgId);
    
                        SmsMessageSender sender = new SmsSingleRecipientSender(this,
                                address, msgText, threadId, status == Sms.STATUS_PENDING,
                                msgUri);
    
                        if (LogTag.DEBUG_SEND ||
                                LogTag.VERBOSE ||
                                Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {
                            Log.v(TAG, "sendFirstQueuedMessage " + msgUri +
                                    ", address: " + address +
                                    ", threadId: " + threadId);
                        }
    
                        try {
                            sender.sendMessage(SendingProgressTokenManager.NO_TOKEN);;
                            mSending = true;
                        } catch (MmsException e) {
                            Log.e(TAG, "sendFirstQueuedMessage: failed to send message " + msgUri
                                    + ", caught ", e);
                            mSending = false;
                            //发生异常:将短信type更新为MESSAGE_TYPE_FAILED(5),这里的error为1
                            messageFailedToSend(msgUri, SmsManager.RESULT_ERROR_GENERIC_FAILURE);
                            success = false;
                            // Sending current message fails. Try to send more pending messages
                            // if there is any.
                            //发送下一条需要发送的短信
                            sendBroadcast(new Intent(SmsReceiverService.ACTION_SEND_MESSAGE,
                                    null,
                                    this,
                                    SmsReceiver.class));
                        }
                    }
                } finally {
                    c.close();
                }
            }
            if (success) {
                // We successfully sent all the messages in the queue. We don't need to
                // be notified of any service changes any longer.
                unRegisterForServiceStateChanges();
            }
    }
    

    11.sendMessage

    packages\apps\Mms\src\com\android\mms\transaction\SmsSingleRecipientSender.java

    public boolean sendMessage(long token) throws MmsException {
            if (LogTag.DEBUG_SEND) {
                Log.v(TAG, "sendMessage token: " + token);
            }
            if (mMessageText == null) {
                // Don't try to send an empty message, and destination should be just
                // one.
                throw new MmsException("Null message body or have multiple destinations.");
            }
            SmsManager smsManager = SmsManager.getDefault();
            ArrayList<String> messages = null;
            if ((MmsConfig.getEmailGateway() != null) &&
                    (Mms.isEmailAddress(mDest) || MessageUtils.isAlias(mDest))) {
                String msgText;
                msgText = mDest + " " + mMessageText;
                mDest = MmsConfig.getEmailGateway();
                messages = smsManager.divideMessage(msgText);
            } else {
                messages = smsManager.divideMessage(mMessageText); //分割信息
                // remove spaces and dashes from destination number
                // (e.g. "801 555 1212" -> "8015551212")
                // (e.g. "+8211-123-4567" -> "+82111234567")
                mDest = PhoneNumberUtils.stripSeparators(mDest);
                mDest = Conversation.verifySingleRecipient(mContext, mThreadId, mDest);
            }
            int messageCount = messages.size();
    
            if (messageCount == 0) {
                // Don't try to send an empty message.
                throw new MmsException("SmsMessageSender.sendMessage: divideMessage returned " +
                        "empty messages. Original message is \"" + mMessageText + "\"");
            }
            //更新信息type为MESSAGE_TYPE_OUTBOX(4)
            boolean moved = Sms.moveMessageToFolder(mContext, mUri, Sms.MESSAGE_TYPE_OUTBOX, 0);
            if (!moved) {
                throw new MmsException("SmsMessageSender.sendMessage: couldn't move message " +
                        "to outbox: " + mUri);
            }
            if (LogTag.DEBUG_SEND) {
                Log.v(TAG, "sendMessage mDest: " + mDest + " mRequestDeliveryReport: " +
                        mRequestDeliveryReport);
            }
    
            ArrayList<PendingIntent> deliveryIntents =  new ArrayList<PendingIntent>(messageCount);
            ArrayList<PendingIntent> sentIntents = new ArrayList<PendingIntent>(messageCount);
            for (int i = 0; i < messageCount; i++) {
                if (mRequestDeliveryReport && (i == (messageCount - 1))) {
                    // TODO: Fix: It should not be necessary to
                    // specify the class in this intent.  Doing that
                    // unnecessarily limits customizability.
                    deliveryIntents.add(PendingIntent.getBroadcast(
                            mContext, 0,
                            new Intent(
                                    MessageStatusReceiver.MESSAGE_STATUS_RECEIVED_ACTION,
                                    mUri,
                                    mContext,
                                    MessageStatusReceiver.class),
                                    0));
                } else {
                    deliveryIntents.add(null);
                }
                Intent intent  = new Intent(SmsReceiverService.MESSAGE_SENT_ACTION,
                        mUri,
                        mContext,
                        SmsReceiver.class);
    
                int requestCode = 0;
                if (i == messageCount -1) {
                    // Changing the requestCode so that a different pending intent
                    // is created for the last fragment with
                    // EXTRA_MESSAGE_SENT_SEND_NEXT set to true.
                    requestCode = 1;
                    intent.putExtra(SmsReceiverService.EXTRA_MESSAGE_SENT_SEND_NEXT, true);
                }
                if (LogTag.DEBUG_SEND) {
                    Log.v(TAG, "sendMessage sendIntent: " + intent);
                }
                sentIntents.add(PendingIntent.getBroadcast(mContext, requestCode, intent, 0));
            }
            try {
                smsManager.sendMultipartTextMessage(mDest, mServiceCenter, messages, sentIntents, deliveryIntents);
            } catch (Exception ex) {
                Log.e(TAG, "SmsMessageSender.sendMessage: caught", ex);
                throw new MmsException("SmsMessageSender.sendMessage: caught " + ex +
                        " from SmsManager.sendTextMessage()");
            }
            if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE) || LogTag.DEBUG_SEND) {
                log("sendMessage: address=" + mDest + ", threadId=" + mThreadId +
                        ", uri=" + mUri + ", msgs.count=" + messageCount);
            }
            return false;
        }
    

    12.sendMultipartTextMessage

    frameworks\base\telephony\java\android\telephony\SmsManager.java

    public void sendMultipartTextMessage(
                String destinationAddress, String scAddress, ArrayList<String> parts,
                ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents) {
            sendMultipartTextMessageInternal(destinationAddress, scAddress, parts, sentIntents,
                    deliveryIntents, true /* persistMessage*/);
    }
    

    13.sendMultipartTextMessageInternal

    frameworks\base\telephony\java\android\telephony\SmsManager.java

    private void sendMultipartTextMessageInternal(
                String destinationAddress, String scAddress, List<String> parts,
                List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents,
                boolean persistMessage) {
            if (TextUtils.isEmpty(destinationAddress)) {
                throw new IllegalArgumentException("Invalid destinationAddress");
            }
            if (parts == null || parts.size() < 1) {
                throw new IllegalArgumentException("Invalid message body");
            }
    
            if (parts.size() > 1) {//长信息
                try {
                    ISms iccISms = getISmsServiceOrThrow();
                    iccISms.sendMultipartTextForSubscriber(getSubscriptionId(),
                            ActivityThread.currentPackageName(),
                            destinationAddress, scAddress, parts,
                            sentIntents, deliveryIntents, persistMessage);
                } catch (RemoteException ex) {
                    // ignore it
                }
            } else { //短信息
                PendingIntent sentIntent = null;
                PendingIntent deliveryIntent = null;
                if (sentIntents != null && sentIntents.size() > 0) {
                    sentIntent = sentIntents.get(0);
                }
                if (deliveryIntents != null && deliveryIntents.size() > 0) {
                    deliveryIntent = deliveryIntents.get(0);
                }
                sendTextMessage(destinationAddress, scAddress, parts.get(0),
                        sentIntent, deliveryIntent);
            }
    }
    

    相关文章

      网友评论

          本文标题:发送短信流程一

          本文链接:https://www.haomeiwen.com/subject/iifrzqtx.html