Symbian OS Communications (779884), страница 50
Текст из файла (страница 50)
At this point some codecould check to see if it is a weather report message. If so, then thecontent of the message would be passed to the weather report parserand the message would then be deleted. Unfortunately there are somedisadvantages to this approach:1. The binary message, which is not intended for the user in raw form,briefly appears in the inbox before disappearing again.2. All observers in the system are notified about the binary SMS and itssubsequent deletion. This may result in the user being alerted to thearrival of a new SMS.A better approach for implementing this functionality is to intercept theSMS message before it reaches the message server. This can be achievedby using the SMS socket API.8.5.1 SMS Socket APIIn the summary screen application, the CWeatherReportWatcherclass waits for weather report messages.
It does this by opening a socket236RECEIVING MESSAGESto the SMS stack2 and registering for all SMS messages starting with‘Weather:’.The ‘Weather report’ SMS encoding is very simple – it consists of theprefix ‘Weather:’ followed by a single digit, either ‘1’, ‘2’, or ‘3’. Thesecorrespond to ‘sunny’, ‘cloudy’ or ‘rainy’ – we don’t get much interestingweather in the UK!Example 8.11 shows the declaration of CWeatherReportWatcherthat is later used to intercept the weather report messages.class CWeatherReportWatcher : public CActive{...private:RSocketServ iSocketServer;RSocket iSmsSocket;// . .
.enum TWeatherWatcherState{EWaitingForWeatherReport,EAcknowledgingWeatherReport};TWeatherWatcherState iState;};Example 8.11Class declaration for CWeatherReportWatcherExample 8.11 shows how the CWeatherReportWatcher has twostates.1.Waiting for a weather report SMS message.2.Acknowledging the received SMS message.The weather report watcher is implemented as an active object becauseboth the waiting and the acknowledging operations are potentially longrunning and therefore should be performed asynchronously. The activeobject allows these operations to run without blocking the entire thread.Note that if the thread was blocked then the message summaries wouldnot be updated with any newly received messages.Example 8.12 shows how the SMS socket is opened and how itregisters an interest in SMS messages with the prefix ‘‘Weather:’’ by usingRSocket::Bind()._LIT8(KWeatherReportPrefixString, "Weather:");...2For generic information on socket usage, see Chapter 3.RECEIVING APPLICATION-SPECIFIC SMS MESSAGES237void CWeatherReportWatcher::ConstructL(){CActiveScheduler::Add(this);// Connect to sockets server// SMS messages are intercepted via socketsUser::LeaveIfError(iSocketServer.Connect());// Open SMS socketUser::LeaveIfError(iSmsSocket.Open(iSocketServer, KSMSAddrFamily,KSockDatagram, KSMSDatagramProtocol));// Set SMS prefix - only intercept SMS messages starting with a// particular stringTSmsAddr smsAddress;smsAddress.SetSmsAddrFamily(ESmsAddrMatchText);smsAddress.SetTextMatch(KWeatherReportPrefixString);iSmsSocket.Bind(smsAddress);WaitForWeatherReportL();}Example 8.12prefixRegistering to receive SMS messages with a specificWaitForWeatherReport() implements the code that actuallywaits for a weather report message to be received.
This is shownin Example 8.13. Note how RSocket::Ioctl() is used to asynchronously wait for an SMS that matches the attributes that have alreadybeen set on the socket.void CWeatherReportWatcher::WaitForWeatherReportL(){// Wait for an appropriate SMS message// the RunL will be called when an appropriate SMS message is received// Note that the smsAddress has already been set in ConstructL so we// will only intercept messages starting with ’Weather:’iSbuf()=KSockSelectRead;iSmsSocket.Ioctl(KIOctlSelect, iStatus, &iSbuf, KSOLSocket);iState = EWaitingForWeatherReport;SetActive();}Example 8.13arriveWaiting for a message with the registered prefix toWhen a weather report message has been received RunL() is called.RunL() is split into two parts, the first to handle a newly received weatherreport and the second to handle the completion of the acknowledgement.238RECEIVING MESSAGESvoid CWeatherReportWatcher::RunL(){if (iState == EWaitingForWeatherReport){CSmsBuffer* smsBuffer=CSmsBuffer::NewL();CleanupStack::PushL(smsBuffer);CSmsMessage* smsMessage = CSmsMessage::NewL(iFs, ESmsDeliver,smsBuffer);// smsMessage has taken ownership of smsBuffer so remove it from the// cleanup stack.CleanupStack::Pop(smsBuffer);CleanupStack::PushL(smsMessage);RSmsSocketReadStream readstream(iSmsSocket);// This function may leavereadstream >> *smsMessage;// Extract the text from the SMS bufferTBuf<KMaxWeatherReportLength> weatherReportBuf;TInt bufferLength = smsBuffer->Length();if (bufferLength > KMaxWeatherReportLength){bufferLength = KMaxWeatherReportLength;}smsBuffer->Extract(weatherReportBuf, 0, bufferLength);Example 8.14Handling an SMS upon arrivalExample 8.14 shows how the contents of the SMS message areextracted from the SMS socket and how CSmsBuffer and CSmsMessage are used.
Once the weather report has been extracted into adescriptor then it is processed by the code shown in Example 8.15:MWeatherReportObserver::TWeatherReport weatherReport =MWeatherReportObserver::ENone;// Process the messageif (weatherReportBuf.Length() >= KMaxWeatherReportLength){// Get the last character. The last character represents the// weather report.TUint16 lastCharacter = weatherReportBuf[KMaxWeatherReportLength 1];// Process the messageswitch (lastCharacter){case ’1’:weatherReport = MWeatherReportObserver::ESunny;break;case ’2’:weatherReport = MWeatherReportObserver::ECloudy;break;RECEIVING APPLICATION-SPECIFIC SMS MESSAGES239case ’3’:weatherReport = MWeatherReportObserver::ERainy;break;// No default. Leave weather report as ’None’.}}// Update the UI with the new weather reportiWeatherReportObserver.NewWeatherReport(weatherReport);CleanupStack::PopAndDestroy(smsMessage);Example 8.15Processing the received SMSMessages with the contents ‘‘Weather:1’’ cause the UI to be updatedwith an ESunny weather report.
Messages with contents ‘‘Weather:2’’cause the UI to be updated with an ECloudy report, etc.Once the incoming message has been processed then the applicationmust acknowledge it. This lets the SMS stack know that the application hassuccessfully dealt with the SMS so it can be deleted from the reassemblystore.If the current state of the system prevents the handling of this message,for example, due to low memory then the acknowledgement can beomitted so that the SMS stack will attempt to deliver the message to theapplication again and it can be processed later when the appropriateresources may be available.Example 8.16 shows how the weather report is acknowledged.// Acknowledge successful processing of the SMS messageTPckgBuf<TUint> sbuf;iSmsSocket.Ioctl(KIoctlReadMessageSucceeded, iStatus, &sbuf,KSolSmsProv);// Wait for the acknowledgement to be sent, go active.iState = EAcknowledgingWeatherReport;SetActive();}Example 8.16Acknowledging receipt of a received SMSFinally, CWeatherReportWatcher waits for the acknowledgementto complete.
Once this is done RunL() is called again, this time theacknowledgement branch is executed where it then waits for a newweather report message.void CWeatherReportWatcher::RunL(){...else if (iState == EAcknowledgingWeatherReport)240RECEIVING MESSAGES{// The acknowledgement has now been sent so wait for another weather// report.WaitForWeatherReportL();}}Example 8.17Waiting for the acknowledgement process to complete8.6 SummaryIn this chapter, we have learnt how to:• define the structure of the message store• access messages in the message store• filter messages, for example by message type• access the generic parts of each message, for example, sender andsubject information• access the message-type specific parts of messages, such as, emailattachments• monitor the message store for changes• receive an application-specific SMS before it reaches the messagestore.9Sending MessagesThis chapter builds on Chapter 8 to provide a more complete guide tothe messaging architecture on Symbian OS.This chapter details the high-level SendAs messaging API in SymbianOS and also the UI platform-specific Send dialogs.