本文共 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)) { ListcurrentNumberList = 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. *
内容太多发布失败,分开发布 点击继续
转载地址:https://liwangjiang.blog.csdn.net/article/details/88673812 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!