为了正常的体验网站,请在浏览器设置里面开启Javascript功能!

51CTO下载-Android彩信发送介绍

2018-01-07 18页 doc 44KB 15阅读

用户头像

is_833902

暂无简介

举报
51CTO下载-Android彩信发送介绍51CTO下载-Android彩信发送介绍 Android彩信发送介绍 这篇写彩信发送过程。 我想追踪的内容是:用户按下发送之后,彩信的图片阿数据阿文件阿,是怎么包装起来,最后发送出去。 按我看源码的先后顺序来写了。 写完可能最后整理下。 1. com.Android.mms.data.WorkingMessage.Java 类 send()函数。 注释如下: /** * Send this message over the network. Will call back with onMessageSent(...
51CTO下载-Android彩信发送介绍
51CTO下载-Android彩信发送介绍 Android彩信发送介绍 这篇写彩信发送过程。 我想追踪的内容是:用户按下发送之后,彩信的图片阿数据阿文件阿,是怎么包装起来,最后发送出去。 按我看源码的先后顺序来写了。 写完可能最后整理下。 1. com.Android.mms.data.WorkingMessage.Java 类 send()。 注释如下: /** * Send this message over the network. Will call back with onMessageSent() * once it has been dispatched to the telephony stack. This WorkingMessage * object is no longer useful after this method has been called. */ 这个是2.1的源码 Java代码 1. public void send() { 2. if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) { 3. LogTag.debug("send"); 4. } 5. 6. // Get ready to write to disk. 7. prepareForSave(true /* notify */); 8. 9. // We need the recipient list for both SMS and MMS. 10. final Conversation conv = mConversation; 11. String msgTxt = mText.toString(); 12. 13. if (requiresMms() || addressContainsEmailToMms(conv, msgTx t)) { 14. // Make local copies of the bits we need for sending a messag e, 15. // because we will be doing it off of the main thread, which wil l 16. // immediately continue on to resetting some of this state. 17. final Uri mmsUri = mMessageUri; 18. final PduPersister persister = PduPersister 19. .getPduPersister(mContext); 20. 21. final SlideshowModel slideshow = mSlideshow; 22. final SendReq sendReq = makeSendReq(conv, mSubject); 23. 24. // Make sure the text in slide 0 is no longer holding onto a 25. // reference to the text 26. // in the message text box. 27. slideshow.prepareForSend(); 28. 29. // Do the dirty work of sending the message off of the main U I 30. // thread. 31. new Thread(new Runnable() { 32. public void run() { 33. sendMmsWorker(conv, mmsUri, persister, slideshow, sen dReq); 34. } 35. }).start(); 36. } else { 37. // Same rules apply as above. 38. final String msgText = mText.toString(); 39. new Thread(new Runnable() { 40. public void run() { 41. sendSmsWorker(conv, msgText); 42. } 43. }).start(); 44. } 45. 46. // update the Recipient cache with the new to address, if it's differ ent 47. RecipientIdCache 48. .updateNumbers(conv.getThreadId(), conv.getRecipients ()); 49. 50. // Mark the message as discarded because it is "off the market" af ter 51. // being sent. 52. mDiscarded = true; 53. } 粗浅的解说一下, (1) prapareForSave. 先确保有slidshow,也就是实质内容。 确保文字已拷贝。确保标题。 (2a) 根据消息分类,如果是短信直接起一个线程,跑sendSmsWorker函数,发送短信 (2b) 如果是彩信,先跑这么个函数,确保文本信息 // Make sure the text in slide 0 is no longer holding onto a // reference to the text // in the message text box. slideshow.prepareForSend(); TheCranberriers(卡百利)的歌真好听。 然后起一个线程,单独跑sendMmsWorker函数,后文有介绍。 彩信比sms麻烦很多。从sendMmsWorker函数的参数就可以看出来:(conv, mmsUri, persister, slideshow, sendReq) 上下文,uri,PduPersister(彩信是用pdu的),slideshow包含了所有的彩信信息,sendreq包含了mime封装mms时的headers(在我的剥壳彩信2里面有提到)。包括了 ContentType("application/vnd.wap.multipart.related" ,from,to等信息 。 (3)。 不管是短信还是彩信,起了那俩个worker函数之一就算发送信息成功了。 最后修改Recipient cache, 重置标志位,过程就结束了。 2。函数 sendMmsWorker Java代码 1. private void sendMmsWorker(Conversation conv, Uri mmsUri, 2. PduPersister persister, SlideshowModel slideshow, SendReq sen dReq) { 3. // First make sure we don't have too many outstanding unsent me ssage. 4. Cursor cursor = null; 5. try { 6. Log.d("GN@@@","mContext: "+mContext.toString()); 7. Log.d("GN@@@","mContentResolver: "+mContentResolver.toS tring()); 8. Log.d("GN@@@","Mms.Outbox.CONTENT_URI: "+Mms.Outbox. CONTENT_URI.toString()); 9. 10. cursor = SqliteWrapper.query(mContext, mContentResolve r, 11. Mms.Outbox.CONTENT_URI, MMS_OUTBOX_PROJECTIO N, null, null, 12. null); 13. if (cursor != null) { 14. long maxMessageSize = MmsConfig 15. .getMaxSizeScaleForPendingMmsAllowed() 16. * MmsConfig.getMaxMessageSize(); 17. long totalPendingSize = 0; 18. while (cursor.moveToNext()) { 19. totalPendingSize += cursor.getLong(MMS_MESSAGE_SIZ E_INDEX); 20. } 21. if (totalPendingSize >= maxMessageSize) { 22. unDiscard(); // it wasn't successfully sent. Allow it to b e 23. // saved as a draft. 24. mStatusListener.onMaxPendingMessagesReached(); 25. return; 26. } 27. } 28. } finally { 29. if (cursor != null) { 30. cursor.close(); 31. } 32. } 33. mStatusListener.onPreMessageSent(); 34. 35. // Make sure we are still using the correct thread ID for our 36. // recipient set. 37. long threadId = conv.ensureThreadId(); 38. 39. if (Log.isLoggable(LogTag.APP, Log.VERBOSE)) { 40. LogTag.debug("sendMmsWorker: update draft MMS messag e " + mmsUri); 41. } 42. 43. if (mmsUri == null) { 44. // Create a new MMS message if one hasn't been made yet. 45. mmsUri = createDraftMmsMessage(persister, sendReq, slidesho w); 46. } else { 47. // Otherwise, sync the MMS message in progress to disk. 48. updateDraftMmsMessage(mmsUri, persister, slideshow, sendRe q); 49. } 50. 51. // Be paranoid and clean any draft SMS up. 52. deleteDraftSmsMessage(threadId); 53. 54. MessageSender sender = new MmsMessageSender(mContext, mm sUri, slideshow 55. .getCurrentMessageSize()); 56. try { 57. if (!sender.sendMessage(threadId)) { 58. // The message was sent through SMS protocol, we shoul d 59. // delete the copy which was previously saved in MMS draft s. 60. SqliteWrapper.delete(mContext, mContentResolver, mmsUr i, null, 61. null); 62. } 63. 64. // Make sure this thread isn't over the limits in message coun t 65. Recycler.getMmsRecycler().deleteOldMessagesByThreadId(mCo ntext, 66. threadId); 67. } catch (Exception e) { 68. Log.e(TAG, "Failed to send message: " + mmsUri + ", threadId =" 69. + threadId, e); 70. } 71. 72. mStatusListener.onMessageSent(); 73. } 依旧是粗浅的解说: a )前面挺长一段代码,检查这个对话(conversation)之前还有没有未发送的信息,uri是Mms.Outbox.CONTENT_URI。 这里需要提到一下MessageStatusListener,这个Interface接口实现在 WorkingMessage.java里,而短信类的主题ComposeMessageActivity.java实现了这个接口,所以前者在一些状态改变的时候可以很方便的调用后者的一些函数,作相应的改动。主要是:onProtocolChanged彩信短信互切换,onAttachmentChanged福建改变,onPreMessageSent发消息前,onMessageSent发消息后。 b) 当然,这里调用了onPreMessageSent这个监听函数, 然后ComposeMessageActivity 就会调用resetMessage函数 ,这个函数会调整显示,focus,软键盘等等。 c) 然后检查mmsUri。如果这个uri是空的话,直接造一个新的uri继续发送。这个真是让我叫亚灭爹。因为一开始不知道 这个createDraftMmsMessage(persister, sendReq, slideshow);函数可以包含所有发送需要的信息,以为这么发出去太可怕了。 如果uri不为空。 调用的是updateDraftMmsMessage(mmsUri, persister, slideshow, sendReq); 总之功能是,把这个将发送的mms,存disk了,也就是存draft了。为什么要发送还要存draft呢,后面另会说,因为这个是我写这个文章前想要找的东西。。。这个过程 还有一些信息写道mmsUri了。所以之后mmsUri就可以代将发送的mms的全部信息。 d)deleteDraftSmsMessage 删除草稿 e)创建一个MmsMessageSender,用这个sender来调用sendMessage函数 可以猜到的,Sms那边是SmsMessageSender,同样调用sendMessage函数 通过这里之后,短信已经真的发掉了。 这个类后面有介绍。 f)这里这个if相当搞笑,按正常流程下来,按理这里本来这里是一个彩信的发送,然后有一些数据在draft数据库,会在上面的流程中被移到send数据库。 但是搞笑的地方来了:因为忽然发现函数返回值表示刚刚发送出去的其实是一个短信sms,而已。于是要把数据库里存着的draft删掉。 我也不知道这个if里面的情况会不会发生,反正源码是这么写的,我只管不负责任直译。。。 g)调用onMessageSent这个监听函数。调用ComposeMessageActivity的onMessageSent,这个函数功能是重新显示conversation list。 3 MmsMessageSender.java类。在mms/transaction下面。实现了MessageSender接口。这个接口只有一个事儿,就是sendMessage并返回boolean的值。弱发送的是mms,返回true。若发送的是sms,返回false。出错返回啥,exception。 我最先想要追踪的发送流程也在这里了。贴一些代码 Java代码 1. public MmsMessageSender(Context context, Uri location, long mess ageSize) { 2. mContext = context; 3. mMessageUri = location; 4. mMessageSize = messageSize; 5. 6. if (mMessageUri == null) { 7. throw new IllegalArgumentException("Null message URI. "); 8. } 9. } 10. 11. 12. Java代码 13. public boolean sendMessage(long token) throws MmsExceptio n { 14. // Load the MMS from the message uri 15. PduPersister p = PduPersister.getPduPersister(mContext); 16. GenericPdu pdu = p.load(mMessageUri); 17. 18. if (pdu.getMessageType() != PduHeaders.MESSAGE_TYPE_SEND_ REQ) { 19. throw new MmsException("Invalid message: " + pdu.getMessa geType()); 20. } 21. 22. SendReq sendReq = (SendReq) pdu; 23. 24. // Update headers. 25. updatePreferencesHeaders(sendReq); 26. 27. // MessageClass. 28. sendReq.setMessageClass(DEFAULT_MESSAGE_CLASS.getBytes ()); 29. 30. // Update the 'date' field of the message before sending it. 31. sendReq.setDate(System.currentTimeMillis() / 1000L); 32. 33. sendReq.setMessageSize(mMessageSize); 34. 35. p.updateHeaders(mMessageUri, sendReq); 36. 37. // Move the message into MMS Outbox 38. p.move(mMessageUri, Mms.Outbox.CONTENT_URI); 39. 40. // Start MMS transaction service 41. SendingProgressTokenManager 42. .put(ContentUris.parseId(mMessageUri), token); 43. mContext.startService(new Intent(mContext, TransactionService. class)); 44. 45. return true; 46. } 47. 解说: 现从PduPersister那里拿数据,包括需要拼装的发送报头和需要发送的数据信息。 然后把要发送的信息相关数据从数据库的draft那里转移到send,表示已经发送。 最后起一个TransactionService服务,这个服务也是从PduPersister里找,找到需要发送的数据,并通过不同的用户网络送出去。 这块我猜一般人都没有改的需求。。 4. createDraftMmsMessage(persister, sendReq, slideshow); 和 updateDraftMmsMessage(mmsUri, persister, slideshow, sendReq); 这两个函数 刨掉 try catch , createDraftMmsMessage 函数大概有这么几句: 1. Java代码 2. PduBody pb = slideshow.toPduBody(); 3. sendReq.setBody(pb); 4. Uri res = persister.persist(sendReq, Mms.Draft.CONTENT_URI); 5. slideshow.sync(pb); 6. 7. updateDraftMmsMessage 函数大概有这么几句: 8. Java代码 9. persister.updateHeaders(uri, sendReq); 10. final PduBody pb = slideshow.toPduBody(); 11. persister.updateParts(uri, pb); 12. slideshow.sync(pb); 13. 两个函数从本质上讲是一样的:把附件的东西以pdubody的形式存下来,另外就是更新uri。 什么叫PduBody呢, 厉害了。就是n个PduPart。什么叫PduPart呢,厉害了,就是数据库里的那个Part~ 那个part是什么, 那个最厉害了。数据库里的PART_1234455这种数据,文件名代表创建时间(在mediaModel产生时就进系统了),导出来就是源文件,比如图片文件,改个jpg就可以看了。 sync函数不怎么动,无责任解说:把每个slide里面每个媒体跟真实文件位置对应上。 slideshow.toPduBody();里面,用SMILDocument mDocumentCache; 调用到SlideshowModel.java的 Java代码 1. ,,其中context,null。 isMakingCopy,false。 document,mDocume ntCache 2. private PduBody makePduBody(Context context, SMILDocument d ocument, 3. boolean isMakingCopy) { 4. PduBody pb = new PduBody(); 5. 6. boolean hasForwardLock = false; 7. for (SlideModel slide : mSlides) { 8. for (MediaModel media : slide) { 9. if (isMakingCopy) { 10. if (media.isDrmProtected() && !media.isAllowedToForw ard()) { 11. hasForwardLock = true; 12. continue; 13. } 14. } 15. 16. PduPart part = new PduPart(); 17. 18. if (media.isText()) { 19. TextModel text = (TextModel) media; 20. // Don't create empty text part. 21. if (TextUtils.isEmpty(text.getText())) { 22. continue; 23. } 24. // Set Charset if it's a text media. 25. part.setCharset(text.getCharset()); 26. } 27. 28. // Set Content-Type. 29. part.setContentType(media.getContentType().getBytes ()); 30. 31. String src = media.getSrc(); 32. String location; 33. boolean startWithContentId = src.startsWith("cid:"); 34. if (startWithContentId) { 35. location = src.substring("cid:".length()); 36. } else { 37. location = src; 38. } 39. 40. // Set Content-Location. 41. part.setContentLocation(location.getBytes()); 42. 43. // Set Content-Id. 44. if (startWithContentId) { 45. // Keep the original Content-Id. 46. part.setContentId(location.getBytes()); 47. } else { 48. int index = location.lastIndexOf("."); 49. String contentId = (index == -1) ? location : locatio n 50. .substring(0, index); 51. part.setContentId(contentId.getBytes()); 52. } 53. 54. if (media.isDrmProtected()) { 55. DrmWrapper wrapper = media.getDrmObject(); 56. part.setDataUri(wrapper.getOriginalUri()); 57. part.setData(wrapper.getOriginalData()); 58. } else if (media.isText()) { 59. part.setData(((TextModel) media).getText().getBytes ()); 60. } else if (media.isImage() || media.isVideo() 61. || media.isAudio()) { 62. part.setDataUri(media.getUri()); 63. } else { 64. Log.w(TAG, "Unsupport media: " + media); 65. } 66. 67. pb.addPart(part); 68. } 69. } 70. 71. if (hasForwardLock && isMakingCopy && context != null) { 72. Toast.makeText(context, 73. context.getString(R.string.cannot_forward_drm_ob j), 74. Toast.LENGTH_LONG).show(); 75. document = SmilHelper.getDocument(pb); 76. } 77. 78. // Create and insert SMIL part(as the first part) into the PduBo dy. 79. ByteArrayOutputStream out = new ByteArrayOutputStream (); 80. SmilXmlSerializer.serialize(document, out); 81. PduPart smilPart = new PduPart(); 82. smilPart.setContentId("smil".getBytes()); 83. smilPart.setContentLocation("smil.xml".getBytes()); 84. smilPart.setContentType(ContentType.APP_SMIL.getBytes ()); 85. smilPart.setData(out.toByteArray()); 86. pb.addPart(0, smilPart); 87. 88. return pb; 89. }
/
本文档为【51CTO下载-Android彩信发送介绍】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索