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

看到在WIKI上Beover1984寫的一篇文章很不錯.
在這裏轉過來做一個備忘.大家也應該有用得着.

一、消息存儲基本知識

Symbian OS提供的消息傳送架構基於Client/Server機制,服務器負責管理手機上的各種消息,在進行消息相關操作之前我們需要了解Symbian OS是如何組織和存儲消息的。
手機中的各種消息都是以數據項(Entry)形式供程序操作,數據項有4種類型,SymbianOS爲每種數據項提供了相應的常量標識UID,這些UID保存在msvuids.h文件中:



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

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

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

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

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

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

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

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

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

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

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

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

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

二、數據項常用操作

下面的消息操作使用了一個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);
}

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