首先和以前各篇文章一樣,我們先簡要介紹幾個重要的類:
CMsvSession
該類代表客戶端(客戶端MTM、用戶接口MTM或者客戶端消息應用程序)與消息服務器端的通訊通道。每一個客戶端線程對應一個該類的實例,CMsvSession提供客戶端能及時獲取消息服務端消息的有效方式。一個消息客戶端應用必須在正常使用任何MTM或CMsvEntry對象前,使用OpenSyncL()或者OpenASyncL()來新建一個session對象。
CClientMtmRegistry
Registry掌握了客戶端所有目前可用的MTM有關的細節,消息客戶端可以使用該類獲得從CBaseMtm繼承de對象。
CBaseMtm
這個類主要用來操作sms的內容,比如可以新建、修改sms;具體是使用方法下面將會藉助代碼說明,更詳細的內容你也可以查看具體sdk的help。
CMsvEntry
相當於一個特定消息服務器的入口,當前entry與其的具體內容相關聯。CMsvEntry包含兩個部分的功能:一是可以允許訪問與這個entry關聯的,不同類型的數據;而是運行訪問它的子entry。該類只在客戶端使用,服務器端使用CMsvServerEntry。
TMsvEntry
用於代表消息服務器的一個入口,主要用於sms的新建。
下面還是看幾段例程吧:)
TMsvSelectionOrdering sort; sort.SetShowInvisibleEntries(ETrue); //全部內容排序,包括隱藏 //設置入口爲outbox,也就是發信箱 CMsvEntry* entry = CMsvEntry::NewL(*iSession,KMsvGlobalOutBoxIndexEntryId,sort); CleanupStack::PushL(entry); //選擇全部內容 CMsvEntrySelection* entries = entry->ChildrenL(); CleanupStack::PushL(entries); TTime time; //得到首信息的時間,At(0)代表首信息,取其他的可以給出相應的index time = entry->ChildDataL(entries->At(0)).iDate; //彈出對話框,有首信息接收人的號碼信息 CAknInformationNote* informationNote = new (ELeave) CAknInformationNote; informationNote->ExecuteLD(entry->ChildDataL(entries->At(0)).iDetails); CleanupStack::PopAndDestroy(2); |
------------------------------------------
注意:一些變量沒有做介紹,比如iSession,這是因爲前面的文章有提到過!
------------------------------------------
上面這段例程的作用就是讓大家瞭解一下如何獲取並操作sms。
簡單說一下:首先定義一個消息服務器的入口,關聯着outbox;然後取出outbox中所有的短信內容,並存儲到CMsvEntrySelection型指針指向的list中,操作list便可方便的操作outbox中的sms。
下面講述瞭如果取單個sms的具體內容,這些都是公共變量,可以利用它們來獲取sms的具體細節:
------------------------------------------
TTime iDate (類型和名稱)
Time (描述)短信時間
--------------------------------------------------------------------------------
TPtrC iDescription
Description 短信內容
--------------------------------------------------------------------------------
TPtrC iDetails
Details 發送或接受人號碼
--------------------------------------------------------------------------------
TInt32 iError
Error
--------------------------------------------------------------------------------
TUid iMtm
MTM
--------------------------------------------------------------------------------
TInt32 iMtmData1
MTM data 1: this can be used for any purpose by an MTM.
--------------------------------------------------------------------------------
TInt32 iMtmData2
MTM data 2: this can be used for any purpose by an MTM.
--------------------------------------------------------------------------------
TInt32 iMtmData3
MTM data 3: this can be used for any purpose by an MTM.
--------------------------------------------------------------------------------
TMsvId iRelatedId
Related folder ID.
--------------------------------------------------------------------------------
TMsvId iServiceId
Service ID.
--------------------------------------------------------------------------------
TInt32 iSize
Size 短信大小
--------------------------------------------------------------------------------
TUid iType
Entry type
--------------------------------------------------------------------------------
TInt32 iWdpPortNumber
Port number
--------------------------------------------------------------------------------
TInt32 iBioType
BIO message type
------------------------------------------
通過使用上述變量就可以取得sms中的所有信息,我只對經常使用的幾個做了介紹,剩下的當大家使用到時可以詳細研究一下。上面的一段例程很簡單、也很清楚,使用起來也會比較方便,接下來使用上面的方法我們可以同樣實現delete操作:
TMsvSelectionOrdering sort; sort.SetShowInvisibleEntries(ETrue); CMsvEntry* entry = CMsvEntry::NewL(*iSession,KMsvDraftEntryId,sort); CleanupStack::PushL(entry); CMsvEntrySelection* entries = entry->ChildrenL(); CleanupStack::PushL(entries); TInt i = entries->Count(); for(TInt ncount=0;ncount<i;ncount++) entry->DeleteL(entries->At(ncount)); // information to the user iEikonEnv->InfoMsg(_L("DeleteAll Done!")); CleanupStack::PopAndDestroy(2); |
如果你已經理解了上面的讀取sms信息的操作,這個全部刪除也就不難理解了。所不同的只是調用了一個DeleteL()函數,這個函數是在類CMsvEntry中定義的,它可以刪除固定index位置的sms。詳情可以查看相關sdk help
有了上面的瞭解,不難看出sms的操作其實和我們上一講所說的vCard有類似之處,下面我們來看看如何將sms的內容導出到文件。
這裏會用到類CBaseMtm,看下面例程:
iSmsMtm->SwitchCurrentEntryL(aEntryId); iSmsMtm->LoadMessageL(); // load the message CRichText& body = iSmsMtm->Body(); //sms的內容存到CRichText控件對象中 TPtrC msg(body.Read(0)); WriteToFileL(msg); |
iSmsMtm是CBaseMtm類型的指針變量,它當然需要初始化,如下方式:
1.iSession = CMsvSession::OpenAsyncL(*this);
// 該函數的參數應該是從MMsvSessionObserver繼承過來的任何類.....它會和 session library 間建立一個異步連接...
//然後你可以在函數HandleSessionEventL中收到事件EMsvServerReady...
//事件到達表明同服務器間的通話已建立... 接着去得到 Mtm Registry,並返回 SMS mtm...
2.iMtmReg = CClientMtmRegistry::NewL(*iSession);
3.iMtmSms = static_cast<CSmsClientMtm *> (iMtmReg->NewMtmL(KUidMsgTypeSMS));
下面是WriteToFileL()函數的具體實現:
void WriteToFileL(const TPtrC &aMsg) { //設置存儲路徑以及文件 _LIT(KDirName,"//system//apps//MyApp//Data"); _LIT(KFileName,"//system//apps//MyApp//Data//MsgBody.txt"); //連接文件服務器並生成相應文件夾 RFs fileSession; fileSession.Connect(); fileSession.MkDirAll(KDirName); RFileWriteStream writer; writer.PushL(); User::LeaveIfError(writer.Replace(fileSession, KFileName, EFileWrite)); //寫入文件並確認 writer << aMsg; writer.CommitL(); CleanupStack::PopAndDestroy(); fileSession.Close(); } //以下頭文件會使用到 #include <smsclnt.h> #include <smut.h> |
上面的步驟清晰明瞭,無需多說,大家要注意一下CBaseMtm這個類的用法,因爲在接下來,我們看到的新建sms同樣會重點使用到這個類,而且使用的次數會更多。
新建sms的步驟較爲複雜,我們列出一些主要步驟:
TMsvEntry newEntry; newEntry.iMtm newEntry.iType newEntry.iServiceId newEntry.iDate.HomeTime();//一般設置爲當前時間 newEntry.SetInPreparation(ETrue);//設置爲true |
設置好上面的參數之後,接下來就可以使用CBaseMtm類來完成新建操作了
CBaseMtm* iMtmSms; ... iMtmSms->SwitchCurrentEntryL(KMsvGlobalInBoxIndexEntryId);//設置爲收信箱 iMtmSms->Entry().CreateL(newEntry); long smsId = newEntry.Id();//得到新sms的id iMtmSms->SwitchCurrentEntryL(smsId); //設置sms的詳細內容 _LIT(KSMSBody,"Hello World!"); CRichText& body = iMtmSms->Body(); body.Reset(); body.InsertL(0,KSMSBody); newEntry.iDescription.Set(KSMSBody); //設置sms的收信或發信人手機號碼 iMtmSms->AddAddresseeL(_L("13500000000")); newEntry.iDetails.Set(_L("13500000000")); iMtmSms->Entry().ChangeL(newEntry); //別忘了保存 iMtmSms->SaveMessageL(); |
如此一來,你就可以新建一條sms了,當然有了新建sms的經驗,實現修改sms的信息也就不困難,主要步驟可分爲三步:
1. 給定一些需要修改sms的信息,比如id、index、所在位置或其他
2. 通過搜索找到滿足條件的sms,並暫存這些結果
3. 利用搜索結果進行sms信息修改,最後確認變化即可
這裏對sms的修改就不做詳細的分析,大家可以自己嘗試一下!
下一節內容,我會和大家一起繼續討論有關sms的內容,只不過重點放在發送上,期待您的關注!
發送SMS也許我們大多數人都操作過,簡單說來就是編輯一段文本,然後選擇一個或多個目標號碼,點擊發送一切ok。其實在程序中實現的步驟也是如此,只不過需要我們瞭解更多的知識。
老方法,我們先來了解一些必須的類:
CSmsSettings
設置sms服務的屬性類
CSmsHeader
sms頭信息,主要有關消息的各種參數,當然與上面的CSmsSettings密切相關
其他有關sms的類在上一節我們都大致介紹了,這裏不重複說明,接下來我們會用一些具體的源碼加以分析。
首先,我們需要新建一個sms而且得到接受方的號碼,這兩步可以參照上一節的內容,裏邊詳細介紹瞭如何新建一條sms。
然後就是要設定發送前的一些參數信息,並選擇做一些相應的操作。
程序代碼:
- //iMtm是在新建sms階段設定
- TMsvEntry msvEntry = iMtm->Entry().Entry();
- // 得到sms內容 mtmBody.Reset(); //重新設定TMsvEntry
- msvEntry.iDetails.Set(iRecipient->Des()); // set recipient info in details
- msvEntry.SetInPreparation(EFalse); // set inPreparation to false
- msvEntry.SetSendingState(KMsvSendStateWaiting); // set the sending state (immediately)
- msvEntry.iDate.HomeTime(); // set time to Home Time // 使用CSmsClientMtm類處理sms
- CSmsClientMtm* smsMtm = STATIC_CAST(CSmsClientMtm*, iMtm);
- smsMtm->RestoreServiceAndSettingsL(); // CSmsHeader封裝sms消息的參數,像服務中心號碼和發送設定
- CSmsHeader& header = smsMtm->SmsHeader(); //CSmsSettings類用來詳細設定sms Header
- CSmsSettings* sendOptions = CSmsSettings::NewL();
- CleanupStack::PushL(sendOptions);
- sendOptions->CopyL(smsMtm->ServiceSettings());
- sendOptions->SetDelivery(ESmsDeliveryImmediately);//設定立即發送
- header.SetSmsSettingsL(*sendOptions); //檢查服務中心號碼有效性
- if (header.Message().ServiceCenterAddress().Length() == 0)
- {
- // 如果沒有設定,則查找默認中心號碼
- CSmsSettings* serviceSettings = &(smsMtm->ServiceSettings());
- // 中心號碼列表爲空
- if (!serviceSettings->NumSCAddresses())
- {
- // 錯誤消息
- iEikonEnv->InfoWinL(_L("No service center number"),_L("cannot send this one."));
- }
- else
- {
- // 設定爲默認服務中心號碼
- CSmsNumber* sc = 0;
- sc = &(serviceSettings->SCAddress(serviceSettings->DefaultSC()));
- header.Message().SetServiceCenterAddressL(sc->Address());
- }
- }
- CleanupStack::PopAndDestroy();
- ... ...
- CMsvEntrySelection* selection = new (ELeave) CMsvEntrySelection;
- CleanupStack::PushL(selection);
- selection->AppendL(movedId); // 添加我們要發送的sms,movedId在省略部分有定義,是TMsvId型變量
- // 調用的這個函數是用於發送的,具體的代碼後面介紹
- SetScheduledSendingStateL(selection);
- CleanupStack::PopAndDestroy(); // selection
- return ETrue; // 到這裏sms已被髮送
SetScheduledSendingStateL函數的代碼如下:
程序代碼:
- void ...::SetScheduledSendingStateL(CMsvEntrySelection* aSelection)
- {
- CBaseMtm* smsMtm = iMtm;
- // 添加entry到任務列表
- TBuf8<1> dummyParams;
- CCommandAbsorbingControl::NewLC();
- CMsvOperationWait* waiter = CMsvOperationWait::NewLC();
- waiter->Start();
- // 這個函數是關鍵
- CMsvOperation* op= smsMtm->InvokeAsyncFunctionL(
- ESmsMtmCommandScheduleCopy,
- *aSelection,
- dummyParams,
- waiter->iStatus);
- CleanupStack::PushL(op);
- CActiveScheduler::Start(); //開始時間表中任務
- CleanupStack::PopAndDestroy(3); // waiter, op, CCommandAbsorbingControl
- }
需要我們注意的是:在發送sms的過程中大部分的操作都是用於設定發送sms時的參數,所以東西比較瑣碎;如果您想自己實現這部分工作,給您的建議就是儘量採用一個比較通用的方法,無需設定一些讓人捉摸不定的信息。在發送sms中起主要作用的還是CBaseMtm類,這個類以及從它繼承的類負責sms的具體發送,所以整個過程的結束點一定是使用這些類的函數來實現發送的動作,猶如上述的InvokeAsyncFunctionL函數。