SMS 短信发送过程(仅供病毒分析时参考)
消息基本单位是条目Entry.
--------------------------关键类-----------------------------------
1. CMsvSession
该类代表客户端(客户端MTM、用户接口MTM或者客户端消息应用程序)与消息服务器端的通讯通道。每一个客户端线
程对应一个该类的实例,CMsvSession提供客户端能及时获取消息服务端消息的有效方式。一个消息客户端应用必须
在正常使用任何MTM或CMsvEntry对象前,使用OpenSyncL()或者OpenASyncL()来新建一个session对象。
2. CClientMtmRegistry
Registry掌握了客户端所有目前可用的MTM有关的细节,消息客户端可以使用该类获得从CBaseMtm继承de对象。
3. CBaseMtm: 处理消息数据结构内部表示和用户界面接口,如新建、修改sms等
CBaseMtmUi: 提供用户界面功能,如阅览,编辑消息等.
CBaseMtmUiData: 用户界面数据.
4. CMsvEntry
相当于一个特定消息服务器的入口,当前entry与其的具体内容相关联。CMsvEntry包含两个部分的功能:一是可以
允许访问与这个entry关联的,不同类型的数据;而是运行访问它的子entry。该类只在客户端使用,服务器端使用
CMsvServerEntry。
用于代表消息服务器的一个入口,主要用于sms的新建, 删除, 操作, 移动和访问等Entry.
5. CMsvSrverEntry: 用于服务器端.
-------------------------关键API-------------------------------------
消息API函数:
(1) 客户/服务器会话
CMsvEntry* NewL(CMsvSession& aMsvSession, TMsvId aMsvId, constTMsvSelectionOrdering& aSortType);\
创建函数,在实例化任何MTM或CMsvEntry对象之前创建一个会话对象.
CMsvSession* OpenSyncL(MMsvSessionObserver& aObserver);//同步打开会话,一旦启动会话保持有效,该函数就返回.
CMsvSession* OpenAsyncL(MMsvSessionObserver& aObserver);//异步打开
建立了会话,就可以对注册内条目访问
(2) CMsvEntry 条目操作
CMsvEntry::GetEntryL(TMsvId aId): 获取条目并返回指向改消息树内部所需要的对象指针.
CMsvEntry::GetEntryL(TMsvId aId, TMsvId& aService, TMsvEntry& aEntry);
CMsvEntry::RemoveEntry(TMsvId aId);//从消息树中删除一个条目.
CMsvEntry::DeleteL(TMsvId aId, TRequestStatus& aStatus);//删除条目函数
CMsvEntry::CopyL(TMsId aMsvid, TMsvid aTargetId, TRequestStatus& aStatus);//复制ID
CMsvEntry::ChangeL(const TMsEntry& aEntry); //对条目进行修改
CMsvEntry::ChangeEntry(const TMsEntry& aEntry); //对条目进行修改,提交
(3) 消息服务器操作
AddObserverL(MMsvEntryObserver& aObserver); //加入观察者程序,用于提示接口
OpensyncL(MMsvEntryObserver& aObserver); //同步创建一个消息线程
OpenAsynscL(MMsvEntryObserver& aObserver);//异步创建一个消息线程
HandleSessionEventL(); //通知会话事件
如果异步方式开启会话,就会以一个EMsvServerReady事件来通知观察者程序.
(4) 客户端MTM 操作
CBaseMtm::CreateMessageL(TMsvId aServiceId); // 新创建的消息
AddAddresseeL(); //添加代表收件人的描述符(字符串)
SaveMessageL(); //保存消息
SetSubjectL(); // 添加主题描述符
ValidateMessage(TMsvPartList aPartList); //消息确认函数,函数返回确认结果
ReplyL(TmsvId aDestination, TmsvPartlist aPartList, TRequestStatus& aCompletionStatus);//对当前消息产生一个回复
ForWardL(TmsvId aDestination, TmsvPartlist aPartList, TRequestStatus& aCompletionStatus);//对当前的消息进行转发
InvokeAsyncFunctionL();//启动附加扩展.
--------------------------消息开发-----------------------------------
1. 发送消息
步骤: (1)选择MTM
SetMtmL(TUid aMtmUid);//设置MTM
CDesCArry& AvailableMtms() const;//获取MTM值
(2)选择一个服务
CDesCArray& AvalilableService() const;//返回字符串,描述服务是否存在
void SetService(Tint aServiceIndex); //选择相应的服务
(3)创建消息
void CreateMessageL();
void CreatemessageL(TmsvId aId);//消息从输入的参数中复制过来
信息接收者可以由以下函数一个添加或修改
CDesCArray& RecipientList() const;//获取地址字符串
void AddRecipientL(const TDesc &aRealAddress);//添加收件人的地址
void RemoveRecipent(Tint aIndex);//删除接收者
void SetSubjectL(const TDesC& aSubject); //信息标题
void SetBodyL(const CRichText& aMessageBody);//信息主题
void CreateAttachmentL(...);//创建附件
void DeleteAttachmentL(...);//删除附件
void SetAttachmentL(..)//设置信息到附件
(4) 存储和发送信息
void SaveMessageL(TBOOL aMakeVisible = ETURE);//是否内容在服务器中可见
void SaveMessageL(TRequestStatus& aCompletionStatus, TBOOL aMakeVisible = ETURE);//异步存储
2. 接收消息
应用程序的消息接收主要是指消息到来的通知过程,消息服务器负责完成消息的监听和传送,应用程序只需注册,当有消息被通知.
iSession = CMsvSession::OpeSyncL(*this);
然后使用HandleSessionEventL处理
------------------------------- 短信 SMS------------------------------------
SMS 实例: 基于SMS MTM
信息的发送的部分:
TInt CSMSAppUi :: CreateAndSendNewSMSL()
{
//在消息服务器目录中的entry
TMsvEntry newEntry;
//消息的类型
newEntry.iMtm = KUidMsgTypeSMS;
//给出entry 的类型
newEntry.iType = KuiMsvMessageEntry;
//将ServiceId 设置为本地服务,取得时间,设置信息状态
newEntry.iServiceId = KMsvlocaServiceIndexEntryId;
newEntry.iData.HomeTime();
newEntry.SetInPreparation(ETrue);
CMsvEntry* entry = CMsvEntry::newL(..);
CleanupStack::PushL(entry);
//创建新的entry,并且设置内容
entry ->CreateL(newEntry);
entry ->SetEntry(newEntry.Id());
//注册消息MTM客户端
CClientMtmRegistry* mtmReg;
mtmReg = CClientMtmRegistry::NewL(*session);
CleanupStack::PushL(mtmReg);
//创建一个客户端的SMS MTM对象
CBaseMtm* mtm = mtmReg -> NewMtmL(entry ->Entry().iMtm);
CleaupStack::PushL(mtm);
mtm ->SetCurrentEntry(entry);
CleanupStack::PopAndDestroy(3);
//填入消息内容
CRichText& mtmBody = mtm ->Body();
mtmBody.Reset();
_LIT(KTestSmsMsg, "Hello world");
//插入文本
mtmBody.InsertL(0, KTestSmsMsg);
newEntry.SetInPreparation(EFalse);
newEntry.SetSendingState(KMsvSendStateWaiting);
//设置本地时间
newEntry.iDate.HomeTime();
entry->ChangeL(newEntry);
//处理一些SMS MTM使用规范
CSmsClientMtm* smsMtm = static_cast<CSmsClientMtm*>(mtm);
CleaupStack::PushL(smsMtm);
//将头部信息和选项更改放入Cache
smsMtm ->RestoreServiceAndSettingL();
//CSmsHeader 获得SMS头部信息
CSmsHeader& header = smsMtm -> SmsHeader();
CSmsSetting* sendOptions = CSmsSettings::NewL();
CleaupStack::PushL(sendOptions);
//恢复当前的服务设置
sendOptions ->CopyL(smsMtm -> ServiceSettings());
//设置发送的选项
sendOptions -> SetDelivery(ESmsDeliveryImmediately());
header.SetSmsSettingsL(*sendOptions);
CleanupStack::PopAndDestroy(2);
//设置目的地址,并且将改变从缓存提交
_LIT(KDestinationAdd, "+12345678910");
smmMtm -> AddresseL(KDestinationAdd);
//提交缓存中的改变值
smsMtm -> SaveMessageL();
//现在消息已经准备好了可以发送了,首先把他放入发件箱,从发件箱再被发到目的地
//将entry移到发件箱中, 然后处理父节点
CMsvEntry* parentEntry = CMsventry::NewL(...);
CleanipStack::PushL(parentEntry);
//将原始的消息移从根目录移到发件箱
CMuiuOperationWait* wait = CMuiuOperationWait::NewL();
CMsvOpertion * op = parentEntry -> MoveL(NewEntry.Id(), KMsvGlobalOutBoxIndexEntryId, wait -> iStatue);
CleanipStack::PushL(op);
wait -> Start(); //等待操作完成
CleanupStack::PopAndDestroy(2);
}
//发送消息
void CSMSAppUi :: SetScheduledSendingStateL(CMsvEntrySession& aMsvSession)
{
CBaseMtm* smsMtm = iMtm;
//将Entry 加入到任务队列中
TBuf8<1> dummyPrams;
CMuiuOperationWait *wait = CMuiuOperationWait::NewL();
CMsvOperation* op = smsMtm -> InvokeAsyncFunctionL(..);
CleanipStack::PushL(op);
Wait -> Start();
CleanupStack::PopAndDestroy(2);
}
例子2:
#include "SMSHandler.h"
private: //data
...
CSmsHandler* iSmsHandler; //创建对象
//初始化 SmsHandler object.
CYrApplicationContainer::ConstructL()
{...
SetRect(aRect);
ActivateL();
iSmsHandler = CSmsHandler::NewL(); // 创建一个SmsHandler对象
}
//发送消息
void CYrApplicationContainer ::SendMsg()
{
TBuf<128> SMSText,PhoneNumber;
SMSText.Copy(_L("Test Message"));
PhoneNumber.Copy(_L("999999999")); //Replace Number as per your needs
iSmsHandler->SendL( PhoneNumber, SMSText) ;
}
//从收件箱,发信箱...读取
void CSmsHandler::ReadInbox()
{
HBufC* SMSContent = HBufC::NewLC(400);
HBufC8* SMSContent8 = HBufC8::NewLC(400);
TMsvSelectionOrdering sort;
sort.SetShowInvisibleEntries(ETrue); //设置句柄可见.
CMsvEntry* inboxContext=CMsvEntry::NewL(*iSession,KMsvGlobalInBoxIndexEntryId,sort); // 从收件箱中读取消息
CleanupStack::PushL( entries );
TInt msgCount= entries->Count();
for (TInt i=0; i<entries->Count(); i++)
{
TMsvId entryID = entries->At(i);
iSmsMtm->SwitchCurrentEntryL(entryID);
CMsvEntry* entry= iSession->GetEntryL((*entries)[i]);
CleanupStack::PushL(entry);
CMsvStore* inboxStore;
TRAPD(r, inboxStore = entry->ReadStoreL());
if(KErrNone != r)
{
CleanupStack::PopAndDestroy(entry);
continue;
}
CleanupStack::PushL(inboxStore);
if (inboxStore->HasBodyTextL())
{
TMsvEntry entry1 = entry->Entry();
/* Gives you phone Number or Contact Name if Contact is present*/
TBufC<50>text(entry1.iDetails);
TBuf16<30> msg;
msg.Copy(_L("Name: "));
msg.Append(text);
/*If you want to get the Recipient Number, when iDetails gives you Contact's Name. */
iSmsMtm->LoadMessageL();
CSmsHeader& header = iSmsMtm->SmsHeader();
TPtrC from = header.FromAddress();
TBuf8<60> number;
number.Copy(_L("Number: "));
number.Append(from);
/* To read phone number from Sent Item folder, see the Note below */
CRichText& richText= iSmsMtm->Body();
inboxStore->RestoreBodyTextL(richText);
const TInt length = richText.DocumentLength();
/* Gives you actual content(Body) of SMS */
SMSContent->Des().Copy(richText.Read(0,length));
richText.Reset();
SMSContent8->Des().Copy(SMSContent->Des());
/* Write SMS Body in the SMSBody.txt file*/
//WriteToFile(SMSContent8->Des());
/* Write SMS Body, number and contact name in file*/
WriteToFile(msg, number,SMSContent8->Des());
}
else
{
// no text in SMS
}
CleanupStack::PopAndDestroy(2,entry);
}
CleanupStack::PopAndDestroy(4,SMSContent);
}
//读取电话号码,发送文件夹中消息
CSmsHeader& smsHeader = iSmsMtm->SmsHeader();
const CArrayPtrFlat<CSmsNumber>& array= smsHeader.Recipients();
CSmsNumber* smsNumber = array.At(0);
TPtrC recipentNumber = smsNumber->Address(); // recipentNumber will contain the recipient Number
。。。。