The purpose of MMS Client MTM API is to provide a way to create and send multimedia messages and to retrieve and manipulate multimedia message entries in Message Server.

MMS messages

MMS messaging provide a means of sending multimedia objects (such as images, sounds and videos) between devices. The multimedia objects are sent as attachments to a message and the required presentation of the message (in a message viewer) is defined by SMIL. (SMIL is a markup language. More information can be found at http://www.w3.org/AudioVideo/ )


Messaging architecture of the Symbian platform is a powerful and extensible multi-protocol messaging framework. It allows the creation of plug-in modules to support individual messaging protocols such as SMS, email, and MMS. The set of components that make up such a plug-in module is called a Message Type Module (MTM). All interaction with lower-level communication protocols is performed by MTM. The components that comprise a module are Client MTM, UI MTM, UI Data MTM and Server MTM. A diagram illustrating the MTM architecture is shown in Figure 1:

Messaging architecture

Messaging architecture

The plug-in nature of the architecture means that devices based on Symbian OS may support different protocols and that support for any given protocol may differ between Symbian OS versions.

API description

MMS Client MTM API is used to access Message Server and hence message entries. MMS Client MTM forms part of the MMS MTM module (a plug-in to the messaging architecture). It implements a class derived from CBaseMtm and provides functionality to create and send MMS messages, retrieve messages from the message store and view or change their attributes, forward or reply to messages and so on.

Note that MTMs are often platform specific. So, while the base class, CBaseMtm , is common to all Symbian platforms, MMS Client MTM described here is specific to S60 on Symbian platforms.

Before using MMS Client MTM API, it is advisable to consider whether either of the more lightweight APIs, Send As ( RSendAs and RSendAsMessage ) or Send UI ( CSendUI ), may be more suitable.

API class structure

MMS Client MTM is one module of MMS MTM.

The main class of MMS Client MTM API is CMmsClientMtm . It is derived from CBaseMtm and is the MMS MTM's implementation of Client MTM.

(An overview of the MTM architecture is given in the MTMs section of this document. Further information can be found in the SDK documentation.

A class diagram for MMS Client MTM API is shown in Figure 2:

MMS Client MTM class diagram

MMS Client MTM class diagram

Related APIs
  • CBaseMtm
  • CMmsClientMtm
Related APIs
  • CBaseMtm
  • CSendUI
  • RSendAs
  • RSendAsMessage

Using MMS Client MTM API

The messaging architecture relies on the client/server framework. This means that a session (an instance of CMsvSession ) is required as a channel of communication between the client thread (Client MTM) and the Message Server thread. This session must exist before Client MTM can be constructed and its functionality used.

The most important use cases are described in the sections below. Note that these use cases do not constitute an exhaustive list of the MMS Client MTM's functionality. CMmsClientMtm contains numerous functions documented in the header file mmsclient.h .

Note that a prerequisite of using MMS Client MTM is a good understanding of the key messaging concepts.

Capabilities required to use MMS Client MTM API are ReadUserData , ReadDeviceData and NetworkServices

Constructing MMS Client MTM

The first step for using MMS Client MTM API is creating a session with Message Server. To do this, a class which implements the mixin MMsvSessionObserver is required. An example of such a class is shown below.

              class CMtmExample : public CActive, public MMsvSessionObserver
private: // from MMsvSessionObserver
    void HandleSessionEventL(TMsvSessionEvent aEvent, TAny* aArg1, TAny* aArg2, TAny* aArg3);
    CMsvOperation*      iOp;
    CMsvSession*        iSession;              // Session to the messaging server
    CClientMtmRegistry* iMtmReg;
    CMmsClientMtm*      iMmsMtm;
    TMsvId              iNewMessageId;


A session with the Message Server can be created either synchronously (using CMsvSession::OpenSyncL ) or asynchronously (using CMsvSession::OpenAsyncL() ). In each case, an instance of the MMSvSessionObserver derived class is passed, by reference to the function. (Use of the asynchronous implementation is recommended to ensure responsiveness of the device.)

              void CMtmExample::ConstructL()

    // Create CMsvSession
    // New session is opened asynchronously
    iSession = CMsvSession::OpenAsyncL(*this);

For asynchronous connections, notification of success is through a call to the implemented HandleSessionEventL() function, with the argument aEvent = EMsvServerReady being passed through. Once this notification has been received (or the synchronous function has returned), other messaging objects can be created.

              void CMtmExample::HandleSessionEventL(TMsvSessionEvent aEvent, TAny* /*aArg1*/, TAny* /*aArg2*/, TAny* /*aArg3*/)
    switch (aEvent)
        // This event tells us that the session has been opened
        case EMsvServerReady:

Accessing MMS Client MTM is done through the Client MTM registry ( CClientMtmRegistry ). This holds details of all registered client MTMs available on the device. The registry is constructed with a handle to the session. MMS Client MTM can then be created through a call to CClientMtmRegistry::NewMtmL() , passing through KUidMsgTypeMultiMedia (defined in mmsconst.h ) as the MTM UID. NewMtmL() returns a CBaseMtm pointer which needs to be cast into the correct type, that is CMmsClientMtm .

              void CMtmsExampleEngine::CompleteConstructL()
    // Construct the Client MTM registry
    iMtmReg = CClientMtmRegistry::NewL(*iSession);

    // Obtain MMS Client MTM from the MTM registry
    iMmsMtm = static_cast<CMmsClientMtm*>(iMtmReg->NewMtmL(KUidMsgTypeMultimedia));

MMS Client MTM can now be used to access Message Server and create, manipulate, and send multimedia messages.

Related APIs
  • CBaseMtm
  • CClientMtmRegistry
  • CClientMtmRegistry::NewMtmL()
  • CMmsClientMtm
  • CMsvSession::OpenAsyncL()
  • CMsvSession::OpenSyncL
  • HandleSessionEventL()
  • KUidMsgTypeMultiMedia
  • MMSvSessionObserver
  • MMsvSessionObserver
  • NewMtmL()

Creating an MMS message entry

Once the MMS Client MTM instance has been constructed (see Constructing MMS Client MTM ), it can be used to create an MMS entry in Message Server. There is more than one way to create an MMS message entry but the most obvious way is to use CMmsClientMtm::CreateMessageL() . This function creates an empty message entry as the child of the current context. (The context is simply the entry on which the MTM actions are performed.) The entry is created with its visible flag set to false and its in-preparation flag set to true since at this stage it is empty.

As the entry is created as a child to the current context , it is important to first set the context appropriately before CreateMessageL() is called. It is usual to create new messages in the drafts folder. To set the context , SwitchCurrentEntryL() is called with the parent folder ID ( KMsvDraftEntryId ) passed through. CMmsClientMtm::CreateMessageL() is then called with the required service ID as a parameter. The service ID can be retrieved by calling DefaultServiceL() on the MTM. After successfully creating the new message entry, CreateMessageL() then sets the new entry as the current context.

              TBool CMtmsExampleEngine::CreateNewMessageL()
    // Set context to the parent folder (Drafts folder)

At this stage, the created message is empty. To be useful, the intended message recipient(s) of the message must be set. For MMS entries, it is also useful to give the message a subject attribute.

CMmsClientMtm::AddAddresseeL() has a number of overloads that can be used to set the To, Cc, and Bcc fields of an MMS entry. CMMsClientMtmL::SetSubjectL() takes a descriptor ( TDesC& ) and is used to set the subject.

                  // Set the recipients (_LIT used only for demonstration purposes)
    // "To" recipient.
    _LIT(KSamsNumber, "07738123456");
    _LIT(KSamsAlias, "Sam");
    // Cc recipient
    _LIT(KPetesNumber, "07812654321");
    iMmsMtm->AddAddresseeL(EMsvRecipientTo, KSamsNumber, KSamsAlias); // To field, alias set
    iMmsMtm->AddAddresseeL(EMsvRecipientCc, KPetesNumber); // Cc field, no alias
    // Set a message subject
    _LIT(KMessageSubject, "MMS Example");


The next step at this point is to add some text and multimedia object to the message. How this is done is shown in Adding an attachment to an MMS message .

Here, the message is just saved to the drafts folder. To indicate that the message entry is no longer being amended, TMsvEntry::SetInPreparation() can be set to EFalse while TMsvEntry::SetVisible() is set to ETrue to ensure the message is displayed in the Messaging application. Changes to the entry should be committed using CMsvEntry::ChangeL() and the message saved using CMmsClientMtm::SaveMessageL() .

SetInPreparation() and SetVisible() need to be called on the TMsvEntry that represents the message in Message Server. To access this, Entry() is called on Client MTM and then Entry() is called on the returned CMsvEntry .

                  TMsvEntry ent = iMmsMtm->Entry().Entry();
    // Set InPreparation to false
    ent.SetVisible(ETrue);            // Mark as visible, so this the message can be seen in Drafts    
    iMmsMtm->Entry().ChangeL(ent);    // Commit changes
    //Save the changes
Related APIs
  • CMMsClientMtmL::SetSubjectL()
  • CMmsClientMtm::AddAddresseeL()
  • CMmsClientMtm::CreateMessageL()
  • CMmsClientMtm::SaveMessageL()
  • CMsvEntry
  • CMsvEntry::ChangeL()
  • CreateMessageL()
  • DefaultServiceL()
  • EFalse
  • ETrue
  • Entry()
  • KMsvDraftEntryId
  • SetInPreparation()
  • SetVisible()
  • SwitchCurrentEntryL()
  • TDesC&
  • TMsvEntry
  • TMsvEntry::SetInPreparation()
  • TMsvEntry::SetVisible()

Adding and amending attributes of an MMS message

There are a number of attributes on a message entry than can be set or amended. These attributes are properties of the message header but can be set through Client MTM and include the expiry date on the message, the delivery time, and priority. As long as the context of the MTM is set to the appropriate message, setting the values for the properties is simply a case of calling the correct function. The functions are detailed in the Client MTM header file ( mmsclient.h ) and enumeration values required by some of the functions can be found in mmsconst.h .

An example showing the message priority being set to high is shown below.

//Save the changes

Adding body text to an MMS message

Although CMmsClientMtm has a Body() function defined, it should not be used. Body text for an MMS message is treated as a message attachment and therefore should be set using CMmsClientMtm::CreateTextAttachmentL() . See Adding attachments to an MMS message for further information.

Related APIs
  • Body()
  • CMmsClientMtm
  • CMmsClientMtm::CreateTextAttachmentL()

Adding attachments to an MMS message

All MMS message data (text, images, sounds, and so on) should be sent as attachments to the message with the required presentation being defined by a SMIL file (also sent as an attachment). Note, although CMmsClientMtm has a Body() function defined, it should not be used - the message body text is treated as an attachment. Therefore, text should be added using CMmsClientMtm::CreateTextAttachmentL() .

              virtual void CMmsClientMtm::CreateTextAttachmentL(  
    CMsvStore&  aStore,  
    TMsvAttachmentId &  aAttachmentId,  
    const TDesC&  aText,  
    const TDesC&  aFile,  
    TBool  aConvertParagraphSeparator = ETrue); 

The function requires that the message store for the message entry has been opened ready for editing. A pointer to the open store is then passed as a parameter. The text required for the message is passed as a descriptor ( aText ) and a suggestion for a suitable file name is also needed (SMIL references this filename). If required, the unicode paragraph separator (character 0x2029 ) can be replaced with a line feed (character 0x000a ). On completion, aAttachmentId is set.

To use CreateTextAttachmentL() , the message entry's store must first be opened.

              // Open the entry's store - assume message context set correctly
CMsvStore* store = iMmsMtm->Entry().EditStoreL();
// Add the text attachment. _LIT used for demonstration purposes   
_LIT(KMMSText, "Thought you'd like to see where I'm staying");
_LIT(KMMSTextFilename, "hello.txt");

iMmsMtm->CreateTextAttachmentL(*store, attachId, KMMSText, KMMSTextFilename);
// Add more attachments or save the message
// Remember to do the appropriate clean up at the end

For multimedia attachments, CMmsClientMtm::CreateAttachment2L() is used.

              virtual void CreateAttachment2L(             
    CMsvStore& aStore,             
    RFile& aFile,             
    TDesC8& aMimeType,             
    CMsvMimeHeaders& aMimeHeaders,             
    CMsvAttachment* aAttachmentInfo,             
    TMsvAttachmentId& aAttaId);

The function creates an attachment entry and copies the file specified as a parameter ( aFile ) to an open message store ( aStore ). The attachment should be passed as a handle to an open file. The MIME type, for example "image/jpeg" for a JPEG image, is passed as a descriptor. A MIME header ( CMsvMimeHeaders ) for the attachment is created. A reference to the header is passed to the function so it can be updated. A CMsvAttachment object is created with the parameter CMsvAttachment::EMsvFile to represent the attachment. This is also updated by the CreateAttachment2L function.

              // Continuation of code above which set a text attachment
// Add an image attachment
// Set the filename for the image
#define KDirPictures   PathInfo::ImagesPath()
#define KPhoneRootPath PathInfo::PhoneMemoryRootPath()
_LIT(KFileName, "mmsexample.jpg");  

TFileName attachmentFile(KPhoneRootPath);
// Open the attachment file
RFile attachment;

TInt error = attachment.Open(CCoeEnv::Static()->FsSession(), attachmentFile, EFileShareReadersOnly | EFileRead);
// Check that the attachment file exists.
if(error != KErrNone)
    _LIT(KFileNotFound, "Attachment file not found!");
    return EFalse;
    // Mime header
    CMsvMimeHeaders* mimeHeaders = CMsvMimeHeaders::NewL();

    // Represents a single attachment and information about the attachment
    CMsvAttachment* attaInfo = CMsvAttachment::NewL(CMsvAttachment::EMsvFile);

    // Mime Type
    _LIT8(KMimeType, "image/jpeg");
    TBufC8<10> mimeType(KMimeType);  

    // Attachment file must be in a public folder (e.g. c:\Data\images)
        attachId );

    CleanupStack::Pop(attaInfo); // attaInfo
    CleanupStack::PopAndDestroy(mimeHeaders); // mimeHeaders

    // If a SMIL file is attached for presentation layout purposes
    // then it should be done here before the 
    // the changes are committed

    // Commit the changes and perform the appropriate cleanup

    // Save the changes

This example shows how to attach some text and an image to an MMS message. However, the layout of the message is left to the receiving device. To dictate how the message should be presented to the recipient, a SMIL file is needed. An example file is shown below.

              <smil xmlns="http://www.w3.org/2000/SMIL20/CR/Language">
            <root-layout width="160" height="140"/>
            <region id="Image" width="160" height="120" left="0" top="0"/>
            <region id = "Text" width="160" height="20" left="100" top="120"/>
        <par dur="10s">
            <img src="mmsexample.jpg" region="Image" />
            <text src="hello.txt" region="Text" />

This file indicates that the image should be displayed before the text in the message.

The SMIL file should be added as an attachment in the same way that the image was added, that is using CMmsClientMtm::CreateAttachment2L() . In this case, the MIME type should be set to KMmsApplicationSmil (defined in mmsconst.h ). The SMIL attachment should then be set as the root attachment using CMmsClientMtm::SetMessageRootL() and passing through the ID ( TMsvAttachmentId ) of the SMIL attachment set by the Createattachment2L() function.


Note that after setting the root, the changes to the store should be committed and the message saved.

Related APIs
  • "image/jpeg"
  • 0x000a
  • 0x2029
  • Body()
  • CMmsClientMtm
  • CMmsClientMtm::CreateAttachment2L()
  • CMmsClientMtm::CreateTextAttachmentL()
  • CMmsClientMtm::SetMessageRootL()
  • CMsvAttachment
  • CMsvAttachment::EMsvFile
  • CMsvMimeHeaders
  • CreateAttachment2L
  • CreateTextAttachmentL()
  • Createattachment2L()
  • KMmsApplicationSmil
  • TMsvAttachmentId
  • aAttachmentId
  • aFile
  • aStore
  • aText

Validating an MMS message

Before sending an MMS message, it is advisable to validate it to ensure the added data is compliant with the message type. The base class ( CBaseMtm ) defines the function ValidateMessage() and this is implemented by each MTM to provide type-specific validation. The function takes a TMsvPartList parameter which is a bit-set (flags for this bit-set are defined in Mmtdef.h ) indicating the parts to be checked. Not all flags are supported by MMS MTM. Supported flags are KMsvMessagePartRecipient , KMsvMessagePartOriginator and KMsvMessagePartAttachments . The return value of ValidateMessage() is also a TMsvPartList bit set that indicates which parts of the message were invalid.

              TBool CMtmsExampleEngine::ValidateMMS()     
    // Context should be set to appropriate message
    TMsvPartList msgCheckParts = KMsvMessagePartRecipient | KMsvMessagePartOriginator | KMsvMessagePartAttachments;
    TMsvPartList msgFailParts = iMmsMtm->ValidateMessage(msgCheckParts);      
    return msgFailParts == KMsvMessagePartNone;     
Related APIs
  • CBaseMtm
  • KMsvMessagePartAttachments
  • KMsvMessagePartOriginator
  • KMsvMessagePartRecipient
  • TMsvPartList
  • ValidateMessage()

Sending an MMS message

Assuming that the MMS message has been created and validated, sending a message using MMS Client MTM is simply a case of using its SendL() function. The important point to realize is that the ID of the message entry that should be sent must be set as the context of the MTM. If required, a time can be set for the sending of the message. The SendL() function is asynchronous and returns a CMsvOperation pointer. This can be used to obtain progress information about the operation before the active object completes (that is, before the RunL() is called).

              void CMtmsExampleEngine::SendMMSL()     
    iOp = iMmsMtm->SendL(iStatus);     

There is also an overload of CMmsClientMtm::SendL() that enables the sending of multiple messages with one operation. An array of message IDs ( TMsvId s) is created as a CMsvEntrySelection object and this is passed as a parameter to the SendL() function. Again the function is asynchronous and returns a CMsvOperation pointer to allow progress monitoring.

Related APIs
  • CMmsClientMtm::SendL()
  • CMsvEntrySelection
  • CMsvOperation
  • RunL()
  • SendL()
  • TMsvId

Querying a received MMS message

MMS Client MTM can be used to retrieve information from received MMS messages. Functions such as Sender() , MessageReceiveTime() , NumberOfPreviousSenders() are available to use. In each case, the important point is that the context of the MTM is set correctly using the ID of the message.

The example below shows an incoming message, caught by MMsvSessionObserver::HandleSessionEventL() . The message ID ( TmsvId iNewMessageId ) is stored as the entry is created in Inbox and then, once the message has been stored ( aEvent == EMsvEntriesChanged ), the MTM context is set and the message loaded. Information about the message can then be queried, for example the sender.

              void CMtmsExampleEngine::HandleSessionEventL(TMsvSessionEvent aEvent, TAny* aArg1, TAny* aArg2, TAny* aArg3)
    switch (aEvent)
        case EMsvEntriesCreated:
            if(*(static_cast<TMsvId*>(aArg2)) == KMsvGlobalInBoxIndexEntryId)
                CMsvEntrySelection* entries = static_cast<CMsvEntrySelection*>(aArg1);
                iNewMessageId = entries->At(0);
        case EMsvEntriesChanged:
            if(*(static_cast<TMsvId*>(aArg2)) == KMsvGlobalInBoxIndexEntryId)
                CMsvEntrySelection* entries = static_cast<CMsvEntrySelection*>(aArg1);
                if(iNewMessageId == entries->At(0))
                    TPtrC sender = iMmsMtm->Sender();
                    // Use the sender information

Further information about the general messaging concepts that are needed to understand this example can be found in the SDK documentation and at Nokia Developer .

It is important to note that an MMS entry does not have a message body as the message text is sent as an attachment and therefore the Client MTM's Body() function should not be used. However, further information about the message text and attachments can be obtained through the message entry's store. The general procedure is to use CMsvStore::AttachmentManagerL() . The example below shows how the message text could be retrieved.

              CMsvEntry* entry = iSession->GetEntryL(iNewMessageId);   
CMsvStore* store = entry->ReadStoreL();  
if(store!= NULL)  
    MMsvAttachmentManager& attManager = store->AttachmentManagerL();         

    _LIT8(KMimeBuf, "text/plain");                   
    // Cycle through the attachments
    for(TInt i=0; i<attManager.AttachmentCount(); i++)           
        CMsvAttachment* attachment = attManager.GetAttachmentInfoL(i);          

        // Test to see if we have a text file
        if(mimeBuf.CompareF(attachment->MimeType())== 0)               
            RFile file = attManager.GetAttachmentFileL(i);
            // The file can then be read using the normal file functionality
            // After reading, the file should be closed

This aspect of message querying falls outside the scope of MMS Client MTM and therefore is not covered in detail here but is included for completeness.

Related APIs
  • Body()
  • CMsvStore::AttachmentManagerL()
  • MMsvSessionObserver::HandleSessionEventL()
  • MessageReceiveTime()
  • NumberOfPreviousSenders()
  • Sender()

Responding to (replying/forwarding) a received message

An obvious requirement of a messaging client is to be able to reply to or forward received messages. MMS Client MTM provides CMmsClientMtm::ReplyL() and CMmsClientMtm::ForwardL() for this purpose. Both functions are asynchronous and return a CMsvOperation pointer to allow the monitoring of the progress of the function and ultimately to provide the ID( TMsvId ) of the newly created message.

To use the functions, the message to be replied to/forwarded must be set as the context. The functions take as parameters the ID ( TMsvId ) of the folder in which the new message should be created, a list ( TMsvPartList ) of the elements of the original message that should be copied to the new message, and a TRequestStatus reference. (Note that not all elements of TMsvPartList are supported, see mmsclient.h for further information.) An example of using CClientMtm::ReplyL() is shown here but CMmsClientMtm::ForwardL() can be used similarly.

              void CMtmsExampleEngine::ReplyL()
    // Add the description of the received message to the new (reply) message
    // Note the Recipient address is automatically set to the sender
    // KMsvMessagePartRecipient is only needed for reply to all
    TMsvPartList msgCheckParts = KMsvMessagePartDescription;

    iOp = iMmsMtm->ReplyL(KMsvDraftEntryId,msgCheckParts,iStatus);

On completion ( RunL() being called), the ID of the newly created message is retrieved using CMsvOperation::Progress() . A package buffer is used to transfer this information. If the creation of the reply/forward message was not successful, the ID will be set to KMsvNullIndexEntryId . Once the operation has completed, the message can be modified and saved, or sent, using the usual functions.

              void CMtmsExampleEngine::RunL()
    if(iStatus.Int() == KErrNone)
        // Retrieve the id of the created message
        // Id is returned in a package buffer
        TPckgBuf<TMsvId> pkg;
        pkg.Copy( iOp->ProgressL());
        TMsvId indexEntry = pkg();

        if(indexEntry != KMsvNullIndexEntryId)
            // Set the context to the new message
            // Here add further recipients, subject, attachments
            // to the message

            // Commit the changes and save the Message 
            TMsvEntry ent = iMmsMtm->Entry().Entry();
            // Set InPreparation to false
            ent.SetVisible(ETrue);            // mark as visible
            iMmsMtm->Entry().ChangeL(ent);    // Commit changes
            //Save the changes
Related APIs
  • CClientMtm::ReplyL()
  • CMmsClientMtm::ForwardL()
  • CMmsClientMtm::ReplyL()
  • CMsvOperation
  • CMsvOperation::Progress()
  • KMsvNullIndexEntryId
  • RunL()
  • TMsvId
  • TMsvPartList
  • TRequestStatus

Cleaning up of resources

Once all of the required operations have been carried out, the appropriate destruction of resources should be carried out. Obviously the resources used are application specific but in general require at least Client MTM, the MTM registry and the session. They should be deleted in the reverse order to which they were created.

    // For this particular example cleanup     
    Cancel();         // Active Object
    delete iOp;
    // For general use of the MMS Client MTM
    delete iMmsMtm;   // CMmsClientMtm  
    delete iMtmReg;   // CClientMtmRegistry 
    delete iSession;  // CMsvSession  

Error handling

The leave mechanism of Symbian platform is used to handle error conditions on method calls. In addition, messaging defines a series of panics; these are detailed in Symbian OS reference » System panic reference » MSGS.

Related APIs
  • CMmsClientMtm
  • CMsvSession
  • NetworkServices
  • ReadDeviceData
  • ReadUserData



MMS Client MTM API abbreviations


Application Programming Interface.


Multipurpose Internet Mail Extensions.


Multimedia Messaging Service. Protocol defined by 3GPP. Messaging for text, images, audio.


Message Type Module. A group of components that together provide message handling for a particular protocol.


Software Development Kit.


Synchronized Multimedia Integration Language. A markup language designed to present multiple media files together.


Short Message System. A protocol, defined within the GSM standard, which allows point-to-point transmission of short messages. 'Short' means 140 bytes, or 160 characters with the special 7-bit SMS character set. Can also be used to transmit up to 31k of binary or text data by concatenating messages.


User Interface.



Synchronized Media Integration Language (SMIL)


SDK documentation


Nokia Developer