MMS发送流程(代码版)Android

liming0604 贡献于2014-07-23

作者 zhanghao  创建于2012-06-18 01:23:23   修改者liming0604  修改于2018-01-20 02:45:26字数22106

文档摘要:MMS发送流程(代码版)Android
关键词:

MMS发送流程(代码版) Android2.2packages/apps/Mms 1.      点击发送按钮Src/com/android/mms/ui/ComposeMessageActivity.java public void onClick(View v) {         if ((v == mSendButton) && isPreparedForSending()) {             confirmSendMessageIfNeeded(); //确认是否需要发送短信—-》         } }   2.src/com/android/mms/ui/ComposeMessageActivity.java private void confirmSendMessageIfNeeded() {         if (!isRecipientsEditorVisible()) {  //编辑联系人不可见时,也就是给已存在会话的联系人发送短信时             sendMessage(true);             return;         }           boolean isMms = mWorkingMessage.requiresMms();   //是否需要以彩信形式发送                 if (mRecipientsEditor.hasInvalidRecipient(isMms)) {//是否含有不合法的收件人             if (mRecipientsEditor.hasValidRecipient(isMms)) {//有合法的和不合法的,弹出尝试发送对话框                 String title = getResourcesString(R.string.has_invalid_recipient,                         mRecipientsEditor.formatInvalidNumbers(isMms));                 new AlertDialog.Builder(this)                    .setIcon(android.R.drawable.ic_dialog_alert)                     .setTitle(title)                     .setMessage(R.string.invalid_recipient_message)                    .setPositiveButton(R.string.try_to_send,                             newSendIgnoreInvalidRecipientListener())                    .setNegativeButton(R.string.no, new CancelSendingListener())                     .show();             } else {//如果全是不合法的联系人,提示不能发送信息                 new AlertDialog.Builder(this)                    .setIcon(android.R.drawable.ic_dialog_alert)                     .setTitle(R.string.cannot_send_message)                     .setMessage(R.string.cannot_send_message_reason)                    .setPositiveButton(R.string.yes, new CancelSendingListener())                     .show();             }         } else {//判断收件人没有问题,接着发送信息 --》             sendMessage(true);         } }   3. src/com/android/mms/ui/ComposeMessageActivity.java private void sendMessage(boolean bCheckEcmMode) {     Log.v(TAG, "sendMessage");         if (bCheckEcmMode) {             // TODO: expose this in telephony layer for SDK build             String inEcm = SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE);     //判断电话是否处于紧急拨号模式,得到的inEcm一般为空             Log.v(TAG, "inEcm = " + inEcm);             if (Boolean.parseBoolean(inEcm)) {                 try {                     startActivityForResult(                             new Intent(TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS,null),                             REQUEST_CODE_ECM_EXIT_DIALOG);                     return;                 } catch (ActivityNotFoundException e) {                     // continue to send message                     Log.e(TAG, "Cannot find EmergencyCallbackModeExitDialog", e);                 }             }         }           if (!mSendingMessage) {             // send can change the recipients. Make sure we remove the listeners firstand then add             // them back once the recipient list has settled.             removeRecipientsListeners();  //取消对收件人的监听             mWorkingMessage.send();   //发送信息—-》             mSentMessage = true;             mSendingMessage = true;             addRecipientsListeners(); //重新添加收件人监听         }         // But bail out if we are supposed to exit after the message is sent.         if (mExitOnSent) {//如果mExitOnSent为true,信息发送完成后退出Activity             finish();         }     }   4. src/com/android/mms/data/WorkingMessage.java /**      * Send this message over the network.  Will call back with onMessageSent() once      * it has been dispatched to the telephonystack.  This WorkingMessage object is      * no longer useful after this method hasbeen called.      */     public void send() {         if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {             LogTag.debug("send");         }           // Get ready to write to disk.         prepareForSave(true /* notify */);//主要做一下同步收件人和WorkingMessage,彩信时在准备其他一些东西           // We need the recipient list for both SMS and MMS.         final Conversation conv = mConversation;         String msgTxt = mText.toString();         Log.v(TAG, "msgText = " + msgTxt);         if (requiresMms()|| addressContainsEmailToMms(conv, msgTxt)) {             // 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;   //如果第一次发送,此时mmsUri为null,如果是重发,则是草稿箱的地址 mMessageUri =content://mms/drafts/1             final PduPersister persister = PduPersister.getPduPersister(mContext);               final SlideshowModel slideshow = mSlideshow;             final SendReq sendReq = makeSendReq(conv,mSubject);               // Do the dirty work of sending the message off of the main UI thread.             new Thread(new Runnable() {                 public void run() {                     // 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);                 }             }).start();         }else {             // Same rules apply as above.             final String msgText = mText.toString();//取出短消息             Log.v(TAG, "msgText = " + msgText);             new Thread(new Runnable() {                 public void run() {                     preSendSmsWorker(conv, msgText);//发送信息--》                 }             }).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;     }   5. src/com/android/mms/data/WorkingMessage.java private void sendMmsWorker(Conversation conv, Uri mmsUri, PduPersisterpersister, SlideshowModel slideshow, SendReq sendReq) {     Log.v(TAG, "sendMmsWorker");         // If user tries to send the message, it's a signal the inputtedtext is what they wanted.         UserHappinessSignals.userAcceptedImeText(mContext);           // First make sure we don't have too many outstanding unsent message.         Cursor cursor = null;         try {             cursor = SqliteWrapper.query(mContext, mContentResolver,                     Mms.Outbox.CONTENT_URI,MMS_OUTBOX_PROJECTION, null, null, null);             if (cursor != null) {//如果MMS_OUTBOX里有未发送的彩信,并且总的大小已经超过了彩信的最大限制,则取消此次发送,并存入草稿箱               Log.v(TAG, "query Mms.Outbox.CONTENT_URI is not empty");                 long maxMessageSize = MmsConfig.getMaxSizeScaleForPendingMmsAllowed()*                     MmsConfig.getMaxMessageSize();                 Log.v(TAG, "MmsConfig.getMaxSizeScaleForPendingMmsAllowed() =" + MmsConfig.getMaxSizeScaleForPendingMmsAllowed());                 Log.v(TAG, "MmsConfig.getMaxMessageSize()() = " + MmsConfig.getMaxMessageSize());                                 long totalPendingSize = 0;                 while (cursor.moveToNext()) {                     totalPendingSize +=cursor.getLong(MMS_MESSAGE_SIZE_INDEX);                     Log.v(TAG, "totalPendingSize = " + totalPendingSize);                 }                 if (totalPendingSize >= maxMessageSize) {                     unDiscard();    // itwasn't successfully sent. Allow it to be saved as a draft.                     mStatusListener.onMaxPendingMessagesReached();                     return;                 }             }else{               Log.v(TAG, "query Mms.Outbox.CONTENT_URI is empty");             }         } finally {             if (cursor != null) {                 cursor.close();             }         }         mStatusListener.onPreMessageSent();           // Make sure we are still using the correct thread ID for our         // recipient set.         long threadId = conv.ensureThreadId();           if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) {             LogTag.debug("sendMmsWorker: update draft MMS message " + mmsUri);         }           if (mmsUri == null) {//如果是首次发送,先把彩信保存入草稿箱             // Create a new MMS message if one hasn't been made yet.         Log.v(TAG, "mmsUri == null and startcreateDraftMmsMessage");             mmsUri = createDraftMmsMessage(persister,sendReq, slideshow);         } else {             // Otherwise, sync the MMS message in progress to disk.         Log.v(TAG, "mmsUri = " + mmsUri);         Log.v(TAG, "updateDraftMmsMessage");             updateDraftMmsMessage(mmsUri,persister, slideshow, sendReq);         }           // Be paranoid and clean any draft SMS up.         deleteDraftSmsMessage(threadId);           // 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;         }           MessageSender sender = new MmsMessageSender(mContext, mmsUri,                slideshow.getCurrentMessageSize());         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(mContext, mContentResolver, mmsUri, null, null);             }               // Make sure this thread isn't over the limits in message count             Recycler.getMmsRecycler().deleteOldMessagesByThreadId(mContext, threadId);         } catch (Exception e) {             Log.e(TAG, "Failed to send message: " + mmsUri + ",threadId=" + threadId, e);         }           mStatusListener.onMessageSent(); }   6.src/com/android/mms/transaction/MmsMessageSender.java public boolean sendMessage(long token) throws MmsException {         // Load the MMS from the message uri         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);           // Move the message into MMS Outbox         p.move(mMessageUri, Mms.Outbox.CONTENT_URI);           // Start MMS transaction service         SendingProgressTokenManager.put(ContentUris.parseId(mMessageUri), token);         mContext.startService(new Intent(mContext, TransactionService.class));           return true;     }   7.src/com/android/mms/transaction/TransactionService.java @Override     public int onStartCommand(Intent intent, int flags, int startId) {     Log.v(TAG, "onStartCommand");         if (intent == null) {             return Service.START_NOT_STICKY;         }         mConnMgr = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);         boolean noNetwork =!isNetworkAvailable();           if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {             Log.v(TAG, "onStart: #" + startId + ": " + intent.getExtras() + " intent=" + intent);             Log.v(TAG, "   networkAvailable=" + !noNetwork);         }         Log.v(TAG, "getAction is " + intent.getAction());         if (ACTION_ONALARM.equals(intent.getAction())|| (intent.getExtras() == null)) {         Log.v(TAG, "ACTION_ONALARM.equals(intent.getAction()) ||(intent.getExtras() == null)");             // Scan database to find all pending operations.             Cursor cursor = PduPersister.getPduPersister(this).getPendingMessages(                     System.currentTimeMillis());             if (cursor != null) {                 try {                     int count = cursor.getCount();                       if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {                         Log.v(TAG, "onStart: cursor.count=" + count);                     }                       if (count == 0) {                         if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {                             Log.v(TAG, "onStart: no pending messages. Stoppingservice.");                         }                         RetryScheduler.setRetryAlarm(this);                        stopSelfIfIdle(startId);                         return Service.START_NOT_STICKY;                     }                       int columnIndexOfMsgId =cursor.getColumnIndexOrThrow(PendingMessages.MSG_ID);                     int columnIndexOfMsgType =cursor.getColumnIndexOrThrow(                             PendingMessages.MSG_TYPE);                       if (noNetwork) {                         // Make sure we register for connection state changes.                         if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {                             Log.v(TAG, "onStart: registerForConnectionStateChanges");                         }                         MmsSystemEventReceiver.registerForConnectionStateChanges(                                getApplicationContext());                     }                       while (cursor.moveToNext()) {                         int msgType =cursor.getInt(columnIndexOfMsgType);                         int transactionType =getTransactionType(msgType);                         Log.v(TAG, "msgType = " + msgType);                         Log.v(TAG, "transactionType = " + transactionType);                         if (noNetwork) {                            onNetworkUnavailable(startId, transactionType);                             return Service.START_NOT_STICKY;                         }                                                 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.                                 int failureType =cursor.getInt(                                        cursor.getColumnIndexOrThrow(                                                PendingMessages.ERROR_TYPE));                                 if (!isTransientFailure(failureType)){                                     break;                                 }                                 // fall-through                             default:                                 Uri uri =ContentUris.withAppendedId(                                         Mms.CONTENT_URI,                                        cursor.getLong(columnIndexOfMsgId));                                TransactionBundle args = new TransactionBundle(                                        transactionType, uri.toString());                                 // FIXME: We use the same startId for all MMs.                                 launchTransaction(startId, args, false);                                 break;                         }                     }                 } finally {                     cursor.close();                 }             } else {                 if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {                     Log.v(TAG, "onStart: no pending messages. Stoppingservice.");                 }                 RetryScheduler.setRetryAlarm(this);                 stopSelfIfIdle(startId);             }         } else {             if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {                 Log.v(TAG, "onStart: launch transaction...");             }             // For launching NotificationTransaction and test purpose.             TransactionBundle args = newTransactionBundle(intent.getExtras());             launchTransaction(startId, args,noNetwork);         }         return Service.START_NOT_STICKY;     }   8. src/com/android/mms/transaction/TransactionService.java private void launchTransaction(int serviceId,TransactionBundle txnBundle, boolean noNetwork) {     Log.v(TAG, "launchTransaction");         if (noNetwork) {             Log.w(TAG, "launchTransaction: no network error!");             onNetworkUnavailable(serviceId,txnBundle.getTransactionType());             return;         }         Message msg = mServiceHandler.obtainMessage(EVENT_TRANSACTION_REQUEST);         msg.arg1 = serviceId;         msg.obj = txnBundle;           if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {             Log.v(TAG, "launchTransaction: sending message " + msg);         }         mServiceHandler.sendMessage(msg);     }   9. src/com/android/mms/transaction/TransactionService.java private final class ServiceHandler extends Handler {         public ServiceHandler(Looper looper) {             super(looper);         }           /**          * Handle incoming transactionrequests.          * The incoming requests are initiatedby the MMSC Server or by the          * MMS Client itself.          */         @Override         public void handleMessage(Messagemsg) {             if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {                 Log.v(TAG, "Handling incoming message: " + msg);             }               Transaction transaction = null;               switch (msg.what) {                 case EVENT_QUIT:                     getLooper().quit();                     return;                   case EVENT_CONTINUE_MMS_CONNECTIVITY:                     synchronized (mProcessing) {                         if (mProcessing.isEmpty()) {                             return;                         }                     }                       if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {                         Log.v(TAG, "handle EVENT_CONTINUE_MMS_CONNECTIVITYevent...");                     }                       try {                         int result =beginMmsConnectivity();                         if (result != Phone.APN_ALREADY_ACTIVE){                             Log.v(TAG, "Extending MMS connectivity returned " + result +                                     " instead of APN_ALREADY_ACTIVE");                             // Just wait for connectivity startup without                             // any newrequest of APN switch.                             return;                         }                     } catch (IOException e) {                         Log.w(TAG, "Attempt to extend use of MMS connectivityfailed");                         return;                     }                       // Restart timer                    sendMessageDelayed(obtainMessage(EVENT_CONTINUE_MMS_CONNECTIVITY),                                        APN_EXTENSION_WAIT);                     return;                   case EVENT_DATA_STATE_CHANGED:                     /*                      * If we are being informedthat connectivity has been established                      * to allow MMS traffic,then proceed with processing the pending                      * transaction, if any.                      */                     if (mConnectivityListener == null) {                         return;                     }                       NetworkInfo info = mConnectivityListener.getNetworkInfo();                     if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {                         Log.v(TAG, "Handle DATA_STATE_CHANGED event: " + info);                     }                       // Check availability of the mobile network.                     if ((info == null) || (info.getType() !=                            ConnectivityManager.TYPE_MOBILE_MMS)) {                         if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {                             Log.v(TAG, "   type isnot TYPE_MOBILE_MMS, bail");                         }                         return;                     }                       if (!info.isConnected()) {                         if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {                             Log.v(TAG, "  TYPE_MOBILE_MMS not connected, bail");                         }                         return;                     }                       TransactionSettings settings = newTransactionSettings(                             TransactionService.this,info.getExtraInfo());                       // If this APN doesn't have an MMSC, wait for one that does.                     if (TextUtils.isEmpty(settings.getMmscUrl())){                         if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {                             Log.v(TAG, "   empty MMSCurl, bail");                         }                         return;                     }                       // Set a timer to keep renewing our "lease" on the MMSconnection                    sendMessageDelayed(obtainMessage(EVENT_CONTINUE_MMS_CONNECTIVITY),                                        APN_EXTENSION_WAIT);                    processPendingTransaction(transaction, settings);                     return;                   case EVENT_TRANSACTION_REQUEST://响应请求                   Log.v(TAG, "EVENT_TRANSACTION_REQUEST");                     int serviceId = msg.arg1;                     try {                         TransactionBundle args= (TransactionBundle) msg.obj;                         TransactionSettingstransactionSettings;                           // Set the connection settings for this transaction.                         // If these have not been set in args, load thedefault settings.                         String mmsc =args.getMmscUrl();                         if (mmsc != null) {                             transactionSettings= new TransactionSettings(                                     mmsc,args.getProxyAddress(), args.getProxyPort());                         } else {                             transactionSettings= new TransactionSettings(                                                    TransactionService.this, null);                         }                           int transactionType =args.getTransactionType();                         Log.v(TAG, "transactionType = " + transactionType);                         if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {                             Log.v(TAG, "handle EVENT_TRANSACTION_REQUEST:transactionType=" +                                    transactionType);                         }                           // Create appropriate transaction                         switch (transactionType){                             case Transaction.NOTIFICATION_TRANSACTION:                                 String uri =args.getUri();                                 if (uri != null) {                                     transaction= new NotificationTransaction(                                            TransactionService.this, serviceId,                                            transactionSettings, uri);                                 } else {                                     // Now it's only used for test purpose.                                     byte[] pushData =args.getPushData();                                     PduParserparser = new PduParser(pushData);                                     GenericPdu ind= parser.parse();                                       int type = PduHeaders.MESSAGE_TYPE_NOTIFICATION_IND;                                     if ((ind != null) &&(ind.getMessageType() == type)) {                                         transaction = newNotificationTransaction(                                                TransactionService.this, serviceId,                                                transactionSettings, (NotificationInd) ind);                                     } else {                                         Log.e(TAG, "Invalid PUSH data.");                                        transaction = null;                                         return;                                     }                                 }                                 break;                             case Transaction.RETRIEVE_TRANSACTION:                                 transaction = newRetrieveTransaction(                                        TransactionService.this, serviceId,                                        transactionSettings, args.getUri());                                 break;                             case Transaction.SEND_TRANSACTION://根据transactiontype响应发送彩信                                 Log.v(TAG, "Transaction.SEND_TRANSACTION");                                 transaction = new SendTransaction(                                        TransactionService.this, serviceId,                                        transactionSettings, args.getUri());                                 break;                             case Transaction.READREC_TRANSACTION:                                 transaction = newReadRecTransaction(                                         TransactionService.this, serviceId,                                        transactionSettings, args.getUri());                                 break;                             default:                                 Log.w(TAG, "Invalidtransaction type: " + serviceId);                                 transaction = null;                                 return;                         }                           if (!processTransaction(transaction)) {                             transaction = null;                             return;                         }                           if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {                             Log.v(TAG, "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) {                             if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {                                 Log.v(TAG, "Transaction was null. Stopping self: " + serviceId);                             }                            endMmsConnectivity();                            stopSelf(serviceId);                         }                     }                     return;                 case EVENT_HANDLE_NEXT_PENDING_TRANSACTION:                    processPendingTransaction(transaction, (TransactionSettings) msg.obj);                     return;                 default:                     Log.w(TAG, "what=" + msg.what);                     return;             }         }   10. src/com/android/mms/transaction/TransactionService.java /**          * Internal method to begin processinga transaction.          * @param transaction the transaction. Must not be{@code null}.          * @return {@code true} if process hasbegun or will begin. {@code false}          * if the transaction should bediscarded.          * @throws IOException if connectivityfor MMS traffic could not be          * established.          */         private boolean processTransaction(Transaction transaction) throws IOException {             // Check if transaction already processing         Log.v(TAG, "processTransaction");             synchronized (mProcessing) {                 for (Transaction t : mPending) {                     if (t.isEquivalent(transaction)) {                         if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {                             Log.v(TAG, "Transaction already pending: " +                                    transaction.getServiceId());                         }                         return true;                     }                 }                 for (Transaction t : mProcessing) {                     if (t.isEquivalent(transaction)) {                         if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {                             Log.v(TAG, "Duplicated transaction: " + transaction.getServiceId());                         }                         return true;                     }                 }                   /*                 * Make sure that the networkconnectivity necessary                 * for MMS traffic is enabled.If it is not, we need                 * to defer processing thetransaction until                 * connectivity is established.                 */                 if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {                     Log.v(TAG, "processTransaction: callbeginMmsConnectivity...");                 }                 int connectivityResult = beginMmsConnectivity();                 if (connectivityResult == Phone.APN_REQUEST_STARTED){                     mPending.add(transaction);                     if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {                         Log.v(TAG, "processTransaction: connResult=APN_REQUEST_STARTED," +                                 "defer transaction pending MMS connectivity");                     }                     return true;                 }                   if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {                     Log.v(TAG, "Adding transaction to 'mProcessing' list: " + transaction);                 }                 mProcessing.add(transaction);             }               // Set a timer to keep renewing our "lease" on the MMSconnection             sendMessageDelayed(obtainMessage(EVENT_CONTINUE_MMS_CONNECTIVITY),                                APN_EXTENSION_WAIT);               if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {                 Log.v(TAG, "processTransaction: starting transaction " + transaction);             }               // Attach to transaction and process it            transaction.attach(TransactionService.this);             transaction.process();             return true;         }   11.src/com/android/mms/transaction/SendTransaction.java @Override     public void process() {     Log.v(TAG, "process");         mThread = new Thread(this);         mThread.start();     }   12. src/com/android/mms/transaction/SendTransaction.java public void run() {     Log.v(TAG, "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();             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);             byte[] response = sendPdu(SendingProgressTokenManager.get(tokenKey),                                       new PduComposer(mContext,sendReq).make());//发送彩信             SendingProgressTokenManager.remove(tokenKey);               if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {                 String respStr = new String(response);                 Log.d(TAG, "[SendTransaction] run: send mms msg (" + mId + "),resp=" + respStr);             }               SendConf conf = (SendConf)new PduParser(response).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 {             if (mTransactionState.getState() != TransactionState.SUCCESS) {                 mTransactionState.setState(TransactionState.FAILED);                 mTransactionState.setContentUri(mSendReqURI);                 Log.e(TAG, "Delivery failed.");             }             notifyObservers();         }     }   13.src/com/android/mms/transaction/Transaction.java /**      * A common method to send a PDU to MMSC.      *      * @param token The token to identify the sendingprogress.      * @param pdu A byte array which contains the dataof the PDU.      * @return A byte array which containsthe response data.      *        If an HTTP error code is returned, an IOException will be thrown.      * @throws IOException if any erroroccurred on network interface or      *        an HTTP error code(>=400) returned from the server.      */     protected byte[] sendPdu(long token, byte[]pdu) throws IOException {         return sendPdu(token, pdu, mTransactionSettings.getMmscUrl());     }   14. src/com/android/mms/transaction/Transaction.java protected byte[] sendPdu(long token, byte[] pdu, StringmmscUrl) throws IOException {         ensureRouteToHost(mmscUrl, mTransactionSettings);         return HttpUtils.httpConnection(                 mContext, token,                 mmscUrl,                 pdu, HttpUtils.HTTP_POST_METHOD,                 mTransactionSettings.isProxySet(),                 mTransactionSettings.getProxyAddress(),                 mTransactionSettings.getProxyPort());//通过网络发送彩信,AP层的最后实现     }

下载文档到电脑,查找使用更方便

文档的实际排版效果,会与网站的显示效果略有不同!!

需要 2 金币 [ 分享文档获得金币 ] 0 人已下载

下载文档