SMS(短Message Service)

來源:互聯網
上載者:User

      摘要:SMS(短Message Service)是GSM規範的一部分。Symbian OS SMS實現基於SMS規範的ETSI GSM 03.40 v7.4.0 Technical實現。(可從http://www.etsi.org中下載該規範)因為我們的主要工作主要是讀取、建立、修改、刪除等操作,所以我們本篇文章的重點放在這些操作上,在文章的結束部分,我們也會簡單的談及有關SMS的發送。

首先和以前各篇文章一樣,我們先簡要介紹幾個重要的類:
CMsvSession
該類代表用戶端(用戶端MTM、使用者介面MTM或者用戶端訊息應用程式)與Message Service器端的通訊通道。每一個用戶端線程對應一個該類的執行個體,CMsvSession提供用戶端能及時擷取Message Service端訊息的有效方式。一個訊息用戶端應用必須在正常使用任何MTM或CMsvEntry對象前,使用OpenSyncL()或者OpenASyncL()來建立一個session對象。
CClientMtmRegistry
Registry掌握了用戶端所有目前可用的MTM有關的細節,訊息用戶端可以使用該類獲得從CBaseMtm繼承de對象。
CBaseMtm
這個類主要用來操作sms的內容,比如可以建立、修改sms;具體是使用方法下面將會藉助代碼說明,更詳細的內容你也可以查看具體sdk的help。
CMsvEntry
相當於一個特定Message Service器的入口,當前entry與其的具體內容相關聯。CMsvEntry包含兩個部分的功能:一是可以允許訪問與這個entry關聯的,不同類型的資料;而是運行訪問它的子entry。該類只在用戶端使用,伺服器端使用CMsvServerEntry。
TMsvEntry
用於代表Message Service器的一個入口,主要用於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。
簡單說一下:首先定義一個Message Service器的入口,關聯著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函數。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.