Symbian OS中的消息存儲與常用操作

說明:前面消息的基本知識主要參考《Series60應用程序開發》中的有關內容,後面是前段做MTM開發中用到的代碼。

一、消息存儲基本知識

Symbian OS提供的消息傳送架構基於Client/Server機制,服務器負責管理手機上的各種消息,在進行消息相關操作之前我們需要了解Symbian OS是如何組織和存儲消息的。

手機中的各種消息都是以數據項(Entry)形式供程序操作,數據項有4種類型,SymbianOS爲每種數據項提供了相應的常量標識UID,這些UID保存在msvuids.h文件中:

Ø         文件夾類型,,對應常量UIDKUidMsvFolderEntry,和PC上的文件系統一樣,每個文件夾可以包含其它數據項也可能是其它數據項的子數據項。

Ø         消息類型,對應常量UIDKUidMsvMessageEntry,它表示該數據項是一條消息。

Ø         附件類型,對應常量UIDKUidMsvAttachmentEntry,它表示該數據項是某條信息的附件。

Ø         服務類型,對應常量UIDKUidMsvServiceEntry,服務數據項包含某個消息服務的配置信息,在一般情況還擁有通過該服務收發的消息數據項。

 

除了上面提到的四種類型UID還有常用到的UIDKUidMsvRootEntrymsvids.h),它指的是根數據項,根數據項包含了4個標準文件夾數據項,分別是收件箱(KMsvGlobalInBoxIndexEntryId)、發件箱(KMsvGlobalOutBoxIndexEntryId)、草稿箱(KMsvDraftEntryId)和已發送項(KMsvSentEntryId),另外根數據項下面還包含有各種消息服務的服務項,Symbian OS中消息存儲如下圖所示:

Symbian OS中的消息服務器負責保存各種類型的數據項,這裏有兩個基本概念需要了解:消息存儲和消息索引。消息存儲保存了數據項的數據,保存的數據格式取決於消息服務,服務數據項使用消息存儲保存服務配置信息,文件夾數據項不使用消息存儲,Symbian 提供了CMsvStore類來訪問數據項的消息存儲;爲了節省內存和快速檢索消息,消息服務器把數據項的一些概要信息(標題,日期,類型,ID等)寫到消息索引中,當消息服務器啓動時將索引裝載到RAM中直到消息服務器關閉,Symbian提供了TMsvEntry類表示數據項的索引。

操作消息常用的類和數據類型:

CMsvSession

CMsvSession表示客戶端與消息服務器的會話,會用到它獲得下面將要提到的CMsvEntry上下文對象。

TMsvId

它只是一個TInt32typedef,消息服務器爲每個數據項分配一個惟一的數值做爲標識,除了上面提到的幾個固定的標識,其它的標識都是動態分配的。想要對某個消息進行操作必須先得到它的IDSymbian中消息相關的大部分函數都會用到TMsvId

TMsvEntry

上面已經提到過了它表示數據項的索引,只包含消息的一些概要信息,主要會用到Id()成員函數得到數據項的標識ID和公有數據成員iDetailsiDescriptioniDate,前面兩個成員可以用來獲取和設置索引的概要信息,iDate成員可以獲取和設置數據項的日期及時間。

CMsvEntryCMsvServerEntry

CMsvEntryCMsvServerEntry可以理解爲數據項的上下文(Context),這兩個類非常類似,只不過CMsvEntry用於客戶端,CMsvServerEntry用於實現消息的服務器端,它提供了操作數據項的各種接口,可以根據指定ID定位數據項、獲得消息存儲和消息索引。

 CMsvStore

上面已經提到過它表示數據項的存儲,可以通過CMsvEntryCMsvServerEntry)的 EditStoreL()ReadStoreL()函數取得可編輯存儲或只讀存儲。

CMsvEntrySelection

CMsvEntrySelection是一個可以存儲TMsvId的數組,在使用CMsvEntryCMsvServerEntry)的許多操作中都會做爲參數或者返回對象。

 

二、數據項常用操作

下面的消息操作使用了一個CMsvEntry CMsvServerEntry的指針對象,這兩個類提供的功能基本一樣,但有一部分函數名會不一樣,可以查一下SDK

1. 獲得當前數據項索引和ID

TMsvEntry oldEntry = iServerEntry->Entry();

TMsvId oldContext = oldEntry.Id(); //如果使用CMsvEntry可以直接使用EntryId()

 

2. 定位到指定數據項

在更換當前數據項之前通常先保存當前數據項索引ID,更換數據項並完成相關操作後再更換回原來的數據項,這可以避免影響其它函數,是一個很好的習慣。

TMsvId oldContext = iServerEntry->Entry().Id();

//使用SetEntry()更換當前數據項到root

iServerEntry->SetEntry(KMsvRootIndexEntryId);

//具體操作後更換回原來數據項

iServerEntry->SetEntry(oldContext);

 

3. 查找數據項

下面的三個CMsvEntry成員函數都能完成在當前數據項下進行查找的功能:

CMsvEntrySelection* ChildrenWithMtmL(TUid aMtm) const;

根據消息服務(MTM)進行查找,查找消息索引對象(TMsvEntry)的成員iMtm等於aMtm的數據項ID

 

CMsvEntrySelection* ChildrenWithServiceL(TMsvId aId) const;

根據消息服務ID進行查找,查找消息索引對象(TMsvEntry)的成員iServiceId等於aId的數據項ID

 

CMsvEntrySelection* ChildrenWithTypeL(TUid aEntryType) const;

根據數據項類型進行查找,查找消息索引對角的(TMsvEntry)的成員iType等於aEntryType的數據項ID

CMsvServerEntry與之相對應的三個函數爲GetChildrenWithMtm(), GetChildrenWithService(), GetChildrenWithType(),注意的一點是CMsvEntry的三個函數都返回一個CMsvEntrySelection對象的指針,使用完之後我們要負責釋放,使用CMsvServerEntry的三個函數需要事先構造一個CMsvEntrySelection對象,用完之後也需要釋放。

找出POP3郵箱個數的代碼

iMsvEntry->SetEntryL( KUidMsgTypePop3 );

CMsvEntrySelection* sel = NULL;

sel = entry->ChildrenWithMtmL( KPkiSmtpTechnologyTypeUid );

TInt cnt = sel->Count();  //獲得集合中數據項的個數

delete sel;

 


4. 更改消息索引

TMsvEntry entry = iMsvEntry->Entry();

entry.iDetails.Set( _L( “New details” ) );

iMsvEntry->ChangeL( entry );  //把更改後的數據項索引寫回消息索引中去

 

5. 數據項的讀寫

在進行數據項的讀寫之前需要使用EditStoreL()ReadStoreL()函數得到相應的存儲CMsvStore通過它提供的接口進行操作。

void CMessageView::ViewMessageL(TMsvId aId)

{     

       // Construct the CMsvEntry

       CMsvEntry* entry = iSession->GetEntryL(aId);

       CleanupStack::PushL(entry);

       // Get the messaging store

       CMsvStore* store = entry->ReadStoreL();

       CleanupStack::PushL(store);

       // Construct the CRichText and restore the body text

       CParaFormatLayer* paraLayer = CParaFormatLayer::NewL();

       CleanupStack::PushL(paraLayer);

       CCharFormatLayer* charLayer = CCharFormatLayer::NewL();

       CleanupStack::PushL(charLayer);

       CRichText* body = CRichText::NewL(paraLayer, charLayer);

       CleanupStack::PushL(body);

 

       store->RestoreBodyTextL(*body);

       // Extract body text from CRichText

       TInt len = body->DocumentLength();  //get length

       HBufC *buf = HBufC::NewL( len );

       TPtr ptrBuf = buf->Des();

       body->Extract( ptrBuf, 0, len );  //get data

//因爲不同的消息的存儲格式不同,還可能需要對ptrBuf進行相應的解碼才能正常

//顯示

       delete buf;

       buf = NULL;

       CleanupStack::PopAndDestroy(5, entry);

}

發佈了20 篇原創文章 · 獲贊 3 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章