• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            franksunny的個(gè)人技術(shù)空間
            獲得人生中的成功需要的專注與堅(jiān)持不懈多過天才與機(jī)會(huì)。 ——C.W. Wendte

             

            Symbian端彩信讀取初探

             

            上周由于項(xiàng)目需要對(duì)彩信讀取進(jìn)行了預(yù)研,雖然并未涉及彩信的攔截,只是對(duì)Symbian S60手機(jī)收件箱中的彩信和彩信通知的內(nèi)容進(jìn)行提取并分析,但是也算是趟了下之前一直沒有搞過的彩信這渾水,小結(jié)一下。為了體現(xiàn)分析過程的邏輯性,下文并非是由簡(jiǎn)入繁,而是采用由已知到未知的說明過程來進(jìn)行。

            彩信和彩信通知的區(qū)別

            正如前面博文《Symbian OS中的消息存儲(chǔ)與常用操作》中提及的那樣,手機(jī)中的各種消息都是以數(shù)據(jù)項(xiàng)(Entry)形式供程序操作,鑒于Nokia之前的SDK有眾多API采用非公開的方式,很多東西碰上了只能拼命的試,試通了就算OK了,短信就是這個(gè)樣子的,自從Cxt將發(fā)送短信的代碼調(diào)通后,目前用的代碼基本都是他那份原型。寫了這么多只想說雖然手機(jī)中的各種消息都是以數(shù)據(jù)項(xiàng)形式給出的,但是數(shù)據(jù)項(xiàng)又由文件夾類型、消息類型、附件類型和服務(wù)類型的數(shù)據(jù)項(xiàng),我們所指的消息如短信、彩信和郵箱乃至用戶自定義的一些消息等等都是消息類型的數(shù)據(jù)項(xiàng)即KuidMsvMessageEntry類型。既然消息類型的數(shù)據(jù)項(xiàng)這么多,那么如何區(qū)分呢,這就靠各自不同的Mtm類型,由于SDK沒有系統(tǒng)性闡述,我們雖然已經(jīng)知道短信的類型是KUidMsgTypeSMS,但是彩信的Mtm類型值到底是什么,它跟彩信通知是否是有區(qū)分的,我們不得而知。

            沒辦法只能通過數(shù)據(jù)項(xiàng)的通用操作,對(duì)手機(jī)中已存的彩信和彩信通知進(jìn)行讀取后進(jìn)行分析內(nèi)容,才得知彩信和彩信通知是兩個(gè)完全不同的Mtm類型值,一個(gè)是0x100058E1,另一個(gè)是0x100059C8,后來通過google搜索才知道前者的宏定義類型為KuidMsgTypeMultimedia,后者的宏定義類型為KUidMsgMMSNotification,兩者在mmsconst.h頭文件中有定義。

            同樣使用通用的數(shù)據(jù)項(xiàng)操作,我們可以獲取彩信和彩信通知消息數(shù)據(jù)項(xiàng)的消息存儲(chǔ)CMsvStore和附件情況,兩者的CMsvStore都是有數(shù)據(jù)的(SizeL()函數(shù)返回都是大于0的),但是卻沒有文本體(HasBodyTextL()返回都是Efalse);另外彩信都是有附件的,而彩信通知一般是沒有附件的。

            因?yàn)楦郊旧硪彩菙?shù)據(jù)項(xiàng)(KuidMsvAttachmentEntry類型的數(shù)據(jù)項(xiàng)),所以我們可以更進(jìn)一步通過通用的數(shù)據(jù)項(xiàng)操作將彩信的所有附件全部都讀取出來。而附件類型由文件類型、鏈接類型和數(shù)據(jù)項(xiàng)類型三種,通常彩信中的附件都是文件類型的附件,我們用以下代碼來演示將附件拷貝出來

            CMsvStore* inboxStore= iSmsMtm->Entry().ReadStoreL();

            CleanupStack::PushL(inboxStore);

             

            MMsvAttachmentManager& attachManager = inboxStore->AttachmentManagerL();

            TInt attachmentCount = attachManager.AttachmentCount();

            for(TInt i=0;i< attachmentCount;i++)

            {

                CMsvAttachment *attachment = attachManager.GetAttachmentInfoL(i);

                CleanupStack::PushL(attachment);

             

                if(type != CMsvAttachment::EMsvMessageEntry)

                {

                    TFileName newPath(_L("c:\\data\\"));

                    newPath.AppendNum(aMessageId);

                    newPath.Append(_L("LLF"));

                    newPath.Append(attachment->AttachmentName());

                    RFile file = attachManager.GetAttachmentFileL(i);

                    TInt size(0);

                    file.Size(size);

                    HBufC8 *buf = HBufC8::NewLC(size);

                    TPtr8 ptrBuf(buf->Des());

                    file.Read(ptrBuf, size);

                    RFile newFile;

                    User::LeaveIfError(newFile.Replace(iFs, newPath, EFileWrite));

                    newFile.Write(ptrBuf);

                    newFile.Close();

                    CleanupStack::PopAndDestroy(buf); 

                }

                CleanupStack::PopAndDestroy();

            }

             

            CleanupStack::PopAndDestroy();

            為了更加直觀的區(qū)分各個(gè)附件隸屬于不同的消息,為此以消息ID打頭并加LLF來區(qū)分附件的各個(gè)文件,一條家庭生活報(bào)的彩信,我獲取到13個(gè)附件的截圖如下

            其中有smil文件,有圖片文件,也有文本文件。

            使用通用的數(shù)據(jù)項(xiàng)操作方法,借助SDK我們對(duì)彩信和彩信通知的內(nèi)容區(qū)別和內(nèi)容分析只能到這里了。

             

            彩信的內(nèi)容分析

            顯然如果僅僅知道以上內(nèi)容還是不夠的,困擾我們的CMsvStore里面到底有些什么東西呢?暫時(shí)從代碼里面走出去,我們來參閱下Nokia發(fā)布的一份難得的中文文檔《CH_How_To_Create_MMS_Services_v4_0.pdf》(詳見附件),正如短信有短信的PDU一樣,彩信也是有其PDU的,這個(gè)PDU就在這個(gè)文檔的第五部分,在這里就不詳述了,從里面截個(gè)圖過來說明下問題。

            由這個(gè)MMSPDU,我們可以猜想下附件就是Message Body,CMsvStore是否就是MMS Header的內(nèi)容呢?

            幸好現(xiàn)在NokiaSymbian開源了,否則這個(gè)猜想是沒有辦法揭開了,通過Symbian網(wǎng)站上的源代碼瀏覽器,我們可以搜到彩信相關(guān)的源代碼位于sf\app\messaging文件夾下,但是這個(gè)里面除了彩信之外,短信也有,郵箱也有,到底該如何找到需要的彩信呢,我們知道短信其實(shí)也有短信頭的,在SDK中有提供CSmsHeader,懷疑彩信也應(yīng)該有這么頭才是,于是用C*Header搜索文件夾,過來能夠搜索到一個(gè)mmsheaders.h頭文件中有一個(gè)CMmsHeaders,找到了這個(gè)離勝利就不遠(yuǎn)了,聯(lián)想到短信讀取時(shí)有一個(gè)CSmsClientMtm::LoadMessageL()函數(shù),索性就找找有沒有一個(gè)CMmsClientMtm::LoadMessageL()函數(shù)的,通過sf\app\messaging\mmsengine\clientmtm\src文件加下的mmsclient.cpp果然能找到這個(gè)函數(shù),其源代碼如下

            // ---------------------------------------------------------

            // CMmsClientMtm::LoadMessageL

            // Loads the multimedia message

            // ---------------------------------------------------------

            //

            void CMmsClientMtm::LoadMessageL()

                {

                // First we should assert that iMsvEntry is not NULL, and panic, if it is

                __ASSERT_DEBUG( iMsvEntry, gPanic( EMmsNoCMsvEntrySet ) );

                // LoadMessageL should only be supported for message entries.

                if ( iMsvEntry->Entry().iType.iUid != KUidMsvMessageEntryValue )

                    {

                    iAttributes->Reset();

                    iMmsHeaders->Reset();

                    iAddresseeList->Reset();

                    return;       

                    }

               

                // Old data must be reset first....

                iAttributes->Reset();

             

                // load the correct data

                // get read-only message store

                CMsvStore* store = iMsvEntry->ReadStoreL();

                CleanupStack::PushL( store );

             

                // restore headers of multimedia message

                // Attachment info is not restored.

                // It makes no sense to cache the attachment info as new attachments

                // can be added with the help of the attachment magager without

                // informing MMS Client MTM of the additions.

                // Caller must use attachment manager to get attachment info.

                iMmsHeaders->RestoreL( *store );

               

                RestoreAttributesL( *store );

               

                CleanupStack::PopAndDestroy( store );

                store = NULL;

             

                // Build the iAddresseeList up

                BuildAddresseeListL();

             

                }

            注意源碼中紅色字體部分,我是英盲,所以也不管這個(gè)restore是啥意思,直接看CMmsHeaders里面的頭文件定義和源碼

            頭文件定義

                    /**

                    * Internalize the headers.

                    * @param aStore CMsvStore

                    */

                    IMPORT_C void RestoreL( CMsvStore& aStore );

            其實(shí)看了頭文件里面的定義注釋,初始化頭,參數(shù)是CMsvStore我們就知道是怎么回事了,不過既然有源碼,那就還是貼下源碼,至于分析我就不做了,反正跟短信讀取CSmsHeader一樣,操作這個(gè)CMmsHeaders。

            // ---------------------------------------------------------

            // CMmsHeaders::RestoreL

            //

            // ---------------------------------------------------------

            //

             

            EXPORT_C void CMmsHeaders::RestoreL(

                CMsvStore& aStore )

                {

             

                RMsvReadStream stream;

                Reset( NULL ); // all old pointers are deleted here

                if ( aStore.IsPresentL( KUidMmsHeaderStream ) )

                    {

                    stream.OpenLC( aStore, KUidMmsHeaderStream ); // pushes 'stream' to the stack

                    InternalizeL( stream );

                    CleanupStack::PopAndDestroy( &stream ); // close stream

                    }

                // restore MMBox header streams if present

                if ( aStore.IsPresentL( KUidMMsElementDescriptorStream ) )

                    {

                    stream.OpenLC( aStore, KUidMMsElementDescriptorStream ); // pushes 'stream' to the stack

                    iElementDescriptor = new( ELeave )CMmsElementDescriptor;

                    iElementDescriptor->InternalizeL( stream );

                    CleanupStack::PopAndDestroy( &stream ); // close stream

                    }

                if ( aStore.IsPresentL( KUidMMsMMBoxMessageHeaderStream ) )

                    {

                    stream.OpenLC( aStore, KUidMMsMMBoxMessageHeaderStream ); // pushes 'stream' to the stack

                    iMmBoxMessageHeaders = CMmsMMBoxMessageHeaders::NewL();

                    iMmBoxMessageHeaders->InternalizeL( stream );

                    CleanupStack::PopAndDestroy( &stream ); // close stream

                    }

                if ( aStore.IsPresentL( KUidMMsMMBoxViewHeadersStream ) )

                    {

                    stream.OpenLC( aStore, KUidMMsMMBoxViewHeadersStream ); // pushes 'stream' to the stack

                    iMmBoxViewHeaders = new( ELeave )CMmsMMBoxViewHeaders;

                    iMmBoxViewHeaders->InternalizeL( stream );

                    CleanupStack::PopAndDestroy( &stream ); // close stream

                    }

             

                // Extended notification also restored here

                TInt length = 0; // string length

             

                // Completeness indicator is not saved or restored.

                // If we have stored the text, it normally indicates that the message is not complete

                if ( aStore.IsPresentL( KUidMMsExtendedNotificationStream ) )

                    {

                    stream.OpenLC( aStore, KUidMMsExtendedNotificationStream ); // pushes 'stream' to the stack

                    length = stream.ReadInt32L();

                    if ( length > 0 )

                        {

                        iExtendedNotificationText = HBufC::NewL( stream, length );

                        }

                    CleanupStack::PopAndDestroy( &stream ); // close stream

                    }

               

                if ( aStore.IsPresentL( KUidMmsApplicationInfoStream ) )

                    {

                    stream.OpenLC( aStore, KUidMmsApplicationInfoStream ); // pushes 'stream' to the stack

                    length = stream.ReadInt32L();

                    if ( length > 0 )

                        {

                        iApplicationId = HBufC::NewL( stream, length );

                        }

                    length = stream.ReadInt32L();

                    if ( length > 0 )

                        {

                        iReplyToApplicationId = HBufC::NewL( stream, length );

                        }

                    length = stream.ReadInt32L();

                    if ( length > 0 )

                        {

                        iApplicationInfo = HBufC8::NewL( stream, length );

                        }

                   

                    CleanupStack::PopAndDestroy( &stream ); // close stream

                    }

                   

                if ( aStore.IsPresentL( KUidMmsReserved ) )

                    {

                    stream.OpenLC( aStore, KUidMmsReserved ); // pushes 'stream' to the stack

                    iRecommendedRetrievalMode = stream.ReadInt32L();

                    length = stream.ReadInt32L();

                    if ( length > 0 )

                        {

                        iRecommendedRetrievalModeText = HBufC16::NewL( stream, length );

                        }

                    length = stream.ReadInt32L();

                    if ( length > 0 )

                        {

                        iReplaceCancelId = HBufC8::NewL( stream, length );

                        }

                    iCancelStatus = stream.ReadInt32L();

                    CleanupStack::PopAndDestroy( &stream ); // close stream

                    }

                   

                }

            一來由于時(shí)間倉(cāng)促,二來開源的代碼頭文件和相關(guān)庫(kù)等要拷入工程中去,所以具體的編碼調(diào)試驗(yàn)證就留給以后正式要用的時(shí)候再進(jìn)行了。

             

            彩信通知的內(nèi)容分析

            以上對(duì)彩信的內(nèi)容分析算是告一個(gè)段落了,我們?cè)倩剡^頭來看看這個(gè)彩信通知,這個(gè)消息類型的數(shù)據(jù)項(xiàng)其mtmKUidMsgMMSNotification,那么這個(gè)客戶端的MTm到底是什么,繼續(xù)搜索源碼,發(fā)現(xiàn)在sf\app\messaging\mmsengine\clientmtm\src有一個(gè)mmsnotificationclient.cpp其內(nèi)部正好是CmmsNotificationClientMtm。本來以為其會(huì)跟彩信一樣比較容易看出結(jié)果來,誰知道這個(gè)類的源碼看了下,感覺有點(diǎn)殘缺的味道,里面也有用到彩信的頭CMmsHeaders,因?yàn)?span lang=EN-US>CMmsHeaders就沒有去深入,這下也只能打住了。而且還有一個(gè)疑問,如何通過這個(gè)彩信通知來編程實(shí)現(xiàn)手動(dòng)去獲取彩信,又是一個(gè)比較繁瑣的問題,搜了下源碼貌似跟sf\app\messaging\mobilemessaging\mmsui\notmtmsrc文件下的源碼有關(guān)??磥磉@趟渾水不太清啊,就此打住了。

             

            暫時(shí)將Symbian端的彩信讀取分析到這里。以后有機(jī)會(huì)再繼續(xù)趟這渾水。

             

            按照常規(guī),由于貼圖不會(huì)搞,如果需要詳盡文檔,請(qǐng)下載以下word文檔和諾基亞官方文檔rar的鏈接
            彩信初探.rar

            注意:
            目前在6730機(jī)子上對(duì)草稿箱彩信進(jìn)行試驗(yàn)時(shí)發(fā)現(xiàn)
            編輯的彩信假如沒有經(jīng)過發(fā)送,那么通過之前的attachment->AttachmentName()無法獲得附件的文件名;但是在N81等機(jī)子上是能夠獲取到的。雖然通過attachment->AttachmentName()無法獲取,但是目前發(fā)現(xiàn)通過attachment->FilePath()卻可以得到完整的文件路徑,為此附件文件名的獲取,假設(shè)attachment->AttachmentName()獲取不到,那么將采用attachment->FilePath()獲取文件路徑后進(jìn)行文件名提取的方法來實(shí)現(xiàn)比較可靠一些。

            posted on 2010-07-28 21:16 frank.sunny 閱讀(2559) 評(píng)論(0)  編輯 收藏 引用 所屬分類: symbian 開發(fā)

            常用鏈接

            留言簿(13)

            隨筆分類

            個(gè)人其它博客

            基礎(chǔ)知識(shí)鏈接

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            久久久久久久久久久免费精品| 综合网日日天干夜夜久久| 国产精品久久久久久久久| 久久99热狠狠色精品一区| 久久er国产精品免费观看8| 久久综合亚洲色HEZYO社区| 国产欧美久久一区二区| 日本WV一本一道久久香蕉| 久久综合丝袜日本网| 日韩人妻无码精品久久久不卡| 91超碰碰碰碰久久久久久综合| 亚洲国产小视频精品久久久三级 | 青青草原1769久久免费播放| 久久最新免费视频| 国产欧美一区二区久久| 亚洲精品无码久久一线| 久久精品国产一区二区三区不卡 | 亚洲国产小视频精品久久久三级| 久久久久亚洲精品无码蜜桃| 一本久道久久综合狠狠躁AV| 99久久婷婷免费国产综合精品| 97精品伊人久久大香线蕉| 久久久WWW成人免费毛片| www.久久热.com| 国内精品久久久久影院一蜜桃| 久久久无码精品亚洲日韩蜜臀浪潮| 久久九色综合九色99伊人| 久久中文字幕一区二区| 国产成人久久激情91| 91精品国产综合久久久久久| 亚洲国产精品无码久久一线 | 国产成人精品久久| 亚洲日本久久久午夜精品| 久久婷婷色综合一区二区| 久久综合色之久久综合| 久久精品国产第一区二区| 久久精品免费网站网| 久久午夜免费视频| 国产成人精品久久| 国产成人久久精品区一区二区| 国产精品久久影院|