00001 /* 00002 * Copyright © 2008 Nokia Corporation. 00003 */ 00004 00005 #include "SMSEngine.h" 00006 #include <msvids.h> // Folder Ids 00007 #include <txtrich.h> // CRichText 00008 #include <smut.h> 00009 #include <eikdef.h> 00010 #include <eikenv.h> 00011 #include <rsendas.h> 00012 #include <rsendasmessage.h> 00013 00014 #include "SmsEnginePanics.pan" 00015 00016 00017 #ifdef __WINS__ 00018 const TMsvId KObservedFolderId = KMsvDraftEntryId; 00019 #else 00020 const TMsvId KObservedFolderId = KMsvGlobalInBoxIndexEntryId; 00021 #endif 00022 00023 const TMsvId KInbox = KMsvGlobalInBoxIndexEntryId; 00024 const TMsvId KOutbox = KMsvGlobalOutBoxIndexEntryId; 00025 const TMsvId KDrafts = KMsvDraftEntryId; 00026 00027 const TInt KDelayTime = 1000*3000; 00028 const TInt KErrMsgLength = 20; 00029 00030 _LIT(KEmptyMsg,""); 00031 00032 // CONSTRUCTION AND DESTRUCTION 00033 EXPORT_C CSmsEngine* CSmsEngine::NewL(MSmsEngineObserver& aObserver) 00034 { 00035 CSmsEngine* self = CSmsEngine::NewLC(aObserver); 00036 CleanupStack::Pop( self ); 00037 return self; 00038 } 00039 00040 EXPORT_C CSmsEngine* CSmsEngine::NewLC(MSmsEngineObserver& aObserver) 00041 { 00042 CSmsEngine* self = new( ELeave ) CSmsEngine(aObserver); 00043 CleanupStack::PushL( self ); 00044 self->ConstructL(); 00045 return self; 00046 } 00047 00048 EXPORT_C CSmsEngine::~CSmsEngine() 00049 { 00050 delete iMsvEntry; 00051 iMsvEntry = NULL; 00052 00053 delete iMsvSession; 00054 iMsvSession = NULL; 00055 00056 delete iEngine; 00057 iEngine = NULL; 00058 } 00059 00060 CSmsEngine::CSmsEngine(MSmsEngineObserver& aObserver) : iObserver(aObserver) 00061 { 00062 } 00063 00064 void CSmsEngine::ConstructL() 00065 { 00066 iAutomaticDelete = EFalse; 00067 00068 iListeningForIncoming = ETrue; 00069 00070 iEngine = CSMSExampleMtmsEngine::NewL(*this); 00071 00072 // SMS automatic receiving needs a session to the messaging server 00073 iMsvSession = CMsvSession::OpenAsyncL(*this); 00074 } 00075 00076 //listening for incoming message 00077 void CSmsEngine::HandleSessionEventL(TMsvSessionEvent aEvent, TAny* aArg1, 00078 TAny* aArg2, TAny* /*aArg3*/) 00079 { 00080 switch (aEvent) 00081 { 00082 //One way to make sure that the message has been sent 00083 //is to watch the sent items folder. 00084 //The sent SMS could also be deleted here 00085 00086 //case EMsvEntriesMoved: 00087 //{ 00088 //Check if our message has gone to the sent items 00089 //if (aArg2 && (*(static_cast<TMsvId*>(aArg2)) == KMsvSentEntryId) ) 00090 // { 00091 // CMsvEntrySelection* entries = 00092 // static_cast<CMsvEntrySelection*>(aArg1); 00093 00094 //Note: this doesn't work if the message has been waiting 00095 //to be sent and has been sent after a boot. 00096 //In that case the deletion should be done when the server is 00097 //ready again and the sent items (and also drafts) is searched. 00098 // if (entries && iSentMessageId == entries->At(0)) 00099 // { 00100 // Model().State(ESmsEngineSent); 00101 //if it's our message and we're supposed to delete it 00102 // if( iAutomaticDeleteFromSentItems ) //note a new flag 00103 // { 00104 // iMsvSession->RemoveEntry(iSentMessageId); 00105 // } 00106 // } 00107 // iObserver.MessageSent(); 00108 // } 00109 //break; 00110 //} 00111 case EMsvServerReady: 00112 // Initialise iMsvEntry 00113 if (!iMsvEntry) 00114 { 00115 iMsvEntry = CMsvEntry::NewL(*iMsvSession, KInbox, 00116 TMsvSelectionOrdering()); 00117 00118 00119 //Sent SMS might be left to drafts if the phone was booted during 00120 //SMS sending. 00121 00122 //Engine could also be used for retrieving a response for 00123 //a message. Response could arrive after phone has been booted 00124 //so it should be checked here. 00125 //Now that we're ready to handle messages we could check 00126 //if there's a response in the inbox. 00127 //This could be the case only if the message has been 00128 //sent and the phone has been booted while waiting. 00129 00130 //The same applies to sending and deleting the sent message 00131 //Sent message could be left in the sent items if the phone 00132 //was booted before the sent message had been removed. 00133 00134 //for these situations the engine should be implemented as a 00135 //state machine and engines state should be checked on initialization. 00136 //Of course there might be multiple clients (for example if engine 00137 //implementation would be a server) so there's a need to 00138 //have own state of each client (as in server session). 00139 00140 //implementation could be something like 00141 //TSmsEngineState state = Model().State(); 00142 00143 //if( state == ESmsEngineSending ) 00144 // { 00145 00146 //Make sure that the sent message will be deleted. 00147 //TBool found(EFalse); 00148 00149 //TRAPD(error, SearchForSentMessageFromSentMessagesL(found) ); 00150 00151 //if ( !found ) 00152 // { 00153 //If the sent message is stuck in drafts 00154 // TRAP(error, SearchForSentMessageFromDraftsL(found) ); 00155 //If this is the case then resend! 00156 // } 00157 00158 //if the message is somehow mystically lost, 00159 //then it's handled as the message has been sent. 00160 //if( !found ) 00161 // { 00162 // Model().State(ESmsEngineSMSSent); 00163 // } 00164 // } 00165 00166 } 00167 break; 00168 00169 case EMsvEntriesCreated: 00170 // Only look for changes in the Inbox 00171 if (aArg2 && *(static_cast<TMsvId*>(aArg2)) == KObservedFolderId) 00172 { 00173 CMsvEntrySelection* entries = 00174 static_cast<CMsvEntrySelection*>(aArg1); 00175 if( entries->Count() >= 1 ) 00176 { 00177 iNewMessageId = entries->At(0); 00178 } 00179 else 00180 { 00181 Panic(ESmsEngineInternal); 00182 } 00183 } 00184 break; 00185 00186 case EMsvEntriesChanged: 00187 //Look for changes. When using the emulator observed folder is 00188 //drafts, otherwise inbox. 00189 //Also a check for the iListeningForIncoming is made 00190 if (aArg2 && *(static_cast<TMsvId*>(aArg2)) == KObservedFolderId 00191 && iListeningForIncoming ) 00192 { 00193 CMsvEntrySelection* entries = 00194 static_cast<CMsvEntrySelection*>(aArg1); 00195 00196 //improvement for the case of receiving a response 00197 00198 //When the phone is booted and the message has arrived before 00199 //application has started it only receives notification of 00200 //changes 00201 //in the inbox (when the user reads the message!), not the 00202 //creation where these id is initialized. 00203 //therefore we check when changes occur that if the iNewMessageID 00204 //is -1 we make client handle the response. 00205 //Check the id of the message (iNewMessageId is set 00206 //in case of EMsvEntriesCreated) 00207 00208 //code could be something like: 00209 //if ( entries && (iNewMessageId == entries->At(0) || iNewMessageId == -1) ) 00210 00211 if( entries->Count() < 1 ) 00212 { 00213 Panic(ESmsEngineInternal); 00214 } 00215 else if (iNewMessageId == entries->At(0)) 00216 { 00217 00218 if( !iMsvEntry ) 00219 { 00220 Panic(ESmsEngineNotInitialized); 00221 return; 00222 } 00223 00224 // Set entry context to the new message 00225 iMsvEntry->SetEntryL(iNewMessageId); 00226 00227 // Check the type of the arrived message and that the 00228 // message is complete. 00229 // only SMS's are our consern. 00230 if ( iMsvEntry->Entry().iMtm != KUidMsgTypeSMS || 00231 !iMsvEntry->Entry().Complete() ) 00232 { 00233 return; 00234 } 00235 00236 // Read-only store. 00237 CMsvStore* store = iMsvEntry->ReadStoreL(); 00238 CleanupStack::PushL(store); 00239 00240 // Get address of received message. 00241 TBuf<KSmsMessageLength> iAddress( 00242 iMsvEntry->Entry().iDetails 00243 ); 00244 00245 if (store->HasBodyTextL()) 00246 { 00247 CRichText* richText = CRichText::NewL( 00248 CEikonEnv::Static()->SystemParaFormatLayerL(), 00249 CEikonEnv::Static()->SystemCharFormatLayerL()); 00250 CleanupStack::PushL(richText); 00251 store->RestoreBodyTextL(*richText); 00252 const TInt length = richText->DocumentLength(); 00253 00254 TBuf<KSmsMessageLength> number; 00255 TPtrC ptr = richText->Read(0, length); 00256 00257 //iMessage = ptr; 00258 iMessage.Copy(ptr); 00259 //iLogView->DrawTextL( address ); 00260 CleanupStack::PopAndDestroy(richText); 00261 00262 00263 iObserver.MessageReceived(iAddress, iMessage); 00264 00265 } 00266 else 00267 { 00268 iObserver.MessageReceived(iAddress, KEmptyMsg); 00269 } 00270 00271 CleanupStack::PopAndDestroy(store); 00272 00273 // Automatic delete setting 00274 if ( iAutomaticDelete ) 00275 { 00276 // Ncnlist seems to panic if there is no time to play arrived 00277 // message tone before deletion. 00278 //Codescanner gives a critical 00279 User::After(KDelayTime); 00280 00281 iMsvSession->RemoveEntry(iNewMessageId); 00282 00283 iObserver.MessageDeleted(); 00284 } 00285 } 00286 } 00287 break; 00288 00289 default: 00290 break; 00291 } 00292 } 00293 00294 //callback from CSMSExampleMtmsEngine 00295 void CSmsEngine::HandleMessageSentL(TInt aError) 00296 { 00297 if (aError == KErrNone) 00298 { 00299 iObserver.MessageSent(); 00300 } 00301 else // If there was some error sending the SMS 00302 { 00303 iObserver.SmsEngineError(aError); 00304 } 00305 } 00306 00307 //sending a sms 00308 EXPORT_C void CSmsEngine::SendSmsL(const TDesC& aAddr, const TDesC& aMsg) 00309 { 00310 TInt err (KErrNone); 00311 00312 TRAP(err, SendSmsInThirdEditionL(aAddr, aMsg)); 00313 00314 if( err ) 00315 { 00316 iObserver.SmsEngineError(err); 00317 } 00318 else 00319 { 00320 iObserver.SendingMessage(); 00321 } 00322 } 00323 00324 //Sending the sms in third edition with RSendAs 00325 void CSmsEngine::SendSmsInThirdEditionL(const TDesC& aAddr, const TDesC& aMsg) 00326 { 00327 RSendAs sendAs; 00328 User::LeaveIfError(sendAs.Connect()); 00329 CleanupClosePushL(sendAs); 00330 00331 RSendAsMessage sendAsMessage; 00332 sendAsMessage.CreateL(sendAs, KUidMsgTypeSMS); 00333 CleanupClosePushL(sendAsMessage); 00334 00335 // prepare the message 00336 sendAsMessage.AddRecipientL(aAddr, RSendAsMessage::ESendAsRecipientTo); 00337 sendAsMessage.SetBodyTextL(aMsg); 00338 00339 // send the message 00340 sendAsMessage.SendMessageAndCloseL(); 00341 00342 // sendAsMessage (already closed) 00343 CleanupStack::Pop(); 00344 00345 // sendAs 00346 CleanupStack::PopAndDestroy(); 00347 } 00348 00349 //setting the received message notyfication on/off 00350 EXPORT_C void CSmsEngine::ListenforIncomingSms(TBool aListening) 00351 { 00352 // the iMsvSession could be opened in here when needed 00353 // now the flag only indicates that do we notify the client 00354 iListeningForIncoming = aListening; 00355 } 00356 00357 //setting the automatic deletion of received message on/off 00358 EXPORT_C void CSmsEngine::SetAutomaticDeletetion(TBool aDeletion) 00359 { 00360 // automatic deletion for incoming message isn't done if 00361 // iListeningForIncoming is false 00362 iAutomaticDelete = aDeletion; 00363 } 00364 00365 //getting messages from a folder 00366 EXPORT_C void CSmsEngine::GetFolderSMSMessageInformationL(TMsvId aFolderID, 00367 CDesCArrayFlat*& aAddresses, 00368 CDesCArrayFlat*& aMessages) 00369 { 00370 iEngine->GetFolderSMSMessageInformationL(aFolderID, aAddresses, aMessages); 00371 } 00372 00373 //getting messageids from a folder after having called 00374 //GetFolderSMSMessageInformationL 00375 EXPORT_C RArray<TMsvId>* CSmsEngine::GetMessageIds() 00376 { 00377 return iEngine->GetMessageIds(); 00378 } 00379 00380 //Copying a message to specified folder 00381 EXPORT_C void CSmsEngine::CopyMessageL( TMsvId aMessageId, TMsvId aFolder ) 00382 { 00383 return iEngine->CopyMessageL(aMessageId, aFolder); 00384 } 00385 00386 //Moving a message to specified folder 00387 EXPORT_C void CSmsEngine::MoveToFolderL( TMsvId aMessageId, TMsvId aFolder ) 00388 { 00389 iEngine->MoveToFolderL(aMessageId, aFolder); 00390 } 00391 00392 //Deleting a message from specified folder 00393 EXPORT_C void CSmsEngine::DeleteMessageL( TMsvId aMessageId ) 00394 { 00395 iEngine->DeleteMessageL(aMessageId); 00396 } 00397 00398 // End of file
Copyright ©2010 Nokia Corporation and/or its subsidiary(-ies).
All rights
reserved. Unless otherwise stated, these materials are provided under the terms of the Eclipse Public License
v1.0.