📄 smssendhandler.cpp
字号:
/* Copyright (c) 2001, Nokia Mobile Phones. All rights reserved */
#include <msvids.h>
#include <mtclreg.h>
#include <mtclbase.h>
//#include <comabs.h>
#include <txtrich.h>
#include <smsclnt.h>
#include <smuthdr.h>
#include <smutset.h>
#include <smscmds.h>
#include "SmsSendHandler.h"
#include "MsvObserver.h"
#include <charconv.h> // CCnvCharacterSetConverter
#include <eikenv.h>
//#include <MuiuMsvSingleOpWatcher.h>
// this is the content of the message
// _LIT(KSMSText, "Example SMS");
CSmsSendHandler* CSmsSendHandler::NewL(MMsvObserver& aObserver)
{
CSmsSendHandler* self = CSmsSendHandler::NewLC(aObserver);
CleanupStack::Pop();
return self;
}
CSmsSendHandler* CSmsSendHandler::NewLC(MMsvObserver& aObserver)
{
CSmsSendHandler* self = new (ELeave) CSmsSendHandler(aObserver);
CleanupStack::PushL(self);
self->ConstructL();
return self;
}
CSmsSendHandler::CSmsSendHandler( MMsvObserver& aObserver )
: CMsvHandler(aObserver), iPhase(EIdle)
{
}
CSmsSendHandler::~CSmsSendHandler()
{
// No implementation required
}
TBool CSmsSendHandler::IsIdle()
{
if (CMsvHandler::IsIdle() && (iPhase == EIdle))
{
return ETrue;
}
else
{
return EFalse;
}
}
void CSmsSendHandler::ConstructL()
{
CMsvHandler::ConstructL();
}
// from CActive
void CSmsSendHandler::RunL()
{
ASSERT(iOperation);
// Mtm's should always return KErrNone and clients should rely on other means
// to check on operation progress
User::LeaveIfError(iStatus.Int());
// Determine the current operations progress
// Note : This class is only appropriate to Locally acting operations
// such as Create, Move, Delete.
// For the CBaseMtm::InvokeAsyncFunctionL, used to schedule the messange for sending,
// no status is available as this is not a local operation, so we use the fact
// that sent messages are moved to the 'Sent' folder which we can detect using
// the HandleSessionEventL
TMsvLocalOperationProgress progress;
TUid mtmUid = iOperation->Mtm();
if (mtmUid == KUidMsvLocalServiceMtm)
{
progress = McliUtils::GetLocalProgressL(*iOperation);
User::LeaveIfError(progress.iError);
}
else
{
// The request to schedule the message is the only non-local operation
// we request from this example
if (iPhase != EWaitingForScheduled)
{
// User::Panic(KSms, ESmsStateError);
}
}
delete iOperation;
iOperation = NULL;
switch (iPhase)
{
case EWaitingForCreate:
iObserver.HandleStatusChange(MMsvObserver::ECreated);
SetMtmEntryL(progress.iId);
if (InitializeMessageL())
{
// if ( MoveMessageEntryL(KMsvGlobalOutBoxIndexEntryId) )
if ( MoveMessageEntryL(KMsvGlobalInBoxIndexEntryId) )
{
iPhase = EWaitingForMove;
}
else
{
iPhase = EIdle;
}
}
else
{
iPhase = EIdle;
}
break;
case EWaitingForMove:
{
// iObserver.HandleStatusChange(MMsvObserver::EMovedToOutBox);
iObserver.HandleStatusChange(MMsvObserver::EMovedToInbox);
// We must create an entry selection for message copies
// (although now we only have one message in selection)
CMsvEntrySelection* selection = new (ELeave) CMsvEntrySelection;
CleanupStack::PushL(selection);
selection->AppendL(progress.iId);
// schedule the sending with the active scheduler
SetScheduledSendingStateL(*selection);
CleanupStack::PopAndDestroy(selection);
iPhase = EWaitingForScheduled;
break;
}
case EWaitingForScheduled:
{
const TMsvEntry& msvEntry = iMtm->Entry().Entry();
TInt state = msvEntry.SendingState();
if (state != KMsvSendStateScheduled)
{
iObserver.HandleError(MMsvObserver::EScheduleFailed);
iPhase = EIdle;
}
else
{
iObserver.HandleStatusChange(MMsvObserver::EScheduledForSend);
iPhase = EWaitingForSent;
}
break;
}
case EWaitingForDeleted:
iObserver.HandleStatusChange(MMsvObserver::EDeleted);
iPhase = EIdle;
break;
case EWaitingForSent: // We handle this in HandleSessionEventL
case EIdle: // Shouldn't get triggered in this state
default:
ASSERT(EFalse);
}
}
void CSmsSendHandler::CreateNewMessageL()
{
TMsvEntry newEntry; // This represents an entry in the Message Server index
newEntry.iMtm = KUidMsgTypeSMS; // message type is SMS
newEntry.iType = KUidMsvMessageEntry; // this defines the type of the entry: message
newEntry.iServiceId = KMsvLocalServiceIndexEntryId; // ID of local service (containing the standard folders)
newEntry.iDate.HomeTime(); // set the date of the entry to home time
newEntry.iDate.UniversalTime();
newEntry.SetInPreparation(ETrue); // a flag that this message is in preparation
// - CMsvEntry accesses and acts upon a particular Message Server entry.
// - NewL() does not create a new entry, but simply a new object to access an existing entry.
// - It takes in as parameters the client's message server session,
// ID of the entry to access and initial sorting order of the children of the entry.
CMsvEntry* entry = CMsvEntry::NewL(*iSession, KMsvDraftEntryIdValue, TMsvSelectionOrdering());
CleanupStack::PushL(entry);
iOperation = entry->CreateL(newEntry, iStatus);
CleanupStack::PopAndDestroy(entry);
// The RunL of this class will trigger when the server completes the request
SetActive();
iPhase = EWaitingForCreate;
}
void CSmsSendHandler::SendToL(const TDesC& aRecipient, const TDesC& aText )
{
iRecipientsTelNum = aRecipient;
iText = aText;
CreateNewMessageL();
}
TBool CSmsSendHandler::SetupSmsHeaderL()
{
if (iMtm)
{
// To handle the sms specifics we start using SmsMtm
CSmsClientMtm* smsMtm = static_cast<CSmsClientMtm*>(iMtm);
//
smsMtm->RestoreServiceAndSettingsL();
// CSmsHeader encapsulates data specific for sms messages,
// like service center number and options for sending.
CSmsHeader& header = smsMtm->SmsHeader();
CSmsSettings& serviceSettings = smsMtm->ServiceSettings();
// Added by XiaoGuo
serviceSettings.SetCharacterSet( TSmsDataCodingScheme::ESmsAlphabetUCS2 );
CSmsSettings* sendOptions = CSmsSettings::NewL();
CleanupStack::PushL(sendOptions);
sendOptions->CopyL(serviceSettings); // restore existing settings
// set send options
sendOptions->SetDelivery(ESmsDeliveryImmediately); // set to be delivered immediately
header.SetSmsSettingsL(*sendOptions);
CleanupStack::PopAndDestroy(sendOptions);
// let's check if there's a service centre address
if (header.Message().ServiceCenterAddress().Length() == 0)
{
if ( serviceSettings.ServiceCenterCount() != 0 )
{
// set sc address to default.
CSmsServiceCenter& sc = serviceSettings.
GetServiceCenter( serviceSettings.DefaultServiceCenter() );
header.Message().SetServiceCenterAddressL( sc.Address() );
}
else
{
// here there could be a dialog in which user can add sc number
iObserver.HandleError(MMsvObserver::ENoServiceCentre);
return EFalse;
}
}
return ETrue;
}
else
{
return EFalse;
}
}
#include <aknutils.h>
const TUint KSmsEdUnicodeLFSupportedByBasicPhones = 0x000A;
void CSmsSendHandler::PopulateMessageL(TMsvEntry& aMsvEntry)
{
ASSERT(iMtm);
// We get the message body from Mtm and insert a bodytext
CRichText& mtmBody = iMtm->Body();
mtmBody.Reset();
mtmBody.InsertL( 0, iText );
// set iRecipientTelNum into the Details of the entry
aMsvEntry.iDetails.Set(iRecipientsTelNum); // set recipient info in details
aMsvEntry.SetInPreparation(EFalse);
aMsvEntry.SetSendingState( KMsvSendStateWaiting );
aMsvEntry.iDate.HomeTime();
aMsvEntry.iDate.UniversalTime();
}
TBool CSmsSendHandler::InitializeMessageL()
{
ASSERT(iMtm);
TMsvEntry msvEntry = (iMtm->Entry()).Entry();
PopulateMessageL(msvEntry);
// Set SMS specific Mtm fields
if (!SetupSmsHeaderL())
{
return EFalse;
}
// Add our recipient to the list, takes in two TDesCs, first is real address and second is an alias
// works also without the alias parameter.
iMtm->AddAddresseeL( iRecipientsTelNum, msvEntry.iDetails );
// save message
CMsvEntry& entry = iMtm->Entry();
entry.ChangeL( msvEntry ); // commit index changes
iMtm->SaveMessageL(); // commit message to message server
return ETrue;
}
TBool CSmsSendHandler::MoveMessageEntryL( TMsvId aTarget )
{
ASSERT( iMtm );
TMsvEntry msvEntry( (iMtm->Entry()).Entry() );
if ( msvEntry.Parent() != aTarget )
{
TMsvSelectionOrdering sort;
sort.SetShowInvisibleEntries(ETrue); // we want to also handle the invisible entries
// Take a handle to the parent entry
CMsvEntry* parentEntry = CMsvEntry::NewL(iMtm->Session(), msvEntry.Parent(), sort);
CleanupStack::PushL(parentEntry);
// Move original from the parent to the new location
iOperation = parentEntry->MoveL(msvEntry.Id(), aTarget, iStatus);
CleanupStack::PopAndDestroy(parentEntry);
SetActive();
return ETrue;
}
return EFalse;
}
void CSmsSendHandler::SetScheduledSendingStateL(CMsvEntrySelection& aSelection)
{
ASSERT(iMtm);
// Add entry to task scheduler
TBuf8<1> dummyParams;
// invoking async schedule copy command on our mtm
iOperation = iMtm->InvokeAsyncFunctionL(
ESmsMtmCommandScheduleCopy,
// ESmsMtmCommandScheduleMove,
aSelection,
dummyParams,
iStatus);
SetActive();
}
void CSmsSendHandler::HandleChangedEntryL(TMsvId aEntryId)
{
// if we've no Mtm then we can't be in the middle of sending a message
if (iMtm)
{
// Compare the entry supplied with our current context (the message
// we have been dealing with)
TMsvEntry msvEntry((iMtm->Entry()).Entry());
if (msvEntry.Id() == aEntryId)
{
#if 0
if (msvEntry.SendingState() == KMsvSendStateSent)
{
iPhase = EWaitingForDeleted;
iObserver.HandleStatusChange(MMsvObserver::ESent);
DeleteEntryL(msvEntry);
}
else if (msvEntry.SendingState() == KMsvSendStateFailed)
{
iPhase = EIdle;
iObserver.HandleError(MMsvObserver::ESendFailed);
}
#endif
}
}
}
void CSmsSendHandler::HandleSessionEventL(TMsvSessionEvent aEvent, TAny* aArg1, TAny* /*aArg2*/, TAny* /*aArg3*/)
{
switch (aEvent)
{
case EMsvEntriesChanged:
{
// Find out what happened to the message we scheduled for sending
if (iPhase == EWaitingForSent)
{
// We take the moved entries into a selection
CMsvEntrySelection* entries = static_cast<CMsvEntrySelection*>(aArg1);
//Process each created entry, one at a time.
for(TInt i = 0; i < entries->Count(); i++)
{
HandleChangedEntryL(entries->At(i));
}
iPhase = EIdle;
}
}
break;
// This event tells us that the session has been opened
case EMsvServerReady:
CompleteConstructL(); // Construct the mtm registry
break;
case EMsvCloseSession:
// Handle close session
iSession->CloseMessageServer();
break;
case EMsvServerTerminated:
// Handle server terminated
iSession->CloseMessageServer();
break;
case EMsvGeneralError:
case EMsvServerFailedToStart:
// A major problem has occurred
iObserver.HandleError(MMsvObserver::EFatalServerError);
break;
default:
// All other events are ignored
break;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -