Android短信开发 发送彩信 ‘ 高通源码 ‘ (彩信发送过程1)
发布日期:2021-06-30 21:23:17 浏览次数:2 分类:技术文章

本文共 46373 字,大约阅读时间需要 154 分钟。

Android彩信发送有下面几个类:


 一个一个类看  :

      1 . ComposeMessageActivity.java   详情页面

      2 . WoringMessage.java                  处理一些发送短信-或-彩信方法

      3.  MmsMessageSender.java           彩信入本地数据库

      4.  TransactionService.java              开启服务进行发送或下载操作实现功能

      5. SendTransaction.java                  主要功能他是一个线程,在线程里面访问他的父类Transaction里面的SendPdu()方法

      6. Transaction.java                           主要功能通过他的子类传递值,去调用HttpUtils里面的网络发送下载方法

      7. HttpUtils.java                                  主要进行网络访问httpConnection.java

 

 



ComposeMessageActivity.java

主要作用是send()方法  ,建议先看   , 普通短信发送过程     

 

 


 

WoringMessage.java 

send()方法里面主要看   

new Thread(new Runnable() { }   //这里面调用了
sendMmsWorker()  方法
public void send(final String recipientsInUI) {        long origThreadId = mConversation.getThreadId();        LogTag.debugD("send origThreadId: " + origThreadId);        removeSubjectIfEmpty(true /* notify */);        // Get ready to write to disk.        prepareForSave(true /* notify */);        // Make sure the mConversation has Recipients        checkConversationHasRecipients(recipientsInUI);        // We need the recipient list for both SMS and MMS.        final Conversation conv = mConversation;        String msgTxt = mText.toString();        if (requiresMms() || addressContainsEmailToMms(conv, msgTxt)) {            // uaProfUrl setting in mms_config.xml must be present to send an MMS.            // However, SMS service will still work in the absence of a uaProfUrl address.            if (MmsConfig.getUaProfUrl() == null) {                String err = "WorkingMessage.send MMS sending failure. mms_config.xml is " +                        "missing uaProfUrl setting.  uaProfUrl is required for MMS service, " +                        "but can be absent for SMS.";                RuntimeException ex = new NullPointerException(err);                Log.e(TAG, err, ex);                // now, let's just crash.                throw ex;            }            // Make local copies of the bits we need for sending a message,            // because we will be doing it off of the main thread, which will            // immediately continue on to resetting some of this state.            final Uri mmsUri = mMessageUri;            final PduPersister persister = PduPersister.getPduPersister(mActivity);            final SlideshowModel slideshow = mSlideshow;            final CharSequence subject = mSubject;            final boolean textOnly = mAttachmentType == TEXT;            LogTag.debugD("Send mmsUri: " + mmsUri);            // Do the dirty work of sending the message off of the main UI thread.            new Thread(new Runnable() {  //发送信息调用                @Override                public void run() {                    final SendReq sendReq = makeSendReq(conv, subject);                    // Make sure the text in slide 0 is no longer holding onto a reference to                    // the text in the message text box.                    slideshow.prepareForSend();                    sendMmsWorker(conv, mmsUri, persister, slideshow, sendReq, textOnly);                    updateSendStats(conv);                }            }, "WorkingMessage.send MMS").start();        } else {            // Same rules apply as above.            // Add user's signature first if this feature is enabled.            String text = mText.toString();            LogTag.debugD("mText="+text);            SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mActivity);            if (sp.getBoolean("pref_key_enable_signature", false)) {                String signature = (sp.getString("pref_key_edit_signature", "")).trim();                if (signature.length() > 0) {                    String sigBlock = "\n" + signature;                    if (!text.endsWith(sigBlock)) {                        // Signature should be written behind the text in a                        // newline while the signature has changed.                        text += sigBlock;                    }                }            }            final String msgText = text;            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;    }

-------------------------sendMmsWorker方法

private void sendMmsWorker(Conversation conv, Uri mmsUri, PduPersister persister,            SlideshowModel slideshow, SendReq sendReq, boolean textOnly) {        long threadId = 0;        Cursor cursor = null;        boolean newMessage = false;        boolean forwardMessage = conv.getHasMmsForward();        boolean sameRecipient = false;        ContactList contactList = conv.getRecipients();//        int phoneCount = MessageUtils.getPhoneCount();        if (contactList != null) {            String[] numbers = contactList.getNumbers();            String[] forward = conv.getForwardRecipientNumber();            if (numbers != null && forward != null                    && (numbers.length == forward.length)) {                List
currentNumberList = Arrays.asList(numbers); List
forwardNumberList = Arrays.asList(forward); Collections.sort(currentNumberList); Collections.sort(forwardNumberList); if (currentNumberList.equals(forwardNumberList)) { sameRecipient = true; } } } try { // Put a placeholder message in the database first DraftCache.getInstance().setSavingDraft(true); mStatusListener.onPreMessageSent(); // Make sure we are still using the correct thread ID for our // recipient set. threadId = conv.ensureThreadId(); if (forwardMessage && sameRecipient) { MessageUtils.sSameRecipientList.add(threadId); } if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) { LogTag.debug("sendMmsWorker: update draft MMS message " + mmsUri + " threadId: " + threadId); } // One last check to verify the address of the recipient. String[] dests = conv.getRecipients().getNumbers(true /* scrub for MMS address */); if (dests.length == 1) { // verify the single address matches what's in the database. If we get a different // address back, jam the new value back into the SendReq. String newAddress = Conversation.verifySingleRecipient(mActivity, conv.getThreadId(), dests[0]); if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) { LogTag.debug("sendMmsWorker: newAddress " + newAddress + " dests[0]: " + dests[0]); } if (!newAddress.equals(dests[0])) { dests[0] = newAddress; EncodedStringValue[] encodedNumbers = EncodedStringValue.encodeStrings(dests); if (encodedNumbers != null) { if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) { LogTag.debug("sendMmsWorker: REPLACING number!!!"); } sendReq.setTo(encodedNumbers); } } MessageUtils.markAsNotificationThreadIfNeed(mActivity, threadId, newAddress); } newMessage = mmsUri == null; if (newMessage) { // Write something in the database so the new message will appear as sending ContentValues values = new ContentValues(); values.put(Mms.MESSAGE_BOX, Mms.MESSAGE_BOX_OUTBOX); values.put(Mms.THREAD_ID, threadId); values.put(Mms.MESSAGE_TYPE, PduHeaders.MESSAGE_TYPE_SEND_REQ); if (textOnly) { values.put(Mms.TEXT_ONLY, 1); } if (MessageUtils.isMsimIccCardActive()) { values.put(Mms.SUBSCRIPTION_ID, mCurrentConvSubId); Log.i(LogTag.ljsTest, "多卡··发送彩信 = " + mCurrentConvSubId); } else { values.put(Mms.SUBSCRIPTION_ID, SubscriptionManager.getDefaultDataSubscriptionId()); Log.i(LogTag.ljsTest, "单卡··发送彩信 = " + mCurrentConvSubId); } mmsUri = SqliteWrapper.insert(mActivity, mContentResolver, Mms.Outbox.CONTENT_URI, values); } mStatusListener.onMessageSent(); // If user tries to send the message, it's a signal the inputted text is // what they wanted. UserHappinessSignals.userAcceptedImeText(mActivity); // First make sure we don't have too many outstanding unsent message. cursor = SqliteWrapper.query(mActivity, mContentResolver, Mms.Outbox.CONTENT_URI, MMS_OUTBOX_PROJECTION, null, null, null); if (cursor != null) { long maxMessageSize = MmsConfig.getMaxSizeScaleForPendingMmsAllowed() * MmsConfig.getMaxMessageSize(); long totalPendingSize = 0; while (cursor.moveToNext()) { totalPendingSize += cursor.getLong(MMS_MESSAGE_SIZE_INDEX); } if (totalPendingSize >= maxMessageSize) { unDiscard(); // it wasn't successfully sent. Allow it to be saved as a draft. mStatusListener.onMaxPendingMessagesReached(); markMmsMessageWithError(mmsUri); return; } } } finally { if (cursor != null) { cursor.close(); } } try { if (newMessage) { // Create a new MMS message if one hasn't been made yet. mmsUri = createDraftMmsMessage(persister, sendReq, slideshow, mmsUri, mActivity, null); } else { // Otherwise, sync the MMS message in progress to disk. updateDraftMmsMessage(mmsUri, persister, slideshow, sendReq, null); } // Be paranoid and clean any draft SMS up. deleteDraftSmsMessage(threadId); } finally { DraftCache.getInstance().setSavingDraft(false); } // Resize all the resizeable attachments (e.g. pictures) to fit // in the remaining space in the slideshow. int error = 0; try { slideshow.finalResize(mmsUri); } catch (ExceedMessageSizeException e1) { error = MESSAGE_SIZE_EXCEEDED; } catch (MmsException e1) { error = UNKNOWN_ERROR; } if (error != 0) { markMmsMessageWithError(mmsUri); mStatusListener.onAttachmentError(error); return; } ContentValues values = new ContentValues(1); if (MessageUtils.isMsimIccCardActive()) { values.put(Mms.SUBSCRIPTION_ID, mCurrentConvSubId); Log.i(LogTag.ljsTest, "多卡··发送彩信完 存数据 = " + mCurrentConvSubId); } else { values.put(Mms.SUBSCRIPTION_ID, SubscriptionManager.getDefaultDataSubscriptionId()); Log.i(LogTag.ljsTest, "单卡··发送彩信完 存数据 = " + mCurrentConvSubId); } SqliteWrapper.update(mActivity, mContentResolver, mmsUri, values, null, null); MessageSender sender = new MmsMessageSender(mActivity, mmsUri, slideshow.getCurrentMessageSize(), mCurrentConvSubId); try { if (!sender.sendMessage(threadId)) { // The message was sent through SMS protocol, we should // delete the copy which was previously saved in MMS drafts. SqliteWrapper.delete(mActivity, mContentResolver, mmsUri, null, null); } // Make sure this thread isn't over the limits in message count Recycler.getMmsRecycler().deleteOldMessagesByThreadId(mActivity, threadId); } catch (Exception e) { Log.e(TAG, "Failed to send message: " + mmsUri + ", threadId=" + threadId, e); } if (forwardMessage && sameRecipient) { MessageUtils.sSameRecipientList.remove(threadId); } MmsWidgetProvider.notifyDatasetChanged(mActivity); MessageUtils.updateThreadAttachTypeByThreadId(mActivity, threadId); }

 

 

---------------------------sendMmsWorker----------------------------

sendMmsWorker方法主要调用   MmsMessageSender里面的sendMessage方法进行数据库插入

在主要操作sender

MessageSender sender = new MmsMessageSender(mActivity, mmsUri,                slideshow.getCurrentMessageSize(), mCurrentConvSubId);        try {            if (!sender.sendMessage(threadId)) {                // The message was sent through SMS protocol, we should                // delete the copy which was previously saved in MMS drafts.                SqliteWrapper.delete(mActivity, mContentResolver, mmsUri, null, null);            }            // Make sure this thread isn't over the limits in message count            Recycler.getMmsRecycler().deleteOldMessagesByThreadId(mActivity, threadId);        } catch (Exception e) {            Log.e(TAG, "Failed to send message: " + mmsUri + ", threadId=" + threadId, e);        }        if (forwardMessage && sameRecipient) {            MessageUtils.sSameRecipientList.remove(threadId);        }

 



MmsMessageSender.java    主要也sendMessage()方法为主

public boolean sendMessage(long token) throws MmsException {        // Load the MMS from the message uri        if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) {            LogTag.debug("sendMessage uri: " + mMessageUri);        }        PduPersister p = PduPersister.getPduPersister(mContext);        GenericPdu pdu = p.load(mMessageUri);        if (pdu.getMessageType() != PduHeaders.MESSAGE_TYPE_SEND_REQ) {            throw new MmsException("Invalid message: " + pdu.getMessageType());        }        SendReq sendReq = (SendReq) pdu;        // Update headers.        updatePreferencesHeaders(sendReq);        // MessageClass.        sendReq.setMessageClass(DEFAULT_MESSAGE_CLASS.getBytes());        // Update the 'date' field of the message before sending it.        sendReq.setDate(System.currentTimeMillis() / 1000L);        sendReq.setMessageSize(mMessageSize);        p.updateHeaders(mMessageUri, sendReq);        long messageId = ContentUris.parseId(mMessageUri);        // Move the message into MMS Outbox.        if (!mMessageUri.toString().startsWith(Mms.Draft.CONTENT_URI.toString())) {            // If the message is already in the outbox (most likely because we created a "primed"            // message in the outbox when the user hit send), then we have to manually put an            // entry in the pending_msgs table which is where TransacationService looks for            // messages to send. Normally, the entry in pending_msgs is created by the trigger:            // insert_mms_pending_on_update, when a message is moved from drafts to the outbox.            ContentValues values = new ContentValues(7);            values.put(PendingMessages.PROTO_TYPE, MmsSms.MMS_PROTO);            values.put(PendingMessages.MSG_ID, messageId);            values.put(PendingMessages.MSG_TYPE, pdu.getMessageType());            values.put(PendingMessages.ERROR_TYPE, 0);            values.put(PendingMessages.ERROR_CODE, 0);            values.put(PendingMessages.RETRY_INDEX, 0);            values.put(PendingMessages.DUE_TIME, 0);            SqliteWrapper.insert(mContext, mContext.getContentResolver(),                    PendingMessages.CONTENT_URI, values);        } else {            p.move(mMessageUri, Mms.Outbox.CONTENT_URI);        }        // Start MMS transaction service        SendingProgressTokenManager.put(messageId, token);        Intent intent = new Intent(mContext, TransactionService.class);        intent.putExtra(Mms.SUBSCRIPTION_ID, mSubId);        mContext.startService(intent);        return true;    }

----SqliteWrapper.insert()插入数据库

SqliteWrapper.insert(mContext, mContext.getContentResolver(),                    PendingMessages.CONTENT_URI, values);

 

插入成功后开启服务  TransactionService 

Intent intent = new Intent(mContext, TransactionService.class);        intent.putExtra(Mms.SUBSCRIPTION_ID, mSubId);        mContext.startService(intent);

 

 



 

TransactionService .java 

这个类主要是进行图片上传和下载

主要看Handerl里面

/**         * Handle incoming transaction requests.         * The incoming requests are initiated by the MMSC Server or by the         * MMS Client itself.         */        @Override        public void handleMessage(Message msg) {            LogTag.debugD("Handling incoming message: " + msg + " = " + decodeMessage(msg));            Transaction transaction = null;            switch (msg.what) {                case EVENT_NEW_INTENT:                    onNewIntent((Intent)msg.obj, msg.arg1);                    break;                case EVENT_QUIT:                    getLooper().quit();                    return;                case EVENT_TRANSACTION_REQUEST:   //通知彩信接收                    int serviceId = msg.arg1;                    try {                        TransactionBundle args = (TransactionBundle) msg.obj;                        TransactionSettings transactionSettings;                        LogTag.debugD("EVENT_TRANSACTION_REQUEST MmscUrl=" +                                args.getMmscUrl() + " proxy port: " + args.getProxyAddress());                        // Set the connection settings for this transaction.                        // If these have not been set in args, load the default settings.                        String mmsc = args.getMmscUrl();                        if (mmsc != null) {                            transactionSettings = new TransactionSettings(                                    mmsc, args.getProxyAddress(), args.getProxyPort());                        } else {                            transactionSettings = new TransactionSettings(                                                    TransactionService.this, null,                                                    args.getSubId());                        }                        int transactionType = args.getTransactionType();                        LogTag.debugD("handle EVENT_TRANSACTION_REQUEST: transactionType=" +                                transactionType + " " + decodeTransactionType(transactionType));                        // Create appropriate transaction                        switch (transactionType) {                            case Transaction.NOTIFICATION_TRANSACTION:                                String uri = args.getUri();                                //用户通知                                if (uri!=null){                                    long threadId = MessagingNotification.getThreadId(                                            getApplicationContext(), Uri.parse(uri));                                    MessagingNotification.blockingUpdateNewMessageIndicator(getApplicationContext(),                                            threadId,                                            false);                                    MessagingNotification.updateDownloadFailedNotification(getApplicationContext());                                    MessageUtils.updateThreadAttachTypeByThreadId(getApplicationContext(), threadId);                                }                                if (uri != null) {                                    //开始解压消息   自动解压彩信                                    transaction = new NotificationTransaction(                                            TransactionService.this, serviceId,                                            transactionSettings, uri                                            );                                }  else {                                    // Now it's only used for test purpose.                                    byte[] pushData = args.getPushData();                                    PduParser parser = new PduParser(pushData,                                            PduParserUtil.shouldParseContentDisposition());                                    GenericPdu ind = parser.parse();                                    int type = PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND;                                    if ((ind != null) && (ind.getMessageType() == type)) {                                        transaction = new NotificationTransaction(                                                TransactionService.this, serviceId,                                                transactionSettings, (NotificationInd) ind);                                    } else {                                        Log.e(TAG, "Invalid PUSH data.");                                        transaction = null;                                        return;                                    }                                }                                break;                            case Transaction.RETRIEVE_TRANSACTION:                                //手动下载短信                                transaction = new RetrieveTransaction(                                        TransactionService.this, serviceId,                                        transactionSettings, args.getUri());                                break;                            case Transaction.SEND_TRANSACTION:                                transaction = new SendTransaction(                                        TransactionService.this, serviceId,                                        transactionSettings, args.getUri());                                break;                            case Transaction.READREC_TRANSACTION:                                transaction = new ReadRecTransaction(                                        TransactionService.this, serviceId,                                        transactionSettings, args.getUri());                                break;                            default:                                Log.w(TAG, "Invalid transaction type: " + serviceId);                                transaction = null;                                return;                        }                        //copy the subId from TransactionBundle to transaction obj.                        transaction.setSubId(args.getSubId());                        if (!processTransaction(transaction)) {                            transaction = null;                            return;                        }                        LogTag.debugD("Started processing of incoming message: " + msg);                    } catch (Exception ex) {                        Log.w(TAG, "Exception occurred while handling message: " + msg, ex);                        if (transaction != null) {                            try {                                transaction.detach(TransactionService.this);                                if (mProcessing.contains(transaction)) {                                    synchronized (mProcessing) {                                        mProcessing.remove(transaction);                                    }                                }                            } catch (Throwable t) {                                Log.e(TAG, "Unexpected Throwable.", t);                            } finally {                                // Set transaction to null to allow stopping the                                // transaction service.                                transaction = null;                            }                        }                    } finally {                        if (transaction == null) {                            LogTag.debugD("Transaction was null. Stopping self: " + serviceId);                            endMmsConnectivity();                            stopSelfIfIdle(serviceId);                        }                    }                    return;                case EVENT_HANDLE_NEXT_PENDING_TRANSACTION:                    processPendingTransaction(transaction, (TransactionSettings) msg.obj);                    return;                case EVENT_MMS_CONNECTIVITY_TIMEOUT:                    removeMessages(EVENT_MMS_CONNECTIVITY_TIMEOUT);                    mMmsConnecvivityRetryCount++;                    if (mMmsConnecvivityRetryCount > MMS_CONNECTIVITY_RETRY_TIMES) {                        Log.d(TAG, "MMS_CONNECTIVITY_TIMEOUT");                        mMmsConnecvivityRetryCount = 0;                        return;                    }                    if (!mPending.isEmpty()) {                        try {                            beginMmsConnectivity(SubscriptionManager.getDefaultDataSubscriptionId());                        } catch (IOException e) {                            Log.w(TAG, "Attempt to use of MMS connectivity failed");                            return;                        }                    }                    return;                case EVENT_MMS_PDP_ACTIVATION_TIMEOUT:                    onPDPTimeout((int)msg.obj);                    return;                default:                    Log.w(TAG, "what=" + msg.what);                    return;            }        }

 

handler    msg.what   会传入一个  5 就是     EVENT_NEW_INTENT  调用了   onNewIntent()方法

public void onNewIntent(Intent intent, int serviceId) {        if (!MmsConfig.isSmsEnabled(getApplicationContext())) {            LogTag.debugD("TransactionService: is not the default sms app");            stopSelf(serviceId);            return;        }        mConnMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);        if (mConnMgr == null || !MmsConfig.isSmsEnabled(getApplicationContext())) {            endMmsConnectivity();            stopSelfIfIdle(serviceId);            return;        }        boolean noNetwork = false;        LogTag.debugD("onNewIntent: serviceId: " + serviceId + ": " + intent.getExtras() +                " intent=" + intent);        Bundle extras = intent.getExtras();        String action = intent.getAction();        DownloadManager downloadManager = DownloadManager.getInstance();        if ((ACTION_ONALARM.equals(action) || ACTION_ENABLE_AUTO_RETRIEVE.equals(action) ||                (extras == null)) || ((extras != null) && !extras.containsKey("uri")                && !extras.containsKey(CANCEL_URI))) {            //We hit here when either the Retrymanager triggered us or there is            //send operation in which case uri is not set. For rest of the            //cases(MT MMS) we hit "else" case.            // Scan database to find all pending operations.            Cursor cursor = PduPersister.getPduPersister(this).getPendingMessages(                    System.currentTimeMillis());            LogTag.debugD("Cursor= " + DatabaseUtils.dumpCursorToString(cursor));            if (cursor != null) {                try {                    int count = cursor.getCount();                    LogTag.debugD("onNewIntent: cursor.count=" + count + " action=" + action);                    //判断是否有未发送的如果没有就    停止服务                    if (count == 0) {                        LogTag.debugD("onNewIntent: no pending messages. Stopping service.");                        RetryScheduler.setRetryAlarm(this);                        stopSelfIfIdle(serviceId);                        return;uricolumnIndexOfMsgId = cursor.getColumnIndexOrThrow(PendingMessages.MSG_ID);                    int columnIndexOfMsgType = cursor.getColumnIndexOrThrow(                            PendingMessages.MSG_TYPE);                    int columnIndexOfRetryIndex = cursor.getColumnIndexOrThrow(                            PendingMessages.RETRY_INDEX);                    int inActiveSubCount = 0;                    while (cursor.moveToNext()) {                        int msgType = cursor.getInt(columnIndexOfMsgType);                        int transactionType = getTransactionType(msgType);                        if (transactionType==Transaction.RETRIEVE_TRANSACTION){                            //如果是下载就跳出循环      transactionType=1就表示自动去再次请求下载                             continue;                        }                        LogTag.debugD("onNewIntent: msgType=" + msgType + " transactionType=" +                                transactionType);                        Uri uri = ContentUris.withAppendedId(                                Mms.CONTENT_URI,                                cursor.getLong(columnIndexOfMsgId));                        boolean inRetry = cursor.getInt(columnIndexOfRetryIndex) > 0;                        if (noNetwork) {                            // Because there is a MMS queue list including                            // unsent and undownload MMS in database while data                            // network unenabled. Anyway we should give user the                            // information about the last MMS in the queue list.                            // While there is no data network, we will give                            // a prompt to user about the last MMS failed in                            // database, so we need to fetch the information of                            // last pending MMS in the queue list, just make the                            // cursor move to the end of the queue list, and                            // give the corresponding prompt to user.                            cursor.moveToLast();                            //                            transactionType = getTransactionType(cursor                                    .getInt(columnIndexOfMsgType));                            onNetworkUnavailable(serviceId, transactionType, uri, inRetry);                            return;                        }                        switch (transactionType) {                            case -1:                                break;                            case Transaction.RETRIEVE_TRANSACTION:                                // If it's a transiently failed transaction,                                // we should retry it in spite of current                                // downloading mode. If the user just turned on the auto-retrieve                                // option, we also retry those messages that don't have any errors.                                int failureType = cursor.getInt(                                        cursor.getColumnIndexOrThrow(                                                PendingMessages.ERROR_TYPE));                                boolean autoDownload = downloadManager.isAuto();                                LogTag.debugD("onNewIntent: failureType=" + failureType +                                        " action=" + action + " isTransientFailure:" +                                        isTransientFailure(failureType) + " autoDownload=" +                                        autoDownload);                                if (!autoDownload && !inRetry) {                                    // If autodownload is turned off and not in retry peroid,                                    // don't process the transaction.                                    LogTag.debugD("onNewIntent: skipping - autodownload off");                                    break;                                }                                // If retry always is enabled, need mark state to downloading.                                if (getResources().getBoolean(R.bool.config_retry_always)) {                                    downloadManager.markState(                                            uri, DownloadManager.STATE_DOWNLOADING);                                }                                // Logic is twisty. If there's no failure or the failure                                // is a non-permanent failure, we want to process the transaction.                                // Otherwise, break out and skip processing this transaction.                                if (!(failureType == MmsSms.NO_ERROR ||                                        isTransientFailure(failureType))) {                                    LogTag.debugD("onNewIntent: skipping - permanent error");                                    break;                                }                                LogTag.debugD( "onNewIntent: falling through and processing");                               // fall-through                            default:                                int subId = getSubIdFromDb(uri);                                Log.d(TAG, "destination Sub Id = " + subId);                                if (subId < 0) {                                    Log.d(TAG, "Subscriptions are not yet ready.");                                    int defSmsSubId = getDefaultSmsSubscriptionId();                                    // We dont have enough info about subId. We dont know if the                                    // subId as persent in DB actually would match the subId of                                    // defaultSmsSubId. We can not also ignore this transaction                                    // since no retry would be scheduled if we return from here. The                                    // only option is to do best effort try on current default sms                                    // subId, if it failed then a retry would be scheduled and while                                    // processing that retry attempt we would be able to get correct                                    // subId from subscription manager.                                    Log.d(TAG, "Override with default Sms subId = " + defSmsSubId);                                    subId = defSmsSubId;                                }                                if ((!isMmsAllowed())                                        && !getResources().getBoolean(R.bool.config_retry_always)) {                                    Log.d(TAG, "mobileData off or no mms apn or APM, Abort");                                    if (transactionType == Transaction.RETRIEVE_TRANSACTION) {                                        downloadManager.markState(uri,                                                DownloadManager.STATE_TRANSIENT_FAILURE);                                    }                                    onNetworkUnavailable(serviceId, transactionType, uri, inRetry);                                    break;                                }                                if (!SubscriptionManager.from(getApplicationContext())                                        .isActiveSubId(subId)) {                                    LogTag.debugD("SubId is not active:" + subId);                                    inActiveSubCount ++;                                    if (inActiveSubCount == count) {                                        LogTag.debugD("No active SubId found, stop self: " + count);                                        stopSelfIfIdle(serviceId);                                    }                                    break;                                }                                TransactionBundle args = new TransactionBundle(transactionType,                                        uri.toString(), subId);                                // FIXME: We use the same startId for all MMs.                                LogTag.debugD("onNewIntent: launchTransaction uri=" + uri);                                // FIXME: We use the same serviceId for all MMs.                                launchTransaction(serviceId, args, false);                                break;                        }                    }                } finally {                    cursor.close();                }            } else {                LogTag.debugD("onNewIntent: no pending messages. Stopping service.");                RetryScheduler.setRetryAlarm(this);                stopSelfIfIdle(serviceId);            }        } else if ((extras != null) && extras.containsKey(CANCEL_URI)) {            String uriStr = intent.getStringExtra(CANCEL_URI);            Uri mCancelUri = Uri.parse(uriStr);            for (Transaction transaction : mProcessing) {                transaction.cancelTransaction(mCancelUri);            }            for (Transaction transaction : mPending) {                transaction.cancelTransaction(mCancelUri);            }        } else {            LogTag.debugD("onNewIntent: launch transaction...");            String uriStr = intent.getStringExtra("uri");            Uri uri = Uri.parse(uriStr);            int subId = getSubIdFromDb(uri);            Log.d(TAG, "destination Sub Id = " + subId);            if (subId < 0) {               int defSmsSubId = getDefaultSmsSubscriptionId();                Log.d(TAG, "Override with default Sms subId = " + defSmsSubId);                subId = defSmsSubId;            }            if ((!isMmsAllowed()) && !getResources().getBoolean(R.bool.config_retry_always)) {                Log.d(TAG, "Either mobile data is off or apn not present, Abort");                downloadManager.markState(uri, DownloadManager.STATE_TRANSIENT_FAILURE);                boolean isRetry = getRetryIndex(uri.getLastPathSegment()) > 0;                int type = intent.getIntExtra(TransactionBundle.TRANSACTION_TYPE,                        Transaction.NOTIFICATION_TRANSACTION);                onNetworkUnavailable(serviceId, type, uri, isRetry);                return;            }            if (!SubscriptionManager.from(getApplicationContext()).isActiveSubId(subId)) {                LogTag.debugD("SubId is not active:" + subId);                stopSelfIfIdle(serviceId);                return;            }            Bundle bundle = intent.getExtras();            bundle.putInt(ConstantsWrapper.Phone.SUBSCRIPTION_KEY, subId);            // For launching NotificationTransaction and test purpose.            TransactionBundle args = new TransactionBundle(bundle);            launchTransaction(serviceId, args, noNetwork);        }    }

 

   onNewIntent主要查询数据库对彩信进行一些操作,在底层,还没有研究

onNewIntent发送一个信息到Handelr里面进行操作

private void launchTransaction(int serviceId, TransactionBundle txnBundle, boolean noNetwork) {        if (noNetwork) {            Log.w(TAG, "launchTransaction: no network error!");            onNetworkUnavailable(serviceId, txnBundle.getTransactionType(),                    Uri.parse(txnBundle.getUri()), false);            return;        }        //设置手动现在数据        Message msg = mServiceHandler.obtainMessage(EVENT_TRANSACTION_REQUEST);//接收开始发送给NotificationTransation去接收短信       // Message msg = mServiceHandler.obtainMessage(Transaction.RETRIEVE_TRANSACTION);//接收开始发送给NotificationTransation去接收短信        msg.arg1 = serviceId;        msg.obj = txnBundle;        LogTag.debugD("launchTransaction: sending message " + msg);        mServiceHandler.sendMessage(msg);    }

在Handler里面启动   SendTransaction.java线程

 



SendTransaction.java主要操作进行调用父类的Transaction   ,我就全部复制了这个类很简单

/* * Copyright (C) 2007-2008 Esmertec AG. * Copyright (C) 2007-2008 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package com.android.mms.transaction;import android.content.ContentUris;import android.content.ContentValues;import android.content.Context;import android.database.sqlite.SqliteWrapper;import android.net.Uri;import android.provider.Telephony.Mms;import android.provider.Telephony.Mms.Sent;import android.text.TextUtils;import android.telephony.SubscriptionManager;import android.util.Log;import com.android.mms.LogTag;import com.android.mms.MmsApp;import com.android.mms.ui.MessageUtils;import com.android.mms.util.RateController;import com.android.mms.util.SendingProgressTokenManager;import com.google.android.mms.pdu.EncodedStringValue;import com.google.android.mms.pdu.PduComposer;import com.google.android.mms.pdu.PduHeaders;import com.google.android.mms.pdu.PduParser;import com.google.android.mms.pdu.PduPersister;import com.google.android.mms.pdu.SendConf;import com.google.android.mms.pdu.SendReq;import java.util.Arrays;/** * The SendTransaction is responsible for sending multimedia messages * (M-Send.req) to the MMSC server.  It: * * 
    *
  • Loads the multimedia message from storage (Outbox). *
  • Packs M-Send.req and sends it. *
  • Retrieves confirmation data from the server (M-Send.conf). *
  • Parses confirmation message and handles it. *
  • Moves sent multimedia message from Outbox to Sent. *
  • Notifies the TransactionService about successful completion. *
*/public class SendTransaction extends Transaction implements Runnable { private static final String TAG = LogTag.TAG; private Thread mThread; public final Uri mSendReqURI; public SendTransaction(Context context, int transId, TransactionSettings connectionSettings, String uri) { super(context, transId, connectionSettings); mSendReqURI = Uri.parse(uri); mId = uri; // Attach the transaction to the instance of RetryScheduler. attach(RetryScheduler.getInstance(context)); } /* * (non-Javadoc) * @see com.android.mms.Transaction#process() */ @Override public void process() { mThread = new Thread(this, "SendTransaction"); mThread.start(); } public void run() { try { RateController rateCtlr = RateController.getInstance(); if (rateCtlr.isLimitSurpassed() && !rateCtlr.isAllowedByUser()) { Log.e(TAG, "Sending rate limit surpassed."); return; } // Load M-Send.req from outbox PduPersister persister = PduPersister.getPduPersister(mContext); SendReq sendReq = (SendReq) persister.load(mSendReqURI); // Update the 'date' field of the PDU right before sending it. long date = System.currentTimeMillis() / 1000L; sendReq.setDate(date); // Persist the new date value into database. ContentValues values = new ContentValues(1); values.put(Mms.DATE, date); SqliteWrapper.update(mContext, mContext.getContentResolver(), mSendReqURI, values, null, null); // fix bug 2100169: insert the 'from' address per spec String lineNumber = MessageUtils.getLocalNumber(mSubId); Log.d(TAG, "lineNumber " + lineNumber); if (!TextUtils.isEmpty(lineNumber)) { sendReq.setFrom(new EncodedStringValue(lineNumber)); } // Pack M-Send.req, send it, retrieve confirmation data, and parse it long tokenKey = ContentUris.parseId(mSendReqURI); //sendReq 流在这个方法里面 PduComposer pdu = new PduComposer(mContext, sendReq); byte[] response = sendPdu(SendingProgressTokenManager.get(tokenKey), pdu.make(),mSendReqURI); SendingProgressTokenManager.remove(tokenKey); String respStr = new String(response); LogTag.debugD("[SendTransaction] run: send mms msg (" + mId + "), resp=" + respStr); SendConf conf = (SendConf) new PduParser(response, PduParserUtil.shouldParseContentDisposition()).parse(); if (conf == null) { Log.e(TAG, "No M-Send.conf received."); } // Check whether the responding Transaction-ID is consistent // with the sent one. byte[] reqId = sendReq.getTransactionId(); byte[] confId = conf.getTransactionId(); if (!Arrays.equals(reqId, confId)) { Log.e(TAG, "Inconsistent Transaction-ID: req=" + new String(reqId) + ", conf=" + new String(confId)); return; } // From now on, we won't save the whole M-Send.conf into // our database. Instead, we just save some interesting fields // into the related M-Send.req. values = new ContentValues(2); int respStatus = conf.getResponseStatus(); values.put(Mms.RESPONSE_STATUS, respStatus); if (respStatus != PduHeaders.RESPONSE_STATUS_OK) { SqliteWrapper.update(mContext, mContext.getContentResolver(), mSendReqURI, values, null, null); Log.e(TAG, "Server returned an error code: " + respStatus); return; } String messageId = PduPersister.toIsoString(conf.getMessageId()); values.put(Mms.MESSAGE_ID, messageId); SqliteWrapper.update(mContext, mContext.getContentResolver(), mSendReqURI, values, null, null); // Move M-Send.req from Outbox into Sent. Uri uri = persister.move(mSendReqURI, Sent.CONTENT_URI); mTransactionState.setState(TransactionState.SUCCESS); mTransactionState.setContentUri(uri); } catch (Throwable t) { Log.e(TAG, Log.getStackTraceString(t)); } finally { LogTag.debugD("[SendTransaction]remove cache:" + mSendReqURI); MmsApp.getApplication().getPduLoaderManager().removePdu(mSendReqURI); if (mTransactionState.getState() != TransactionState.SUCCESS) { mTransactionState.setState(TransactionState.FAILED); mTransactionState.setContentUri(mSendReqURI); Log.e(TAG, "Delivery failed."); } notifyObservers(); } } @Override public void abort() { Log.d(TAG, "markFailed = " + this); mTransactionState.setState(TransactionState.FAILED); mTransactionState.setContentUri(mSendReqURI); mFailReason = FAIL_REASON_CAN_NOT_SETUP_DATA_CALL; notifyObservers(); } @Override public int getType() { return SEND_TRANSACTION; }}

 

 



内容太多发布失败,分开发布    点击继续   

转载地址:https://liwangjiang.blog.csdn.net/article/details/88673812 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:Android短信开发 发送彩信 ‘ 高通源码 ‘ (彩信发送过程2)
下一篇:Android短信开发 发送短信 ' 高通源码 '(发送成功或发送失败改变状态)

发表评论

最新留言

留言是一种美德,欢迎回访!
[***.207.175.100]2024年05月02日 04时44分20秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章