彩信发送

本文详细解析了Android系统中彩信的发送流程,从用户点击发送按钮开始,介绍如何准备彩信内容、打包成PDU格式并通过网络发送出去。涵盖了WorkingMessage类的send方法、sendMmsWorker函数以及MmsMessageSender类的工作原理。
摘要由CSDN通过智能技术生成

彩信发送。

转自:http://gnibre.javaeye.com/blog/645655

 

我想追踪的内容是:用户按下发送之后,彩信的图片阿数据阿文件阿,是怎么包装起来,最后发送出去。

按我看源码的先后顺序来写了。 写完可能最后整理下。

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, msgTxt)) {  
  14.         // Make local copies of the bits we need for sending a message,   
  15.         // because we will be doing it off of the main thread, which will   
  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 UI   
  30.         // thread.   
  31.         new  Thread( new  Runnable() {  
  32.             public   void  run() {  
  33.                 sendMmsWorker(conv, mmsUri, persister, slideshow, sendReq);  
  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 different   
  47.     RecipientIdCache  
  48.             .updateNumbers(conv.getThreadId(), conv.getRecipients());  
  49.   
  50.     // Mark the message as discarded because it is "off the market" after   
  51.     // being sent.   
  52.     mDiscarded = true ;  
  53. }  
    public void send() {
        if (Log.isLoggable(LogTag.TRANSACTION, Log.VERBOSE)) {
            LogTag.debug("send");
        }

        // 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)) {
            // 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(mContext);

            final SlideshowModel slideshow = mSlideshow;
            final SendReq sendReq = makeSendReq(conv, mSubject);

            // Make sure the text in slide 0 is no longer holding onto a
            // reference to the text
            // in the message text box.
            slideshow.prepareForSend();

            // Do the dirty work of sending the message off of the main UI
            // thread.
            new Thread(new Runnable() {
                public void run() {
                    sendMmsWorker(conv, mmsUri, persister, slideshow, sendReq);
                }
            }).start();
        } else {
            // Same rules apply as above.
            final String msgText = mText.toString();
            new Thread(new Runnable() {
                public void run() {
                    sendSmsWorker(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;
    }


粗浅的解说一下,
(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 sendReq) {  
  3.     // First make sure we don't have too many outstanding unsent message.   
  4.     Cursor cursor = null ;  
  5.     try  {  
  6.         Log.d("GN@@@" , "mContext:  " +mContext.toString());  
  7.         Log.d("GN@@@" , "mContentResolver:  " +mContentResolver.toString());  
  8.         Log.d("GN@@@" , "Mms.Outbox.CONTENT_URI:  " +Mms.Outbox.CONTENT_URI.toString());  
  9.           
  10.         cursor = SqliteWrapper.query(mContext, mContentResolver,  
  11.                 Mms.Outbox.CONTENT_URI, MMS_OUTBOX_PROJECTION, nullnull ,  
  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_SIZE_INDEX);  
  20.             }  
  21.             if  (totalPendingSize >= maxMessageSize) {  
  22.                 unDiscard(); // it wasn't successfully sent. Allow it to be   
  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 message "  + 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, slideshow);  
  46.     } else  {  
  47.         // Otherwise, sync the MMS message in progress to disk.   
  48.         updateDraftMmsMessage(mmsUri, persister, slideshow, sendReq);  
  49.     }  
  50.   
  51.     // Be paranoid and clean any draft SMS up.   
  52.     deleteDraftSmsMessage(threadId);  
  53.   
  54.     MessageSender sender = new  MmsMessageSender(mContext, mmsUri, slideshow  
  55.             .getCurrentMessageSize());  
  56.     try  {  
  57.         if  (!sender.sendMessage(threadId)) {  
  58.             // The message was sent through SMS protocol, we should   
  59.             // delete the copy which was previously saved in MMS drafts.   
  60.             SqliteWrapper.delete(mContext, mContentResolver, mmsUri, null ,  
  61.                     null );  
  62.         }  
  63.   
  64.         // Make sure this thread isn't over the limits in message count   
  65.         Recycler.getMmsRecycler().deleteOldMessagesByThreadId(mContext,  
  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. }  
    private void sendMmsWorker(Conversation conv, Uri mmsUri,
            PduPersister persister, SlideshowModel slideshow, SendReq sendReq) {
        // First make sure we don't have too many outstanding unsent message.
        Cursor cursor = null;
        try {
            Log.d("GN@@@","mContext:  "+mContext.toString());
            Log.d("GN@@@","mContentResolver:  "+mContentResolver.toString());
            Log.d("GN@@@","Mms.Outbox.CONTENT_URI:  "+Mms.Outbox.CONTENT_URI.toString());
            
            cursor = SqliteWrapper.query(mContext, 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();
                    return;
                }
            }
        } 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.
            mmsUri = createDraftMmsMessage(persister, sendReq, slideshow);
        } else {
            // Otherwise, sync the MMS message in progress to disk.
            updateDraftMmsMessage(mmsUri, persister, slideshow, sendReq);
        }

        // Be paranoid and clean any draft SMS up.
        deleteDraftSmsMessage(threadId);

        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();
    }


依旧是粗浅的解说:
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  messageSize) {  
  2.     mContext = context;  
  3.     mMessageUri = location;  
  4.     mMessageSize = messageSize;  
  5.       
  6.     if  (mMessageUri ==  null ) {  
  7.         throw   new  IllegalArgumentException( "Null message URI." );  
  8.     }  
  9. }  
    public MmsMessageSender(Context context, Uri location, long messageSize) {
        mContext = context;
        mMessageUri = location;
        mMessageSize = messageSize;
        
        if (mMessageUri == null) {
            throw new IllegalArgumentException("Null message URI.");
        }
    }


Java代码
  1. public   boolean  sendMessage( long  token)  throws  MmsException {  
  2.     // Load the MMS from the message uri   
  3.     PduPersister p = PduPersister.getPduPersister(mContext);  
  4.     GenericPdu pdu = p.load(mMessageUri);  
  5.   
  6.     if  (pdu.getMessageType() != PduHeaders.MESSAGE_TYPE_SEND_REQ) {  
  7.         throw   new  MmsException( "Invalid message: "  + pdu.getMessageType());  
  8.     }  
  9.   
  10.     SendReq sendReq = (SendReq) pdu;  
  11.   
  12.     // Update headers.   
  13.     updatePreferencesHeaders(sendReq);  
  14.   
  15.     // MessageClass.   
  16.     sendReq.setMessageClass(DEFAULT_MESSAGE_CLASS.getBytes());  
  17.   
  18.     // Update the 'date' field of the message before sending it.   
  19.     sendReq.setDate(System.currentTimeMillis() / 1000L);  
  20.   
  21.     sendReq.setMessageSize(mMessageSize);  
  22.   
  23.     p.updateHeaders(mMessageUri, sendReq);  
  24.   
  25.     // Move the message into MMS Outbox   
  26.     p.move(mMessageUri, Mms.Outbox.CONTENT_URI);  
  27.   
  28.     // Start MMS transaction service   
  29.     SendingProgressTokenManager  
  30.             .put(ContentUris.parseId(mMessageUri), token);  
  31.     mContext.startService(new  Intent(mContext, TransactionService. class ));  
  32.   
  33.     return   true ;  
  34. }  
    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;
    }


解说:
现从PduPersister那里拿数据,包括需要拼装的发送报头和需要发送的数据信息。
然后把要发送的信息相关数据从数据库的draft那里转移到send,表示已经发送。
最后起一个TransactionService服务,这个服务也是从PduPersister里找,找到需要发送的数据,并通过不同的用户网络送出去。
这块我猜一般人都没有改的需求。。

4.  
createDraftMmsMessage(persister, sendReq, slideshow); 和
updateDraftMmsMessage(mmsUri, persister, slideshow, sendReq); 这两个函数

刨掉 try catch , createDraftMmsMessage 函数大概有这么几句:

Java代码
  1. PduBody pb = slideshow.toPduBody();  
  2. sendReq.setBody(pb);  
  3. Uri res = persister.persist(sendReq, Mms.Draft.CONTENT_URI);  
  4. slideshow.sync(pb);  
            PduBody pb = slideshow.toPduBody();
            sendReq.setBody(pb);
            Uri res = persister.persist(sendReq, Mms.Draft.CONTENT_URI);
            slideshow.sync(pb);


updateDraftMmsMessage 函数大概有这么几句:

Java代码
  1. persister.updateHeaders(uri, sendReq);  
  2. final  PduBody pb = slideshow.toPduBody();  
  3. persister.updateParts(uri, pb);  
  4. slideshow.sync(pb);  
        persister.updateHeaders(uri, sendReq);
        final PduBody pb = slideshow.toPduBody();
        persister.updateParts(uri, pb);
        slideshow.sync(pb);


两个函数从本质上讲是一样的:把附件的东西以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=mDocumentCache  
  2.     private  PduBody makePduBody(Context context, SMILDocument document,  
  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.isAllowedToForward()) {  
  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 : location  
  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_obj),  
  74.                     Toast.LENGTH_LONG).show();  
  75.             document = SmilHelper.getDocument(pb);  
  76.         }  
  77.   
  78.         // Create and insert SMIL part(as the first part) into the PduBody.   
  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.     }  
//其中context=null。 isMakingCopy=false。 document=mDocumentCache
    private PduBody makePduBody(Context context, SMILDocument document,
            boolean isMakingCopy) {
        PduBody pb = new PduBody();

        boolean hasForwardLock = false;
        for (SlideModel slide : mSlides) {
            for (MediaModel media : slide) {
                if (isMakingCopy) {
                    if (media.isDrmProtected() && !media.isAllowedToForward()) {
                        hasForwardLock = true;
                        continue;
                    }
                }

                PduPart part = new PduPart();

                if (media.isText()) {
                    TextModel text = (TextModel) media;
                    // Don't create empty text part.
                    if (TextUtils.isEmpty(text.getText())) {
                        continue;
                    }
                    // Set Charset if it's a text media.
                    part.setCharset(text.getCharset());
                }

                // Set Content-Type.
                part.setContentType(media.getContentType().getBytes());

                String src = media.getSrc();
                String location;
                boolean startWithContentId = src.startsWith("cid:");
                if (startWithContentId) {
                    location = src.substring("cid:".length());
                } else {
                    location = src;
                }

                // Set Content-Location.
                part.setContentLocation(location.getBytes());

                // Set Content-Id.
                if (startWithContentId) {
                    // Keep the original Content-Id.
                    part.setContentId(location.getBytes());
                } else {
                    int index = location.lastIndexOf(".");
                    String contentId = (index == -1) ? location : location
                            .substring(0, index);
                    part.setContentId(contentId.getBytes());
                }

                if (media.isDrmProtected()) {
                    DrmWrapper wrapper = media.getDrmObject();
                    part.setDataUri(wrapper.getOriginalUri());
                    part.setData(wrapper.getOriginalData());
                } else if (media.isText()) {
                    part.setData(((TextModel) media).getText().getBytes());
                } else if (media.isImage() || media.isVideo()
                        || media.isAudio()) {
                    part.setDataUri(media.getUri());
                } else {
                    Log.w(TAG, "Unsupport media: " + media);
                }

                pb.addPart(part);
            }
        }

        if (hasForwardLock && isMakingCopy && context != null) {
            Toast.makeText(context,
                    context.getString(R.string.cannot_forward_drm_obj),
                    Toast.LENGTH_LONG).show();
            document = SmilHelper.getDocument(pb);
        }

        // Create and insert SMIL part(as the first part) into the PduBody.
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        SmilXmlSerializer.serialize(document, out);
        PduPart smilPart = new PduPart();
        smilPart.setContentId("smil".getBytes());
        smilPart.setContentLocation("smil.xml".getBytes());
        smilPart.setContentType(ContentType.APP_SMIL.getBytes());
        smilPart.setData(out.toByteArray());
        pb.addPart(0, smilPart);

        return pb;
    }





好了,齐活儿了

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值