The MMS Client MTM API provides functions to create, send multimedia messages, and retrieve and manipulate multimedia message entries in Message Server.
API category | public |
API type | c++ |
API libraries | mmscli.lib |
Location | /sf/app/messaging/msg_pub/mms_client_mtm_api
|
Buildfiles | /sf/app/messaging/msg_pub/mms_client_mtm_api/group/bld.inf
|
MMS Client MTM API is used to access Message Server and 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 Symbian-specific.
Before using MMS Client MTM API, it is recommeded to check if the lightweight APIs, Send As ( RSendAs
and RSendAsMessage
) or Send UI ( CSendUI
), are suitable.
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 from 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. The following diagram illustrates the MTM architecture:
Different devices on Symbian platform may support different protocols and the support for any given protocol may differ between Symbian platforms. The plug-in architecture makes the support mechanisum easy in Messaging.
The following are the most important use cases of MMS Client API:
Classes | Files |
---|---|
|
/epoc32/include/app/mmsclient.h
, /epoc32/include/app/mmsclient.inl
/epoc32/include/app/mmsconst.h
, /epoc32/include/app/mmserrors.h
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 [MMS_Client_MTM_API_Specification.topic1 MTMs] section of this document. Further information can be found in the SDK documentation.
The following class diagram shows the 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
.
Capabilities required to use MMS Client MTM API are ReadUserData
, ReadDeviceData
and NetworkServices
.
A prerequisite of using MMS Client MTM is a good understanding of the key messaging concepts.
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); ... private: 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. It is recommended to use the asynchronous implementation
to ensure responsiveness of the device.
void CMtmExample::ConstructL() { CActiveScheduler::Add(this); // 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: CompleteConstructL(); break; ... } }
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.
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 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) iMmsMtm->SwitchCurrentEntryL(KMsvDraftEntryId); iMmsMtm->CreateMessageL(iMmsMtm->DefaultServiceL()) ...
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"); iMmsMtm->SetSubjectL(KMessageSubject);
The next step 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.SetInPreparation(EFalse); ent.SetVisible(ETrue); // Mark as visible, so this the message can be seen in Drafts iMmsMtm->Entry().ChangeL(ent); // Commit changes //Save the changes iMmsMtm->SaveMessageL();
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.
iMmsMtm->SetMessagePriority(EMmsPriorityHigh); //Save the changes iMmsMtm->SaveMessageL();
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.
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(); CleanupStack::PushL(store); // 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); attachmentFile.Append(KDirPictures); attachmentFile.Append(KFileName); // Open the attachment file RFile attachment; TInt error = attachment.Open(CCoeEnv::Static()->FsSession(), attachmentFile, EFileShareReadersOnly | EFileRead); CleanupClosePushL(attachment); // Check that the attachment file exists. if(error != KErrNone) { _LIT(KFileNotFound, "Attachment file not found!"); attachment.Close(); CleanupStack::PopAndDestroy(attachment); CleanupStack::PopAndDestroy(store); return EFalse; } else { // Mime header CMsvMimeHeaders* mimeHeaders = CMsvMimeHeaders::NewL(); CleanupStack::PushL(mimeHeaders); mimeHeaders->SetSuggestedFilenameL(KFileName); // Represents a single attachment and information about the attachment CMsvAttachment* attaInfo = CMsvAttachment::NewL(CMsvAttachment::EMsvFile); CleanupStack::PushL(attaInfo); // Mime Type _LIT8(KMimeType, "image/jpeg"); TBufC8<10> mimeType(KMimeType); // Attachment file must be in a public folder (e.g. c:\Data\images) iMmsMtm->CreateAttachment2L( *store, attachment, mimeType, *mimeHeaders, attaInfo, 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 store->CommitL(); attachment.Close(); CleanupStack::PopAndDestroy(attachment); CleanupStack::PopAndDestroy(store); // Save the changes iMmsMtm->SaveMessageL(); }
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"> <head> <layout> <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"/> </layout> </head> <body> <par dur="10s"> <img src="mmsexample.jpg" region="Image" /> <text src="hello.txt" region="Text" /> </par> </body> </smil>
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.
iMmsMtm->SetMessageRootL(smilAttachId);
Note that after setting the root, the changes to the store should be committed and the message saved.
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; }
Assuming that the MMS message has been created and validated, sending a
message using MMS Client MTM is 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()
method is called).
void CMtmsExampleEngine::SendMMSL() { iOp = iMmsMtm->SendL(iStatus); SetActive(); }
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.
The function is asynchronous and returns a CMsvOperation
pointer
to allow progress monitoring.
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); } break; case EMsvEntriesChanged: if(*(static_cast<TMsvId*>(aArg2)) == KMsvGlobalInBoxIndexEntryId) { CMsvEntrySelection* entries = static_cast<CMsvEntrySelection*>(aArg1); if(iNewMessageId == entries->At(0)) { iMmsMtm->SwitchCurrentEntryL(iNewMessageId); iMmsMtm->LoadMessageL(); TPtrC sender = iMmsMtm->Sender(); // Use the sender information ... } } break; ... } }
Further information about the general messaging concepts that are needed to understand this example can be found in the SDK documentation and at Forum Nokia.
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); CleanupStack::PushL(entry); CMsvStore* store = entry->ReadStoreL(); if(store!= NULL) { CleanupStack::PushL(store); MMsvAttachmentManager& attManager = store->AttachmentManagerL(); _LIT8(KMimeBuf, "text/plain"); TBuf8<10>mimeBuf(KMimeBuf); // Cycle through the attachments for(TInt i=0; i<attManager.AttachmentCount(); i++) { CMsvAttachment* attachment = attManager.GetAttachmentInfoL(i); CleanupStack::PushL(attachment); // 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 ... } CleanupStack::PopandDestroy(attachment); } Cleanupstack::PopAndDestroy(store); } CleanupStack::PopAndDestroy(entry);
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.
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 or 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() { iMmsMtm->SwitchCurrentEntryL(iMessageToReplyTo); iMmsMtm->LoadMessageL(); // 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); SetActive(); }
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 or 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 iMmsMtm->SwitchCurrentEntryL(indexEntry); iMmsMtm->LoadMessageL(); // Here add further recipients, subject, attachments // to the message ... // Commit the changes and save the Message TMsvEntry ent = iMmsMtm->Entry().Entry(); ent.SetReadOnly(EFalse); // Set InPreparation to false ent.SetInPreparation(EFalse); ent.SetVisible(ETrue); // mark as visible iMmsMtm->Entry().ChangeL(ent); // Commit changes //Save the changes iMmsMtm->SaveMessageL(); } } }
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 at least Client MTM, the MTM registry and the session are required. They should be deleted in the reverse order in which they were created.
CMtmsExampleEngine::~CMtmsExampleEngine() { // 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 }
The leave mechanism of the Symbian platform is used to handle error conditions on method calls. In addition, messaging defines a series of panics; these are explained in Symbian OS reference » System panic reference » MSGS.
ID | Identifier |
API | Application Programming Interface. |
MIME | Multipurpose Internet Mail Extensions. |
MMS | Multimedia Messaging Service. Protocol defined by 3GPP. Messaging for
text, images, audio. |
MTM | Message Type Module. A group of components that together provide message
handling for a particular protocol. |
SDK | Software Development Kit. |
SMIL | Synchronized Multimedia Integration Language. A markup language designed
to present multiple media files together. |
SMS | 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. |
UI | User Interface. |
Name | Location |
Synchronized Media Integration Language (SMIL) |