quick_recipes (779892), страница 31
Текст из файла (страница 31)
An object of this type caches its children and has a relatively highRAM usage, so creating and destroying them often is not recommended.Instead, it is better to maintain only a small number (ideally one) ofpointers to CMsvEntry objects, and change which entry they pointto (known as the current context) only when necessary, to improveperformance and keep memory usage as low as possible.Each entry has a header which stores the entry’s metadata. The headerclass, TMsvEntry, is most useful in the context of message entries, as itis capable of holding information such as whether a message is unread,is scheduled for sending, has an attachment, and other generic messageattributes. Depending on the actual protocol used, you may be able to usemore specialized subclasses, such as TMsvEmailEntry. An importantfield for all types of entry is the ID (TMsvId), which allows you tonominate a specific message, folder or service.
For a message entry tobe valid, the iType and iMtm data members must be set. For a serviceentry, those and the iServiceId data members must be set; other thanthese, it is not guaranteed that any other data members will be set for aparticular entry.An entry’s header object can be retrieved from CMsvEntry; however,it is recommended that you use TMsvEntry (or one of its derivedclasses) directly, whenever possible – that is, if only the header data isrequired.4.4.4.2Types of EntryWhen navigating the message store, it is common for a client not to knowthe IDs of the entries it wants to access in advance, but instead to ask forMESSAGING175the child entries of a known parent – for instance, listing all the messagesin the inbox.
By repeating that procedure, all entries can be obtainedfrom the root entry of the tree.The next level of the tree consists of service entries. The TMsvIdvalues for a number of common services are defined in msvids.h.Below each service entry are any folders relating to that service. Whenthe message server starts, it creates the standard folders stated in the filemsgs.rsc under the local service. These will generally be:• A global inbox – most SMS and MMS messages are stored here whenthey are received by the device.
Class 2 SMS messages are thecommon exception; they are usually stored on the SIM.• A global outbox – messages are stored here temporarily before beingsent, or if sending fails.• A draft folder – unfinished messages are stored here until they areready to be sent.• A sent folder – messages are stored here after they have successfullybeen sent.• A deleted folder – messages are stored here once they have beendeleted. This folder is invisible to the user.The TMsvId values for the above folders are also defined in msvids.h.Following this, the message store may be customized further – forexample, some phone manufacturers use a templates folder which storesa set of pre-composed messages.
The user may also define its own localfolders. Remember, it is possible to get a list of all the available servicesby requesting the children of the root entry, and the available foldersunder a service by requesting the children of that service.Remote service entries may not use child folder entries, if there is onlyone remote storage area which is relevant to those service settings, suchas a POP3 email mailbox, or the SIM for storing class 2 SMS messages. Inthis case the message entries are stored directly under the remote serviceentry, as shown in Figure 4.4.1. However, IMAP4 does use child folderentries under the remote service to represent the different folders on theremote server.
The UI messaging application controls which folders aredisplayed to the user, and how (for instance a service entry may bedisplayed to the user as a POP3 ‘mailbox’ folder, even though no suchfolder exists in the message store).Under each folder (or service entry) are the entries for the messagesstored in that folder. These contain the message metadata as well asbody text and any data specific to the message type. If the message typesupports attachments, the message entries may have child attachmententries to hold files such as multimedia clips or pictures.176SYMBIAN C++ RECIPES4.4.3 Tips for Writing Messaging Applications4.4.3.1Messaging LibrariesThere are two versions of the messaging library, msgs.lib and msgs_autoshutdown.lib.
With the latter, the message server automaticallyshuts down when no sessions exist.4.4.3.2Multimode SMSYour application should use the multimode version of the messagingAPIs, the header files for which are in \epoc32\include\messaging.If writing an application which makes explicit use of CDMA SMSfunctions (not needed for the examples here), you may require thefollowing macros:MACROMACRO4.4.3.3CDMA_API_ENABLEDGSM_COMPATIBILITY_MODEUI Implementation DifferencesIt is important to remember that there may be implementation differencesbetween different UI versions, especially when it comes to the phone’sown messaging application, service entry, folders, etc. and its own wayof creating, handling and displaying messages.
You may be able to usesome of the functionality provided by the UI in your application, such asthe message editor, but be aware of such differences.You can use SendAs to help shield you from some dependencies onUI implementations, but its functionality only extends to creating andsending messages.4.4.3.4Mail Store DebuggingYou can view the emulator’s message store tree by going to epoc32\winscw\c\private\1000484b\Mail2 in a Windows commandprompt and using the Windows tree command. The message, folder andattachment entries are identified by their TMsvId (hexadecimal) valuesand you can see the message text and attachment files.
It is worth experimenting with this to improve your understanding of how the messagestore works – try creating or deleting some messages in the emulator andsee what happens to the tree. It can be a useful debugging tool once youknow what you are looking at.4.4.4 About the RecipesWe will use SMS to illustrate how to use the message server to carry outcommon messaging tasks. For other transports, these tasks are performedMESSAGING177in a very similar way, as they use the same common interface (forinstance, see Symbian OS Communications Programming, 2nd Editionfor an example using email).However, the implementations of some CMsvEntry functions differbetween message types – for instance, copying messages from a remoteserver to the local service is allowed for email (to download emailsfrom a mailbox) but is not supported (returns KErrNotSupported) forSMS, because SMS messages are automatically received by the SMSwatcher.
Information on these differences can be found in the SymbianDeveloper Library, for example see Symbian OS Guide Messaging Using email CMsvEntry functions for IMAP4 message entries. Underthe same categories you will also find specific information on how theTMsvEntry class is used by each type of messaging.4.4.4.1Required CapabilitiesThe capabilities required for each task depend on various factors, likewhich bearer you are using, whether you are using SendAs, and whichfolder you are creating a message in. Therefore, we have not stated thecapabilities on a per-recipe basis as your application is likely to havedifferent needs to the example application.
However, there are three mainuser capabilities your application is most likely to need: ReadUserData,WriteUserData and NetworkServices.4.4.5 Recipes4.4.5.1Initialize your Application to Use MessagingAmount of time required: 30 minutesLocation of example code: \Messaging\SmsManagerRequired libraries: msgs.lib, smcm.libRequired header file(s): msvapi.h, smsclnt.h, msvids.h, smut.hRequired platform security capability(s): Platform-dependent (seeexample code)Problem: You want to start using messaging services.Solution: We open a session with the message server and create membervariables for classes which are heavy on RAM usage, like CMsvEntryand CSmsClientMtm.Description: It is good practice to call asynchronous versions of messaging functions and make your own messaging functions asynchronous,so that the thread remains responsive to user input, because they canbe long-running.
In some cases, the synchronous versions are not supported for non-local contexts, for exactly this reason. We therefore makeCSmsManager an active object with a RunL() function which breaks178SYMBIAN C++ RECIPESup the functionality into a number of relatively short tasks, many of themasynchronous themselves (though the order of events within RunL() iscontrolled by a state machine).#include <msvapi.h> // CMsvSession, MMsvSessionObserver, CMsvEntry#include <smsclnt.h> // CSmsClientMtmclass CSmsManager : public CActive, public MMsvSessionObserver{public: // methods// MMsvSessionObservervoid HandleSessionEventL(TMsvSessionEvent aEvent, TAny* aArg1, TAny*aArg2, TAny* aArg3);private: // enumenum TSmsManagerState{EIdle,EConnectingToServer,...};private: // methodsvoid Start(TInt aError);// CActivevoid RunL();TInt RunError(TInt aError);void DoCancel();private: // dataCMsvSession* iMsvSession;CMsvEntry* iEntry;CSmsClientMtm* iSmsMtm;};To open a session to the message server asynchronously, we useCMsvSession::OpenAsyncL().Applications need to implement HandleSessionEventL() to respond to events from the message server.
The possible events aredocumented in the MMsvSessionObserver class – you must decidewhich are appropriate for your application to handle. All applicationsmust close their session upon receiving the EMsvCloseSession event.When the connection is ready, the message server calls the MMsvSessionObserver:: HandleSessionEventL() callback functionwith the event EMsvServerReady. We then call Start() to send usinto RunL(), where we can begin to use messaging. If the connectionfailed, the event given is EMsvServerFailedToStart; and we callStart() with an error, which will cause us to retry a few times (this isthe application’s main error-handling strategy)./**In this example application, some of the events are not handled.
However,have a look at the inline comments for some things toMESSAGING179consider when writing your application.*/void CSmsManager::HandleSessionEventL(TMsvSessionEvent aEvent, TAny*aArg1, TAny* aArg2, TAny* /*aArg3*/){switch (aEvent){case (EMsvServerReady):{Start(KErrNone);break;}case (EMsvServerFailedToStart): // do you want to retry?{Start (KErrCouldNotConnect );break;}case (EMsvCloseSession):case (EMsvServerTerminated):// delete objects relying on the session and// then the session itself{CloseSession();break;}case (EMsvEntriesCreated): // to be discussed later...break;// other cases relevant to our application// are already handled in RunL()default:{break;}}}In order to access and manipulate entries in the messaging store, wecreate a CMsvEntry object as a member variable (remembering that itis best to only have one of these objects per application).