标签:des android style class code tar
当准备工作(添加附件,输入文本内容)完成之后,我们这里开始进行该流程分析的第二阶段,也就是发送彩信。这里我们从ComposeMessageActivity类的点击发送按钮(mSendButtonMms)的点击事件开始:<TAG 1-1>
@Override
public void onClick(View v) {
if (mShowTwoButtons && (v == mSendButtonSmsViewSec || v == mSendButtonMmsViewSec)
&& isPreparedForSending()) {
confirmSendMessageIfNeeded(MSimConstants.SUB2);
} else if ((v == mSendButtonSms || v == mSendButtonMms) && isPreparedForSending()) {
if (mShowTwoButtons) {
confirmSendMessageIfNeeded(MSimConstants.SUB1);
} else {
confirmSendMessageIfNeeded();
}
} else if ((v == mRecipientsPicker)) {
launchMultiplePhonePicker();
} else if ((v == mRecipientsPickerGroups)) {
launchContactGroupPicker();
} else if (v == mAttachButton) {
showAddAttachmentDialog(false);
}
}
上述<TAG 1-1>调用了confirmSendMessageIfNeeded方法,这里对收件人(mRecipientEditor)进行了一些处理;<TAG 1-2>
private void confirmSendMessageIfNeeded() {
boolean isMms = mWorkingMessage.requiresMms();
if (!isRecipientsEditorVisible()) {
if (MessageUtils.isMobileDataDisabled(this) &&
MessageUtils.CAN_SETUP_MMS_DATA && isMms) {
showMobileDataDisabledDialog();
} else if (MSimTelephonyManager.getDefault().isMultiSimEnabled()) {
sendMsimMessage(true);
} else {
sendMessage(true);
}
return;
}
if (mRecipientsEditor.hasInvalidRecipient(isMms)) {
showInvalidRecipientDialog();
} else if (MessageUtils.isMobileDataDisabled(this) &&//判断数据连接是否正常
MessageUtils.CAN_SETUP_MMS_DATA && isMms) {
showMobileDataDisabledDialog();
} else {
// The recipients editor is still open. Make sure we use what‘s showing there
// as the destination.
ContactList contacts = mRecipientsEditor.constructContactsFromInput(false);
mDebugRecipients = contacts.serialize();
if (MSimTelephonyManager.getDefault().isMultiSimEnabled()) {
sendMsimMessage(true);
} else {
sendMessage(true);
}
}
}
上述代码<TAG 1-2>中,调用了ComposeMessageActivity类的sendMessage方法;<TAG 1-3>
private void sendMessage(boolean bCheckEcmMode) {
// Check message size, if >= max message size, do not send message.
if(checkMessageSizeExceeded()){
return;
}
// If message is sent make the mIsMessageChanged is true
// when activity is from SearchActivity.
mIsMessageChanged = mIsFromSearchActivity;
if (bCheckEcmMode) {
// TODO: expose this in telephony layer for SDK build
String inEcm = SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE);
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) {
if (LogTag.SEVERE_WARNING) {
String sendingRecipients = mConversation.getRecipients().serialize();
if (!sendingRecipients.equals(mDebugRecipients)) {
String workingRecipients = mWorkingMessage.getWorkingRecipients();
if (!mDebugRecipients.equals(workingRecipients)) {
LogTag.warnPossibleRecipientMismatch("ComposeMessageActivity.sendMessage" +
" recipients in window: \"" +
mDebugRecipients + "\" differ from recipients from conv: \"" +
sendingRecipients + "\" and working recipients: " +
workingRecipients, this);
}
}
sanityCheckConversation();
}
// send can change the recipients. Make sure we remove the listeners first and then add
// them back once the recipient list has settled.
removeRecipientsListeners();
if (mWorkingMessage.getResendMultiRecipients()) {
//if resend sms recipient is more than one, use mResendSmsRecipient
mWorkingMessage.send(mResendSmsRecipient);
} else {
mWorkingMessage.send(mDebugRecipients);
}
mSentMessage = true;
mSendingMessage = true;
addRecipientsListeners();
mScrollOnSend = true; // in the next onQueryComplete, scroll the list to the end.
}
// But bail out if we are supposed to exit after the message is sent.
if (mSendDiscreetMode) {
finish();
}
}
上述代码<TAG 1-3>中,调用了WorkingMessage类中的send()方法;<TAG 1-4>
public void send(final String recipientsInUI) {
long origThreadId = mConversation.getThreadId();
if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {
LogTag.debug("send origThreadId: " + origThreadId);
}
removeSubjectIfEmpty(true /* notify */);//这里判断当前彩信中的主题是否为空,如果为空则移除主题
// Get ready to write to disk.
prepareForSave(true /* notify */);
// We need the recipient list for both SMS and MMS.
final Conversation conv = mConversation;
String msgTxt = mText.toString();
if (requiresMms() || addressContainsEmailToMms(conv, msgTxt)) {
// 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;
if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {
LogTag.debug("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();
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;
}
上述代码<TAG 1-4>中,生成了彩信的可发送的Pdu—SendReq,接着调用了sendMmsWorker(),接着会把彩信写入数据库,把要发送的SendReq也会写入数据库,后面会再从数据库中读取出SendReq,并标识为草稿;然后会构建MmsMessageSender,传入收信人和彩信的Uri,让其发送。这期间也会回调UI一次,以初始化收信人编辑框和信息编辑框。<TAG
1-5>
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();
if (contactList != null) {
String[] numbers = contactList.getNumbers();
String[] forward = conv.getForwardRecipientNumber();
if (numbers != null && forward != null
&& (numbers.length == forward.length)) {
List<String> currentNumberList = Arrays.asList(numbers);
List<String> 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);
}
}
}
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);
}
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 (MSimTelephonyManager.getDefault().isMultiSimEnabled()) {
values.put(Mms.SUB_ID, mCurrentConvSub);
} else {
values.put(Mms.SUB_ID, MSimTelephonyManager.getDefault().getPreferredDataSubscription());
}
SqliteWrapper.update(mActivity, mContentResolver, mmsUri, values, null, null);
MessageSender sender = new MmsMessageSender(mActivity, mmsUri,
slideshow.getCurrentMessageSize(), mCurrentConvSub);
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);
}
// After send mms, this thread should‘t have draft left.
// Be paranoid and clean any draft MMS up.
deleteDraftMmsMessage(threadId);
// 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);
updateSearchResult();
}
上述代码<TAG 1-5>中,创建MmsMessageSender实例并调用了sendMessage()方法;MmsMessageSender先从数据库中读出彩信发送的Pdu—SendReq,Google的内置包com.google.android.mms.*;里面封装了所有操作Pdu的方法,包括把Pdu写入数据库(PduPersister.persist()),从数据库中读取生成Pdu(PduPersister.load())。然后根据当前彩信的配置和其他信息对SendReq进行更新,比如设置Expiration,Priority,Date和Size等,把彩信移到Outbox,然后启动TransactionService来处理彩信。sendMessage()就此返回。WorkingMessage会再次回调UI的接口,因为此时彩信已被在数据库中,所以UI会刷新信息列表,显示刚刚的彩信,这时的状态应该是正在发送中。
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.SUB_ID, mSubscription); //destination sub id
intent.putExtra(MultiSimUtility.ORIGIN_SUB_ID,
MultiSimUtility.getCurrentDataSubscription(mContext));
if (MSimTelephonyManager.getDefault().isMultiSimEnabled()) {
Intent silentIntent = new Intent(mContext,
com.android.mms.ui.SelectMmsSubscription.class);
silentIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
silentIntent.putExtras(intent); //copy all extras
mContext.startService(silentIntent);
} else {
mContext.startService(intent);
}
return true;
}
深度分析:Android4.3下MMS发送到附件为音频文件(音频为系统内置音频)的彩信给自己,添加音频-发送彩信-接收彩信-下载音频附件-预览-播放(二,发送彩信<1>),布布扣,bubuko.com
深度分析:Android4.3下MMS发送到附件为音频文件(音频为系统内置音频)的彩信给自己,添加音频-发送彩信-接收彩信-下载音频附件-预览-播放(二,发送彩信<1>)
标签:des android style class code tar
原文地址:http://blog.csdn.net/huangyabin001/article/details/29204995