|
||
The Short Messaging Service (SMS) provides short text messaging between mobile phones. Messages can be written and read by phone users, and can also be used as a medium for communicating between applications.
Symbian OS until v8.0 supplied functionality for SMS over GSM networks. v8.1 continues to support GSM, and adds support for SMS on CDMA2000 networks. The CDMA SMS standard, defined by the 3GPP2, in standard C.S0015-A, derived from the TIA/EIA standard, TIA/EIA-637-B, defines broadly similiar functionality to GSM, but has differences in architecture and in data structures.
This document concentrates on using SMS through messaging APIs in a CDMA context. It contains the following sections:
CDMA SMS overview provides a summary of the CDMA SMS protocol
Architecture overview describes the main components and classes used in SMS messaging
Project files describes what clients of the MTM need to put in their mmp project files
Client MTM operations describes how to use SMS MTM API for creating and sending messages
TMsvEntry settings describes the use of message server index entries with SMS
SMS services describes how to use service entries to supply defaults for new SMS messages
Over-The-Air settings describes how to read the SMS settings set by the network operator
Acknowledgements describes how to set options for getting acknowledgements to sent messages and how to know that acknowledgements have arrived
Incoming messages describes how an application can handle incoming SMS messages
Common GSM/CDMA message fields describes message fields that can be used with both GSM and CDMA
CDMA-specific message fields describes message fields that can be used only with CDMA
EMS describes how to create and handle Enhanced Messaging Service messages
Send As support describes how to use Send As to send SMS messages
Example describes how to build and run the example accompanying this document
For information on related areas of Symbian OS, see:
For SMS standards, see:
GSM SMS standard on ETSI website (requires registration).
A CDMA SMS message belongs to one of three message definitions:
Point-to-point messages are for sending messages between phones. Such messages includes addressing information and a structured data area, which can include fields that describe various message properties, as well as the user data (i.e. the message contents to display to the user). The SMS MTM allows you to send point-to-point messages and handle incoming messages.
Acknowledge messages exist to pass status information. They simply contain a cause (error) code. The creation and receipt of acknowledge messages is handled at a lower level than the MTM, by the SMS stack.
Broadcast messages are sent from the network to all phones in a certain geographical area. They cannot be sent from a phone. The CDMA SMS MTM currently does not support broadcast messages.
A point-to-point message can have a teleservice identifier to specify the application that should handle it. The standard defines the operation of six teleservices.
The Wireless Messaging Teleservice (WMT) is for short text messaging between users. The Wireless Enhanced Messaging Teleservice (WEMT) extends this to include EMS elements such as pictures. Outgoing messages of these two teleservices can be created. Incoming messages of these teleservices are stored in the message store.
Other teleservices defined are: IS-91 Extended Protocol Enhanced Services, Wireless Paging Teleservice (WPT), Voice Mail Notification (VMN), and Service Category Programming Teleservice (SCPT). Incoming WPT and VMN messages are stored in the message store.
The fields in a message depend on the teleservice being used, and the message type. The most important types are the Deliver type, which is used for a message sent to a phone, and the Submit type, which is used for a message sent from a phone. There are also the following types:
Cancellation: from the phone to the Message Center to cancel a submitted message.
User Acknowledgment: sent from a phone that has received a message to the submitter to inform it that the user has acknowledged the message.
Delivery Acknowledgment: sent from the Message Center to inform the phone of the status of a submitted message.
Read Acknowledgment Message: sent from a phone that has received a message to the submitter to inform it that the user has opened the message.
Incoming acknowledgement messages are handled automatically by messaging. The SMS MTM makes available APIs, described in Acknowledgements, that allow you to find what acknowledgements have been received in response to an outgoing message.
Not all teleservices use all message types: for example, WPT does not support message cancellation, so does not use the Cancellation message type.
Finally, you should be aware that fields are often optional, so even if a field is appropriate to the teleservice and the message type, it may not be present in a message. The CDMA SMS 3GPP2 standard supplies tables of which fields apply to which teleservices and message types.
The messaging SMS plug-in (MTM) integrates SMS into the messaging architecture, so that SMS can be used by a messaging client program in a similar way to other message types such as email and fax. The following diagram shows the key components and their relationships:
SMS MTM component relationships
Components supplied by SMS messaging are in blue; other significant components are in grey.
The SMS client MTM implements the messaging architecture's client MTM API to provide the interface for applications to handle SMS messages. It provides:
encapsulation of SMS messages stored in the message server store, so that the message content and properties can be read and set
functions that allows messages to be created, replied to, and forwarded, and commands relating to phone storage of SMS messages to be given.
encapsulation of settings for sending and receiving messages, and for default properties to give to new messages
Note that UI functionality, such as SMS message viewing and editing, is not provided by Symbian OS, but the platform user interface.
The SMS server-side MTM implements the server-side MTM interface, and primarily provides functionality to handle requests from the client MTM to send SMS messages.
Incoming SMS messages are handled by a group of components called SMS watchers. For CDMA, each watcher handles a particular teleservice, respectively WMT, WPT, WEMT, and VMN. The watchers handle the four possible types of incoming SMS, i.e. the Deliver type, and the three possible acknowledgement types, Read, User, and Delivery. When a deliver type SMS is received for one of these teleservices, the watcher creates a new message entry in the Inbox. When an acknowledgement type SMS is found, the watcher finds the message that is being acknowledged, and updates its relevant acknowledgement fields to record that an acknowledgement has been received. The acknowledgement message itself is not stored in the message store.
These messaging components provide a layer over the SMS support provided in the narrow band protocols stack subsystem. This has SMS stacks for GSM and for CDMA, which offer an encapsulation of an SMS message, together with the ability to send and receive messages. At the lowest level, below the SMS stacks, is the ETel multimode API, which provides low-level access to the phone drivers.
So, for an incoming message, the usual route is:
the phone receives the SMS. The telephony server notifies the SMS stack.
the SMS stack decodes the message and then notifies the SMS watcher that handles messages of the relevant teleservice. The watcher creates a new messaging entry in the message store's Inbox.
any messaging application that is set as an observer of the message store is notified of the arrival of the new message. The application can then determine whether it should handle the message, and if so, can then read the message and process it appropriately.
For an outgoing message, the route is:
a messaging application uses the SMS client MTM APIs to create a message, to set its contents and fields, and to send it
the message server passes the send command to the SMS server MTM. This calls the appropriate SMS stack to send the message.
the stack calls the telephony server to send the message.
The MTM source code has been designed to conditionally include or exclude functionality for GSM/CDMA according to whether certain macros are defined. The macros are:
CDMA_API_ENABLED
: the exported CDMA API will be
operational when defined, otherwise exports leave with
KErrNotSupported
GSM_API_ENABLED
: the exported GSM API will be
operational when defined, otherwise exports leave with
KErrNotSupported
GSM_COMPATIBILITY_MODE
: includes all existing
inline functions required for compatibility with the GSM MTM API. If not
defined, some inlines will not be present or declared as private.
The following diagram shows the key classes in the SMS client MTM:
SMS MTM class relationships
Classes in the client MTM are in blue; significant classes from components other than the MTM are in grey.
The following table summarises the classes:
Class |
Purpose |
|
Implements the messaging architecture client MTM interface for SMS. It allows messages to be created, replied to, and forwarded, and MTM-specific commands to be given. It provides an accessor function |
|
Encapsulates an SMS message in a message store. It provides information about message recipients as an array
of
For compatibility with the API of the v8 (GSM only) SMS MTM,
it also provides access to the GSM SMS stack's message class
|
|
Base class for a family of classes that provide access to message fields. |
|
Provides access to message fields that are compatible with both GSM and CDMA. |
|
Provides access to GSM-specific fields. |
|
Provides access to CDMA-specific fields. |
|
Provides a specialisation of the message server index class
Putting selected SMS-specific fields in the index entry allows message clients to quickly get important message properties without having to create a message object. |
|
Encapsulates recipient information for an SMS message. |
|
Defines settings for the SMS service. It contains some GSM-specific functions to maintain compability with the GSM SMS MTM. It also provides access to
|
|
This is now deprecated and kept for backward compatibility. |
|
Provides defaults for outgoing messages, both GSM and CDMA. It also provides access to an additional object for
CDMA-specific settings,
|
|
Defines CDMA-specific settings for outgoing messages. |
Clients of the API should specify the following in their project files:
Linkage against the messaging and SMS client MTM libraries:
LIBRARY msgs.lib smcm.lib
The following macros to ensure that all relevant declarations in the MTM headers are included.
MACRO GSM_COMPATIBILITY_MODE
MACRO CDMA_API_ENABLED
The following include paths:
SYSTEMINCLUDE \epoc32\include\messaging\sms
SYSTEMINCLUDE \epoc32\include
The order of the system includes is important, so that headers for the CDMA MTM are found before the GSM MTM headers
The SMS client MTM provides an API that allows applications to create and send SMS messages, and to access the properties and fields of a message. This section discusses these tasks:
See Using Messaging for general background information on the messaging APIs if you are not already familiar with them.
The messaging framework is based around a server program, to
which a connection (a session) must be made before anything else with messaging
can be done. The session class is called
CMsvSession
, and message client applications
typically create an instance of this class upon start-up.
// Create message server session
iMsvSession = CMsvSession::OpenSyncL(*this);
The OpenSyncL()
method takes a parameter of type
MMsvSessionObserver
, so, for this code to work,
the containing class must implement this observer interface. It enables the
server to call the client to inform it of significant events, such as new MTMs
being registered.
An application should then get an
CSmsClientMtm
object. This cannot be created
directly: instead, an application must ask the message server to create the
object for it. A record of all the MTM components installed on a machine is
held in a dedicated registry file managed by the message server. Registry
classes use this registration data to allow MTM components to be identified and
instantiated.
To get a SMS client MTM object, use
CClientMtmRegistry
as follows:
// Create client registry object
iClientMtmRegistry = CClientMtmRegistry::NewL(*iMsvSession);
// Request SMS client MTM object
iSmsClientMtm = (CSmsClientMtm *)iClientMtmRegistry->NewMtmL(KUidMsgTypeSMS);
The registry NewMtmL()
function returns a pointer to
the client MTM base class,
CBaseMtm
, so it needs to be cast to the SMS
client class,
CSmsClientMtm
.
Each MTM type is identified by a UID, which is used to specify
the MTM in the NewMtmL()
call. For SMS, this UID is
KUidMsgTypeSMS
.
There are several ways to create new messages:
The simplest way is to use the Client-side MTM
CreateMessageL()
function. The message created is of the Submit
type, of the default teleservice, and has the default settings for the service
applied. See
Creation with CreateMessageL().
By creating a generic
CMsvEntry
message entry, and initialising it
appropriately. This allows messages of types other than Submit, and for
teleservices other than the default to be created. See
Creation using CMsvEntry for a general description. For particular message types, see
also
Creating read and user acknowledgement messages and
Creating cancellation messages.
By forwarding or replying to an existing message. See Forward/reply messages.
These are explained in more detail below.
A client MTM has the concept of a current entry, or context,
on which operations, such as message creation, take place. A new outgoing
message should be created in the Outbox folder, so this current entry needs to
be set to that folder. The identifier for the Outbox folder is published in the
API, and is KMsvGlobalOutBoxIndexEntryId
. The following call sets
the current entry to this folder, and then creates a new SMS message:
// Set context to Outbox folder
iSmsClientMtm->SwitchCurrentEntryL(KMsvGlobalOutBoxIndexEntryId);
// Create new message entry
iSmsClientMtm->CreateMessageL(0);
CreateMessageL()
is a virtual function that is
specified by the base class
CBaseMtm
to take a parameter for the message
ID of the service that should own the entry. However, this parameter is not
used in the SMS MTM implementation: instead, the MTM assumes that a single SMS
service exists and that this service should be used.
The teleservice to which outgoing message belong is set at the
service level (CSmsSettings::DefaultTeleservice()
).
To create a message other than the Submit type, or for a
teleservice other than the default, you need to create and initalise a message
entry using
CMsvEntry
. Typical steps are:
Set up an
TMsvEntry
index entry for the new entry.
The entry is made invisible and in preparation.
// set up index entry
TMsvEntry newEntry;
newEntry.iType = KUidMsvMessageEntry;
newEntry.iServiceId = KMsvLocalServiceIndexEntryId;
newEntry.iMtm = KUidMsgTypeSMS;
newEntry.SetVisible(EFalse);
newEntry.SetInPreparation(ETrue);
Create a new empty message. The following creates an entry in the outbox:
// create empty message in outbox
CMsvEntry* entry = iMsvSession->GetEntryL(KMsvGlobalOutBoxIndexEntryId);
CleanupStack::PushL(entry);
entry->CreateL(newEntry);
iMsvSession->CleanupEntryPushL(newEntry.Id());
// switch to created entry
entry->SetEntryL(newEntry.Id());
Create a
CSmsHeader
object, configure it, and store
it in the entry's message store. There are a number of overloads for
CSmsHeader::NewL()
. For outgoing CDMA
messages, use:
static CSmsHeader* NewL(TSmsMessageType aType, CEditableText& aText);
or
static CSmsHeader* NewL(TSmsMessageType aType, CEditableText& aText, tia637::TTeleserviceId aTeleservice);
aType
specifies the type: e.g.
KSmsTypeCdmaUserACK
for a user acknowledgement; aText
is the message text; and aTeleservice
specifies the teleservice
identifier, defined in the CDMA SMS stack header tia637.h
. The
following example:
creates a rich text object for the message text
creates a
CSmsHeader
object for a Submit message
for the WEMT teleservice. It calls SetDefaultMessageSettingsL()
to
apply the default settings stored by the
SMS service.
opens the entry's message store, and commits the header object to it.
// create a rich text body
CParaFormatLayer* paraFormatLayer = CParaFormatLayer::NewL();
CleanupStack::PushL(paraFormatLayer);
CCharFormatLayer* charFormatLayer = CCharFormatLayer::NewL();
CleanupStack::PushL(charFormatLayer);
CRichText* richText = CRichText::NewL(paraFormatLayer,charFormatLayer);
CleanupStack::PushL(richText);
// ... can set message text in richText now
// create the header object
CSmsHeader* smsHeader = CSmsHeader::NewL(KSmsTypeSubmit, *richText, tia637::KTeleserviceWEMT);
CleanupStack::PushL(smsHeader);
smsHeader->SetDefaultMessageSettingsL(aServiceSettings);
// .. configure further as required
// set the message header in the entry's store
CMsvStore* store = entry->EditStoreL();
CleanupStack::PushL(store);
smsHeader->StoreL(*store);
store->StoreBodyTextL(*richText);
store->CommitL();
CleanupStack::PopAndDestroy(5);
The next two sections describe what more needs to be done to create acknowledgement and cancellation messages.
Incoming CDMA SMS messages can request that user or read acknowledgement messages are sent in response. A messaging application may need to create such messages, for example, when a message is read for the first time. Note that these acknowledgements are specific to CDMA, and are not supported in GSM SMS.
To create an acknowledgement message:
Test if the received message requests a user or read acknowledgement (the third type of acknowledgement, delivery acknowledgement, is handled by the service center.)
To do this, load the received message, and get its
CSmsHeader
object.
mtm->LoadMessageL();
CSmsHeader& smsHdrRecv = static_cast<CSmsClientMtm*>(iMtm)->SmsHeader();
You can then test if the received message requests an
acknowledgement using
CSmsHeader::AcknowledgementRequested()
,
i.e.:
TBool ackRequest = smsHdrRecv.AcknowledgementRequested(ESmsAckTypeUser);
or
TBool ackRequest = smsHdrRecv.AcknowledgementRequested(ESmsAckTypeRead);
If an acknowledgement is requested, the next step is to get information from the received message that will be needed to create the acknowledgement message.
First, get the received message's teleservice. This can be
read from the message's properties accessible through
TMsvMessageCdma
:
TMsvMessageCdma& msgCdma = smsHdrRecv.CdmaMessage();
tia637::TTeleserviceId tid = msgCdma.TeleserviceId();
Second, get the received message's originating address:
TPtrC originatingAddress = msgCdma.OriginatingAddress();
(OriginatingAddress()
is from
TMsvMessageBio
, which is a base class for
TMsvMessageCdma
).
Third, get the received message's message identifier. This
identifier is a CDMA SMS message property that allows a sent message to be
referred to. An acknowledgement message uses the same identifier to indicate
which message is being acknowledged. The identifier is stored in the message
entry fields that are accessible through TMsvSmsEntry
:
TMsvSmsEntry entryRecv = (TMsvSmsEntry)(iMtm->Entry().Entry());
TInt32 incomingId = 0;
entryRecv.MessageId(incomingId);
An acknowledgement message can now be created with
CMsvEntry
using the procedure described
above, with the following adjustments:
The
CSmsHeader
for the new message should
have the message type set to either KSmsTypeCdmaUserACK
or
KSmsTypeCdmaReadACK
depending on the acknowledgement requested,
and the teleservice be set to that of the received message:
// create the header object
CSmsHeader* smsHeader = CSmsHeader::NewL(KSmsTypeCdmaReadACK, *richText, tid);
The destination address of the message should be set to the orginating address of the received message, and its message identifier to that of the received message:
// Set destination address
CSmsNumber* smsNumber = CSmsNumber::NewL();
CleanupStack::PushL(smsNumber);
smsNumber->SetAddressL(originatingAddress, EMsvAddressTypeISDN);
// Set message identifier
TSmsMessageIdentifier outgoingId = incomingId;
smsNumber->SetMessageId(outgoingId);
// Add recipient
smsHdr->Recipients().AppendL(smsNumber);
CleanupStack::Pop(smsNumber); // deleted by CSmsHeader
A cancellation message is used to cancel a message that has
been sent. A cancellation message can be created with
CMsvEntry
using the procedure described above,
with the following adjustments:
The
CSmsHeader
for the new message should have
the message type set to KSmsTypeCdmaCancellation
, and its
teleservice set to that of the sent message.
The recipients of the cancellation message should be set to the recipients of the sent message. These can be obtained by restoring the sent message.
// Get the recipients of the message to cancel
// where messageToCancelId is the TMsvID of that message
iMtm->SwitchCurrentEntryL(messageToCancelId);
CMsvStore* currStore = iMtm->Entry().ReadStoreL();
CleanupStack::PushL(currStore);
CSmsHeader* currMsg = CSmsHeader::RestoreL(*currStore, rtBody->RichText());
CleanupStack::PopAndDestroy(currStore);
CleanupStack::PushL(currMsg);
CArrayPtrFlat<CSmsNumber>& currNumbers = currMsg->Recipients();
// Get the message's teleservice
tia637::TTeleserviceId teleservice = currMsg->CdmaMessage().TeleserviceId();
// create the new message
CSmsHeader* smsHdr = CSmsHeader::NewL(KSmsTypeCdmaCancellation, *richText, teleservice);
CleanupStack::PushL(smsHdr);
// set its recipients
for (TInt i = 0; i < currNumbers.Count(); i++)
{
CSmsNumber* smsNumber = CSmsNumber::NewL(*(currNumbers[i]));
CleanupStack::PushL(smsNumber);
smsHdr->Recipients().AppendL(smsNumber);
CleanupStack::Pop(smsNumber); // CSmsHeader will delete it
}
CleanupStack::Pop(smsHdr);
CleanupStack::PopAndDestroy(currMsg);
CleanupStack::PushL(smsHdr);
// set anything further in CSmsHeader...
CleanupStack::PopAndDestroy(smsHdr);
You can also create new messages by forwarding or replying to
an existing SMS message, through
CSmsClientMtm::ForwardL()
and
CSmsClientMtm::ReplyL()
respectively. In these
cases, the new message is created for you, with the appropriate content copied
into it from the original message.
The message text can be set and accessed as a rich text object
(CRichText
) through Body()
. For example, the
following sets the body text to be "some message text":
_LIT(KText,"some message text");
CRichText& body = iMtm->Body();
body.InsertL(0,KText);
Note that:
any formatting in the rich text is ignored.
the encoding of the messages can be set using
TMsvMessageBio::SetEncoding()
. A default is
set by the message settings held in the SMS service (see
SMS services).
Every outgoing message must be addressed to a recipient. Although the SMS protocol does not allow a message to be addressed to more than one recipient, the SMS MTM does allow this. When a SMS message entry with more than one recipient is sent, the server MTM creates and sends a separate SMS message for each recipient.
The simplest way to add an address is to use
CBaseMtm::AddAddresseeL()
.
iMtm->AddAddresseeL(address);
An array of recipients for the current message can be obtained
from the SMS header object,
CSmsHeader
. Each object in the array is a
CSmsNumber
. In addition to the address, this
class holds:
acknowledgement information: the sender of an CDMA SMS
message can request acknowledgement of the message. Information about the
acknowledgements received can be accessed for each recipient through
CSmsNumber
. The details are discussed later
in
Acknowledgements.
a message identifier: each message is given an identifier when it is sent (this allows the message to be referred to in various circumstances). As a separate message is sent for each recipient, a different identifier is associated with each recipient.
The following code shows creating an address using
CSmsNumber
, and adding it to the recipient
array:
_LIT(KAddress,"0123456789");
CSmsHeader& header = iMtm->SmsHeader();
CArrayPtrFlat<CSmsNumber>& recips = header.Recipients();
CSmsNumber* newRecip = CSmsNumber::NewL();
CleanupStack::PushL(newRecip);
newRecip->SetAddressL(KAddress, EMsvAddressTypeISDN);
recips.AppendL(newRecip);
CleanupStack::Pop(newRecip); //CSmsHeader will delete it
ISDN addresses both have maximum lengths that are set as part of
the phone's provisioned settings (see
Over-The-Air settings). If the
maximum length is exceeded, the error behaviour differs depending on whether
the MTM was compiled with GSM_COMPATIBILITY MODE
: if it was, ISDN
addresses gets trimmed down to the maximum length; if not, the function leaves
with KErrTooBig
.
In addition to a message body and address, a message can have various other fields, such as priority level, privacy setting, and delivery time information. Fields can typically be set on outgoing messages, and read from incoming messages.
Which fields are available depends on whether GSM or CDMA is
being used. Fields common to both are accessible through
TMsvMessageBio
and its derived class
TMsvMessageSms
. This can be got as
follows:
TMsvMessageSms& fields = iMtm->SmsHeader().SmsMessage();
Common GSM/CDMA message fields describes these fields in detail.
CDMA specific fields are accessible through
TMsvMessageCdma
, which derives from
TMsvMessageSms
. It can be got as follows:
TMsvMessageCdma& CDMAFields = iMtm->SmsHeader().CdmaMessage();
CDMA-specific message fields describes these message fields in detail.
Be careful about the lifetime of the returned references to
TMsvMessageSms
or TMsvMessageCdma
objects. If a
message's CSmsHeader
object is deleted, then these references will
become invalid, and using them will cause an undefined error (such as a
KERN-EXEC 3 panic).
Various fields are set to default values when a new message is created. The defaults are set in the service settings.
Once a message has been set up, it can be sent by copying the
message to the SMS service. This can be done using
CMsvEntry::CopyL()
. The following copies the MTM's current entry,
whose ID is obtained using iSmsClientMtm->Entry().EntryId()
, to
the service, whose ID can be got from the MTM using
ServiceId()
.
iSendOperation = ent->CopyL(iSmsClientMtm->Entry().EntryId(), iSmsClientMtm->ServiceId(), iStatus);
The function is asynchronous, and so takes a
TRequestStatus
parameter, usually of an active object in your
program whose RunL()
is called when the operation is
complete.
The function returns a
CMsvOperation
object, which can be used to
monitor the sending progress (TSmsProgress
) and to obtain
any error information.
Progress information includes fields for the total number of messages being handled by the operation, and the number of messages processed so far; as each message is processed, it also updates fields for the total number of recipients of the message, and the number of recipients processed so far.
Final progess information can be obtained when an operation has completed. For example, the following gets the final progress information after a send operation, and displays the number of messages sent out of the total attempted, and the error if any was reported.
// get progress information after send operation completes
TSmsProgressBuf progressBuf;
progressBuf.Copy(iSendOperation -> FinalProgress());
TSmsProgress progress = progressBuf();
TBuf<40> msg1;
TBuf<20> msg2;
msg1.Format(_L("\nSent %d of %d messages"),progress.iMsgDone, progress.iMsgCount);
if (progress.iError) msg2.Format(_L("Error: %d"), progress.iError);
CEikonEnv::Static()->AlertWin(msg1, msg2);
The SMS MTM has the ability to:
schedule messages to be sent at a specified later time.
check that specified conditions are met before sending
resend messages if an error occurs in sending, or if the specified conditions are not met
The sections below describe each of these.
To set a message to be sent at a specified later time:
set the time to send in the message's
TMsvEntry::iDate
create a selection (CMsvEntrySelection
)
with the message(s) to send. Every message in the selection must have the same
scheduled time.
call
CSmsClientMtm::InvokeAsyncFunctionL()
with
command ID ESmsMtmCommandScheduleCopy
The following schedules a message with ID
aID
:
CMsvEntrySelection* smsEntries = new (ELeave) CMsvEntrySelection;
CleanupStack::PushL(smsEntries);
smsEntries->AppendL(aId);
TBuf8<1> p;
CMsvOperation* op = iMtm->InvokeAsyncFunctionL(ESmsMtmCommandScheduleCopy,
*smsEntries, p, status);
CleanupStack::PopAndDestroy(); //smsEntries
Note that:
When the scheduled task occurs, not only will the selected messages be sent but also any waiting SMS messages in the Outbox.
If the messages are successfully sent by the scheduled task, then all the sent messages are moved to the Sent folder.
Messages can be removed from the scheduler with the asynchronous
function ID ESmsMtmCommandDeleteSchedule
.
When preparing to start sending SMS messages. the SMS server MTM
checks that any specified send conditions are met. The send conditions are
defined using a set of conditions
(TMsvSysAgentConditionAction
objects). The conditions are
held in a
CMsvSysAgentActions
object, which is stored in
the SMS service entry. By default, there are no send conditions specified. If
none have been specified, then the conditions are considered to have been
met.
A
TMsvSysAgentConditionAction
contains:
A condition, a
TMsvCondition
object
The action (TMsvSendErrorAction
) to take
if the condition is not met.
The possible actions, defined in
TMsvSendAction
include failing the send,
re-scheduling the message to be resent after a short interval, long interval,
or when the send conditions are met.
A flag indicating whether the default action should be taken.
The default action is owned by the
CMsvSysAgentActions
class.
The following example shows a condition being set. The condition
is met if the KUidNetworkStatus
variable is equal to
ESANetworkAvailable
. If the condition is not met, the action is to
retry the send after a long interval, and to keep trying until the send is
successful.
CMsvSysAgentActions* actions = new (ELeave) CMsvSysAgentActions();
CleanupStack::PushL(actions);
actions->iDefault.iAction = ESendActionRetryLater;
actions->iDefault.iRetries = ESendRetriesInfinite;
TMsvSysAgentConditionAction action;
action.iCondition.iVariable = KUidNetworkStatus;
action.iCondition.iState = ESANetworkAvailable;
action.iCondition.iType = TMsvCondition::EMsvSchSendEquals;
actions->AppendL(action);
// Store the actions in the SMS service entry
CMsvEntry* service = Session().GetEntryL(aServiceId);
CleanupStack::PushL(service);
CMsvStore* msvstore = service->EditStoreL();
CleanupStack::PushL(msvstore);
actions->StoreL(*msvstore);
msvstore->CommitL();
CleanupStack::PopAndDestroy(3, actions);
A message can be rescheduled at two stages of sending:
If send conditions are not met: as seen above, the behaviour when this occurs is configured as part of the the send actions.
If sending to any recipient fails: the behaviour in this
event is determined by a
SEND_ERROR_ACTIONS
resource
in the SMS server MTM resource file (modifiable by the licensee but not by
third-parties). This specifies possible error codes, and the action that should
be taken if that error occurs.
Note that there are two addtional factors that can prevent rescheduling occurring:
In order to avoid an infinite loop of attempting to send a
message, which may result in running the device battery down, a rescheduled
message can be limited to a maximum number of re-tries. If the maximum re-tries
is reached, then the message will be failed and marked as such. The maximum
number of re-tries is defined in the
CMsvSysAgentActions
error action.
A timeout can be specified for waiting for sending conditions to occur. If the timeout occurs before the conditions are met, then the pending SMS messages are marked as failed.
The timeout is configurable through the
CMsvScheduleSettings::SetPendingConditionsTimeout()
function. The
default is 0 (no timeout). The CMsvScheduleSettings
is a separate
stream in the SMS service entry store.
The SMS MTM provides InvokeAsyncFunctionL()
commands
to copy and move messages between the message server store and either the
phone's R-UIM (Removable User Identity Module), or built-in memory (referred to
as the phone store).
Getting messages from a R-UIM/phone store is a two stage process.
First, you need to use the command
ESmsMtmCommandEnumeratePhoneStores
. This reads the SMS messages on
the R-UIM or phone store, and creates a copy of those messages in an invisible
folder in the message store. You can specify whether to read from the R-UIM or
phone store (the enum
TMsvSmsStorage
gives flags for each), and the
target folder in the message store. These parameters are passed to
InvokeAsyncFunctionL()
in a packaged
TMsvSmsSimOperationParams
object.
Once enumeration has taken place, further
InvokeAsyncFunctionL()
commands can be used to:
copy messages to a specified message store folder:
ESmsMtmCommandCopyFromPhoneStore
move messages to a specified message store folder:
ESmsMtmCommandCopyFromPhoneStore
delete messages:
ESmsMtmCommandDeleteFromPhoneStore
Copying or moving messages in the other direction is simpler: to
do this, use the InvokeAsyncFunctionL()
commands
ESmsMtmCommandCopyToPhoneStore
or
ESmsMtmCommandMoveToPhoneStore
.
Each SMS message has an message store index entry that can be
accessed through TMsvEntry
. The index entry allows an application
quick access to important properties of the message.
The table below describe the functions and member variables for
TMsvEntry
that are set by the SMS MTM for an SMS
message:
|
Description |
|
Not used by SMS MTM |
|
Not used by SMS MTM |
|
Normally set to This flag is set to |
|
For normal (i.e. non-BIO) SMS text messages, this is the
beginning of the text message, discarding any leading white space characters.
The maximum length of the description can be got from
For BIO message ( |
|
The full telephone “address” of the first name in the list of recipients. This may either be a telephone number, or it may be the contact name of the recipient, if that recipient appears in the Symbian OS contact database. |
|
If the MTM is unable to send a message, then the
If there is more than one recipient of the message, the flag will be set if the message fails to be sent to any of the recipients. The If the flag has been set, the Note that successfully sending an SMS message to the message/service centre does not mean that the message is guaranteed to be delivered to the recipient(s). |
|
Specifies or identifies the type of the BIO message. If When In outgoing SMS messages, if |
|
The time and date the message was originally created. After an attempt has been made to send the message,
|
|
Any error code which occurred when an attempt was made to
send the message (normally |
|
The MTM type, which is always
|
|
Reserved. |
|
Reserved |
|
Reserved |
|
This is set to true when a new outgoing message is created. The application should set the flag to false when it has finished creating the message. This is also set to true when a watcher creates a new incoming message; it is set to false when creation is complete. |
|
Not used by SMS MTM. |
|
Identifies the SMS service that created the message. There is normally only one SMS service in the message store. |
|
Size, in bytes, of the message. |
|
Set to
|
|
Not used by SMS MTM. |
|
Not used by SMS MTM. |
|
Not used by SMS MTM. |
|
Not used by SMS MTM. |
|
Not used by SMS MTM. |
|
Not used by SMS MTM. |
|
This is set to true by the watcher for incoming SMS messages. |
|
Set to |
|
The sending status of the message. The value of this status will depend upon whether the message
has been scheduled to be sent using the task scheduler. The states are defined
by
|
|
Not used by SMS MTM. |
|
When new SMS messages have been received by the SMS watcher,
the It is the responsibility of the reading client to reset the flag once it has been read/processed. |
|
This is set to false when a new outgoing message is created. The application should set the flag to true when it has finished creating the message. |
The
TMsvSmsEntry
class provides a specialisation of
the message server index class for SMS message entries.
Acknowledgements below discusses
how this can be used to retrieve acknowledgement summaries.
An SMS service entry holds two types of information:
general settings for sending and retrieving SMS messages
default settings applied to new outgoing messages
A SMS service is stored as a message entry with the following characteristics:
Positioned as a child of the root entry.
Has an index entry with the following fields:
|
Description |
|
Set by the SMS MTM to |
|
Set to
|
|
Set to
|
|
Normally set to |
Other index entry fields are not used for an SMS service.
Contains in its message store a
CSmsSettings
object that holds the
settings.
The following code shows how a service that meets the above criteria would be created:
CMsvEntry* entry = iMsvSession->GetEntryL(KMsvRootIndexEntryId);
CleanupStack::PushL(entry);
// set message index entry
TMsvEntry s;
s.iMtm = KUidMsgTypeSMS;
s.iType = KUidMsvServiceEntry;
s.SetVisible(EFalse);
// create new message entry
entry->CreateL(s);
entry->SetEntryL(s.Id());
// open store for entry
CMsvStore* store = entry->EditStoreL();
CleanupStack::PushL(store);
// create new settings object
CSmsSettings* set = CSmsSettings::NewL();
CleanupStack::PushL(set);
// .. make settings as needed here
// save settings in store, and commit store
set -> StoreL(*store);
store -> CommitL();
CleanupStack::PopAndDestroy(3);
Typically, a phone will have just one SMS service defined. When an SMS client MTM object is created, it finds this service and loads the settings from it.
A client can then access the
CSmsSettings
object using
CSmsClientMtm::ServiceSettings()
.
The ID of the service entry being used can be got with
CSmsClientMtm::ServiceId()
.
General settings for sending and retrieving SMS messages can be
manipulated using the member functions of
CSmsSettings
. These are as follows:
Display mode: the
MessageDisplayMode()
/SetMessageDisplayMode()
setting
controls how the phone displays received messages: the options are to display
immediately, or according to a default or user configured setting.
Digit mode: the
DigitMode()
/SetDigitMode()
setting controls the
default encoding for ISDN addresses. CDMA allows such addresses to be encoded
as either 4-bit DTMF codes or 8-bit ASCII codes.
Send As: the
DefaultTeleservice()
/SetDefaultTeleserviceL()
setting
controls the teleservice to which new messages created through Send As belong.
The options are WMT, WEMT, or WPT. For more details, see
Send As support.
Reply with orginal message: the
ReplyWithOriginalMessage()
/SetReplyWithOriginalMessage()
setting controls how an original message should be included in a reply.
Alert On Message Delivery: the
AlertOnDelivery()
/SetAlertOnDelivery()
functions
control the CDMA setting for alerting (e.g. vibrating, sound) when a message is
delivered
Preferred languages: the
PreferedLanguageList()
functions allow a list of preferred
languages for messages to be retrieved and set. The watchers will discard
messages that specify that they are in a language not in the list of preferred
languages.
Schedule send delivery: the
Delivery()
/SetDelivery()
setting controls the default
sending schedule type of a new message. See
Scheduled sending.
Quote reply: the
ReplyQuoted()
/SetReplyQuoted()
setting controls
whether the editor should quote the received message at the beginning of the
reply message.
CommDb: the
SetCommDbAction()
/CommDbAction()
setting controls
whether the service settings should be used to update the communications
database.
SMS bearer: the
SetSmsBearer()
/SmsBearer()
setting controls the
preferred bearer for SMS messages. The
SetSmsBearerAction()
/SmsBearerAction()
setting
controls whether this bearer setting should be used to update the
communications database.
The following service settings are kept for compatibility with the GSM MTM, but have no use in CDMA:
Service center addresses:
NumSCAddresses()
, SCAddress()
,
AddSCAddressL()
, RemoveSCAddress()
,
DefaultSC()
, SetDefaultSC()
Class 2 folder: SetClass2Folder()
,
Class2Folder()
Watcher actions:
StatusReportHandling()
/SetStatusReportHandling()
, and
SpecialMessageHandling()
/SetSpecialMessageHandling()
Default settings applied to new outgoing messages can be obtained
through
CSmsSettings
:
Call CSmsSettings::MessageSettings()
to get a
CSmsMessageSettingsProxy
object, which
stores settings relevant to both CDMA and GSM.
To get CDMA-specific settings, call in turn,
CSmsMessageSettingsProxy::Cdma()
. This
returns a
TSmsMessageSettingsCdma
object.
The common message settings accessible through
CSmsMessageSettingsProxy
are as follows:
Validity period: the message validity period
sets a time after which the message center should discard the message if it has
not been delivered to the destination. The time can be expressed either as an
absolute value
(AbsoluteValidityPeriod()
/SetAbsoluteValidityPeriod()
)
or relative to the time the message is received by the message center
(RelativeValidityPeriod()
/SetRelativeValidityPeriod()
).
The validity period format
(ValidityPeriodFormat()
/SetValidityPeriodFormat()
)
sets whether the absolute or relative setting is used.
The settings can be overriden for an individual message: see Validity period for more details.
Reply options: this setting, accessed through
ReplyOptions()
/SetReplyOptions()
, describes which
acknowledgements are requested.
Encoding: this setting, accessed through
Encoding()
/SetEncoding()
, identifies the default
character set used in SMS messages. Text is stored in Unicode on the Symbian OS
phone and is converted into the appropriate character set when the message is
sent.
The settings can be overriden for an individual message.
The CDMA-specific message settings in
TSmsMessageSettingsCdma
are as follows:
Priority: the
Priority()
/SetPriority()
setting controls the
priority level given to the message. There are four levels, from Normal to
Emergency.
This can be overriden for individual messages: see Priority for more details.
Privacy: the
Privacy()
/SetPrivacy()
setting controls the privacy
level given to the message. The possible levels are Unrestricted, Restricted,
Confidential, and Secret
This can be overriden for individual messages: see Privacy for more details.
Callback number: the
CallBackNumber()
/SetCallBackNumberL()
setting
controls sets the number which should be used to reply to the sent
message.
This can be overriden for individual messages: see Callback number for more details.
Alert On Message Delivery: the
AlertOnDelivery()
/SetAlertOnDelivery()
functions
control the CDMA setting for alerting (e.g. vibrating, sound) when a message is
delivered.
Language Indicator: the
Language()
/SetLanguage()
functions control the CDMA
setting to indicate the language of the message.
The
IsMessageSettingActive()
/ActivateMessageSetting()
functions controls whether a particular message setting is applied or not when
a new message is created.
Each phone on a CDMA network has OTA (Over-The-Air) settings that control the phone's behaviour. They are called OTA because the CDMA network can transmit new values for each setting at any time. You can think of them as the network's rules that govern how your phone should act.
Symbian OS's CDMA implementation monitors these settings and makes sure that your phone does not break any rules. Hence it is not essential that your code reads these settings. However, you may read them if you wish.
A number of these settings are relevant to the SMS client MTM. They are:
Enable/disable all SMS messages; see
KSMSMOSupported
and
KSMSMTSupported
Enable/disable various teleservices; see
KWEMTSupported
,
KWMTMOSupported
etc.
Maximum length of recipient's phone number and the call-back
phone number; see
KMaxRecipientPhoneNumLength
and
KMaxCallbackNumLength
Maximum number of recipients for each message; see
KMaxNumberOfSmsRecipients
Duplicate message filtering: see
KDuplicateMessageFiltering
Reading settings from your code explains how to read these settings. This is part of the Over-The-Air Settings Guide for CDMA Networks. You should never change any settings - only the network is allowed to do this.
The sender of an CDMA SMS message can request acknowledgement of the message. There are three acknowledgement types:
User Acknowledgment: sent from a phone that has received a message to the submitter to inform it that the user has acknowledged the message.
Delivery Acknowledgment: sent from the message center to inform the phone of the status of a submitted message.
Read Acknowledgment Message: sent from a phone that has received a message to the submitter to inform it that the user has opened the message.
The default reply options for new messages are set from the current
message settings
(CSmsMessageSettingsProxy::SetReplyOptions()
). Per message
settings can be made using
CSmsHeader::SetAcknowledgementRequest()
.
When an acknowledgement is received, the relevant watcher processes it, and updates acknowledgement fields on the sent message.
After the message has been sent, you can query the message to find what acknowledgements have been received. You can get details of the acknowledgements for each message recipient, and a summary of the acknowledgements received for all recipients.
Per recipient information is available through the
CSmsNumber
object for the recipient. The following
code starts a loop through a message's recipients and gets the status of the
delivery acknowledgement by calling
CSmsNumber::AckStatus(ESmsAckTypeDelivery)
:
const CArrayPtrFlat <CSmsNumber> & recipArray = iMtm->SmsHeader().Recipients();
for (TInt i=0; i<recipArray.Count(); i++)
{
TPtrC address = recipArray[i]->Address();
CSmsNumber::TSmsAckStatus ackStatus = recipArray[i]->AckStatus(ESmsAckTypeDelivery);
// do something with ackStatus
}
The returned
CSmsNumber::TSmsAckStatus
indicates whether the
acknowledgement has been received (indicating a success or failure) or not. The
following prints a message for each of the possible values:
switch (ackStatus)
{
case CSmsNumber::EPendingAck:
iConsole.Printf(_L("The delivery status for this recipient has been requested, but the status report has not yet been received."));
break;
case CSmsNumber::EAckSuccessful:
iConsole.Printf(_L("A successful acknowledgement for this recipient has been received."));
break;
case CSmsNumber::EAckError:
iConsole.Printf(_L("A failed acknowledgement for this recipient has been received."));
break;
case CSmsNumber::ENoAckRequested:
iConsole.Printf(_L("An acknowledgement for this recipient has not been requested."));
break;
default:
break;
};
The status of the user acknowledgement can also be got by using
AckStatus(ESmsAckTypeUser)
. A user acknowledgement contains a
response code [C.S0015-A 4.5.3] that can be got using
UserAck()
:
ackStatus = recipArray[i]->AckStatus(ESmsAckTypeUser);
if (ackStatus == CSmsNumber::EAckSuccessful)
{
TUint8 userAck = recipArray[i]->UserAck();
iConsole.Printf(_L("\n\tResponse code: %u"), userAck);
}
The status of the read acknowledgement can be got using
AckStatus(ESmsAckTypeRead)
. There is no further information
relating to read acknowledgements.
A summary of the acknowledgements received can be got from the
index entry for the sent message, using
TMsvSmsEntry::AckSummary()
. The returned
TMsvSmsEntry::TMsvSmsEntryAckSummary
indicates if
the message is expecting acknowledgments, has received all expected
acknowledgements, or has no acknowledgement information.
For example, the following code tests if the message has been delivered successfully to all recipients:
TMsvSmsEntry entry = static_cast<TMsvSmsEntry>(iMtm->Entry().Entry());
TMsvSmsEntry::TMsvSmsEntryAckSummary summary = entry.AckSummary(ESmsAckTypeDelivery);
if (summary == TMsvSmsEntry::EAllSuccessful)
iConsole.Printf(_L("\nMessage was successfully delivered to all recipients"));
Messaging receives SMS messages via a number of watcher components that listen to the CDMA stack for incoming messages that belong to particular teleservices (WMT, WEMT, VMN, WPT). When an incoming message belonging to one of these teleservices is received, its contents are read, and a new entry for the message is created in the message server's store (in the global inbox folder). The usual case is that these messages will then be read by the user through the email application, but other messaging clients can receive notifications when a new message is created in the store, and process the message if appropriate.
To receive such notifications, a class must implement the session
observer interface
MMsvSessionObserver
. The interface has just one
function:
void HandleSessionEventL(TMsvSessionEvent aEvent, TAny* aArg1, TAny* aArg2, TAny* aArg3)=0;
When a new message is created in the store, the framework calls
this function with aEvent
set to EMsvEntriesCreated
,
and aArg1
is set to a CMsvEntrySelection*
that
specifies the IDs of the entries that have been created. The following checks
the event type, and gets the entry ID selection:
void CClientApp::HandleSessionEventL(TMsvSessionEvent aEvent, TAny* aArg1, TAny* , TAny* )
{
CMsvEntrySelection* entries = NULL;
switch (aEvent)
{
case EMsvEntriesCreated:
entries = static_cast<CMsvEntrySelection*>(aArg1);
break;
default:
break;
}
The observer will receive notifications for all types of entry, not just SMS, so it's necessary to read the message properties to check that the entry is appropriate to process.
The following code does the first stage in this checking. It:
gets the index entry for the message. Getting an index entry is cheap and quick compared to getting the entire message, so it's a good idea to do any required checks on this first.
tests if the entry is an SMS message, by checking the index
entry's iMtm
and iType
fields
tests if it's an incoming message, by checking that the entry is in the Inbox
if (entries)
{
TInt count = entries->Count();
// check each entry to see if we want to process it
while (count--)
{
// get the index entry
TMsvId serviceId;
TMsvEntry entry;
iMtm->Session().GetEntry((*entries)[count], serviceId, entry);
// if the entry is an SMS message
if (entry.iMtm == KUidMsgTypeSMS && entry.iType == KUidMsvMessageEntry
// and if it's an incoming message (as its in the inbox)
&& entry.Parent() == KMsvGlobalInBoxIndexEntryId)
An application can now perform further checks, e.g. for particular message content. For example, the following code:
sets the client MTM's context to the message
reads the message body and tests that it begins with the string
specified by a value iMatchText
gets the message teleservice ID and tests that it is equal to a
value iMatchTeleservice
iMtm->SwitchCurrentEntryL((*entries)[count]);
iMtm->LoadMessageL();
TBool match = ETrue;
// Check the message body against any specified match text
if (iMatchText.Length())
{
CRichText& body = iMtm->Body();
TPtrC text(body.Read(0, iMatchText.Length()));
match = (text.Compare(iMatchText) == 0);
}
// Check the message teleservice against the match teleservice
if (iMatchTeleservice)
{
match &= (iMtm->SmsHeader().CdmaMessage().TeleserviceId() == iMatchTeleservice);
}
If you determine that your application should process the message,
you can prevent the user from seeing the message in the Inbox of the standard
messaging application. To do this, you can set the message entry's visible flag
to false, using TMsvEntry::SetVisible(EFalse)
. You should delete
the message (as the user will not be able to do so) once its processing is
complete.
Common GSM and CDMA message fields are accessed through the
TMsvMessageSms
class and its base class
TMsvMessageBio
.
Use
CSmsHeader::SmsMessage()
to get a
TMsvMessageSms
object:
TMsvMessageSms& fields = iMtm->SmsHeader().SmsMessage();
The fields include:
Character set for SMS messages (Encoding()
,
SetEncoding()
): text is stored in Unicode on the Symbian OS phone
and is converted into the appropriate character set when the message is
sent.
Functions to manipulate the EMS Information Elements in a message are also provided by this class: see EMS.
The Originating Address is a mandatory parameter on all point-to-point SMS messages.
It does not need to be set on outgoing messages, as the address of the originating phone is set by default.
For incoming messages, the parameter can be got as follows:
TPtrC originatingAddress = fields.OriginatingAddress();
When a reply message is created using
CSmsClientMtm::ReplyL()
, the reply address is
set to this value unless a CDMA call-back number (see below) has been
specified.
Delivered messages can include a Message Center Time Stamp that gives the time that the message was accepted by the destination message center.
The following gets the time stamp. The time is expressed as the message center's local time plus the difference between the message center's time zone and Coordinated Universal Time (UTC) in quarter of hours.
TDateTime timeStamp;
TInt quarterHourUTCOffset;
User::LeaveIfError(iFields->GetMessageServiceCenterTimeStamp(timeStamp,quarterHourUTCOffset));
The message validity period sets a time after which the message center should discard the message if it has not been delivered to the destination. The time can be expressed either as an absolute value or relative to the time the message is received by the message center.
An absolute time is represented using the standard Symbian OS
type
TDateTime
. The following sets the message
validity period to 10:30am on 2004/01/01:
TDateTime time(2004,EJanuary,01,10,30,0,0);
iFields->SetValidityPeriodAbsoluteL(time);
A relative time can be expressed in one of a number of units
[C.S0015-A Table 4.5.6-1], such as days or weeks. Flags for these unit types
are given in the enum
TSmsRelativeTimeUnit
. The following sets a
relativity validity period of 1 day:
TSmsRelativeTimeUnit timeUnit=ETimeUnitDays;
TUint32 relativeTime=1;
iFields->SetValidityPeriodRelativeL(timeUnit, relativeTime);
The validity period can be got and set only on outgoing messages (as incoming messages must either be valid or will have been discarded by the message center).
CDMA-specific message fields are held in a
TMsvMessageCdma
object, which can be obtained
using
CSmsHeader::CdmaMessage()
.
In the following example, CDMAFields
is an
TMsvMessageCdma
reference.
TMsvMessageCdma& CDMAFields = iMtm->SmsHeader().CdmaMessage();
The fields are:
SMS messages received in the messaging inbox belong to one of the
teleservices WMT, WEMT, VMN, or WPT. You can find which one using
TeleserviceId()
:
tia637::TTeleserviceId teleserviceId = CDMAFields.TeleserviceId();
tia637::TTeleserviceId
is an integer type;
constants to identify each teleservice are defined in the
tia637
namespace.
There is no corresponding function to set the teleservice.
As well as an originating address, a message can have an originating subaddress. The originating subaddress can be got for incoming messages as follows:
HBufC* originatingSubAddress = fields.GetOriginatingSubAddressL();
Note that ownership of the returned HBufC*
is passed
to the caller.
The deferred delivery time sets a time at which the message center should deliver the message. Similiarly to the validity period field, this can be got and set on outgoing messages, and can be specified either as an absolute time or relative to when the message is received by the message center.
The setter functions are
SetDeferredDeliveryTimeAbsoluteL()
and
SetValidityPeriodRelativeL()
. The following sets the desired
delivery time to be 09:30 am on 2004/03/02:
TDateTime time(2004,EMarch,02,09,30,0,0);
CDMAFields.SetDeferredDeliveryTimeAbsoluteL(time);
The getter functions are
GetDeferredDeliveryTimeAbsoluteL()
and
GetDeferredDeliveryTimeRelativeL()
. The following tests if the
format is relative, and if so, gets the relative time:
TSmsTimePeriodFormat deliveryTimeFormat = CDMAFields.DeliveryTimeFormat();
if (deliveryTimeFormat == ESmsTimePeriodRelative)
{
// Relative format
TSmsRelativeTimeUnit timeUnit;
TUint32 relativeTime;
CDMAFields.GetDeferredDeliveryTimeRelativeL(timeUnit, relativeTime);
Note the difference with the scheduled sending functionality, which controls when the message is sent from the phone to the message center.
The Number of Messages is a decimal number with range (0 to 99) representing the number of messages stored at the Voice Mail System.
To get the number of messages, use
GetNumberOfMessages()
. It is set only by the Voice Mail
Notification service.
A message can have one of four priority levels, from Normal to Emergency [C.S0015-A 4.5.9-1].
The priority level does not alter the phone's handling of the message, but can be used at application level, for example to highlight urgent messages for the user's attention.
The level can be got and set on outgoing messages, and got on
incoming messages. The priority levels are specified by constants in the
tia637
namespace. The following sets the
priority level to urgent.
tia637::TPriorityIndicator priority = tia637::KBdUrgent;
CDMAFields.SetPriorityIndicatorL(priority);
A default priority level for new messages is set from the current default message settings.
A message can have one of four privacy levels: Unrestricted, Restricted, Confidential, and Secret.
The privacy level does not alter the phone's handling of the message, and can be used at application level for any suitable purpose.
The level can be got and set on outgoing messages, and got on
incoming messages. The privacy levels are specified by constants in the
tia637
namespace. The following sets the privacy
level to confidential.
tia637::TPrivacy privacy = tia637::KBdConfidential;
CDMAFields.SetPrivacyIndicatorL(privacy);
A default privacy level for new messages is set from the current default message settings.
The callback number sets the number to be dialled in reply to a received SMS message. This does not need to be set by the application unless the number is different from the number of the sending phone.
The callback number can be got and set on outgoing messages, and got on incoming messages. It is passed as a descriptor.
CDMAFields.SetCallbackNumberL(iInput);
A default callback number for new messages is set from the current default message settings.
When a reply message is created using
CSmsClientMtm::ReplyL()
, the reply address is
set to this value if it is specified (or to the originator address if it is
not).
A delivered message can specify a flag setting to indicate to the phone when to display the received message: the options are to display immediately, or according to a default or user configured setting.
The modes are defined by constants in the
tia637
namespace, which belong to the
tia637::TBdMode
integer type. The following gets
the mode:
tia637::TBdMode display = 0;
err = CDMAFields.GetMessageDisplayModeL(display);
The message display mode for new outgoing messages is set from the current service settings.
A delivered message can have a Message Deposit Index field that provides a unique reference to the message's user data. This allows a phone, when replying to a received message, to include the Message Deposit Index of the received message to indicate to the message center that the original contents of the message are to be included in the reply.
The MTM sets the index field in this way when a reply message is created, so an application does not normally need to access this field.
Index values belong to the
tia637::TMessageDepositIndex
integer type. The
following gets the index:
tia637::TMessageDepositIndex index;
err = CDMAFields.GetMessageDepositIndexL(index);
The User Response Code is used in SMS User Acknowledgement
Messages to respond to previously received short messages. The
GetUserResponseCodeL()
and SetUserResponseCodeL()
functions allow this to be retrieved and set. The code is message
centre-specific and identifies a predefined response.
The Alert on Message Delivery subparameter indicates that
alerting is requested. Such methods as vibrating and sound may be used (e.g. by
a UI MTM). The possible values are defined by
tia637::TAlertPriority
.
The subparameter can be retrieved from deliver messages, and set on submit messages. The following sets the alert to high:
CDMAFields.SetAlertOnDeliveryL(tia637::KBdUseHighPriorityAlert);
The Language Indicator subparameter indicates the language of the
message so that the receiving mobile station can discard those messages that
are not in the user’s preferred language. The possible language values are
defined by
tia637::TLanguageIndicator
.
The subparameter can be retrieved from deliver messages, and set on submit messages. The following sets the language indicator value to Spanish:
CDMAFields.SetLanguageIndicatorL(tia637::KLanguageSpanish);
CDMA2000 provides a teleservice, the Wireless Enhanced Messaging Teleservice (WEMT), which can carry Enhanced Messaging Service (EMS) over SMS. The EMS standard, defined by the 3GPP [3G TS 23.040, http://www.3gpp.org/ftp/Specs/archive/23_series/23.040/], is based upon the standard SMS, but with formatting added to the text. The formatting allows the message to contain animations, pictures, melodies, formatted text, and vCard and vCalendar objects.
Classes for the various types of EMS element are provided by the gsmu.lib library.
Header |
Class |
Description |
|
|
predefined animation |
|
|
text formatting |
|
|
large, small, and variably-sized pictures |
|
|
predefined sounds |
|
|
user prompt indicator |
|
|
object distribution indicator |
To construct an outgoing WEMT message:
create a new outgoing message, as described in Message creation.
get the
TMsvMessageSms
for the message
create EMS element objects, and add them to the message using
TMsvMessageSms::AddEMSInformationElementL()
The following code adds a pre-defined "winking" animation, and a predefined "drum" sound to a message:
TMsvMessageSms& smsFields = smsHeader -> SmsMessage();
// if simulating an EMS message, add a couple of ems elements
CEmsPreDefAnimationIE* ani = CEmsPreDefAnimationIE::NewL(CEmsPreDefAnimationIE::EWinking);
CleanupStack::PushL(ani);
smsFields.AddEMSInformationElementL(*ani);
CleanupStack::PopAndDestroy(ani);
CEmsPreDefSoundIE* soundIE = CEmsPreDefSoundIE::NewL(CEmsPreDefSoundIE::EDrum);
CleanupStack::PushL(soundIE);
smsFields.AddEMSInformationElementL(*soundIE);
CleanupStack::PopAndDestroy(soundIE);
Particular elements and types of element can be removed using
TMsvMessageSms::RemoveEMSInformationElementL()
.
All elements can be removed with
TMsvMessageSms::ResetEMSL()
.
Incoming WEMT messages can be detected using the approach described
in
Incoming messages. You will need
to check the message's teleservice ID to test that the message is a WEMT
message. Once your application has decided to process the message, you can get
a reference to an array of the message's EMS elements using
TMsvMessageSms::GetEMSInformationElementsL()
.
The following code gets the EMS element array, and prints out the type of each element.
const RPointerArray<const CEmsInformationElement>& ems = CDMAFields.GetEMSInformationElementsL();
TInt numEles = ems.Count();
if (numEles) iConsole.Printf(_L("\nContains %d EMS elements:"),numEles);
for (TInt i=0; i < numEles; i++)
{
CSmsInformationElement::TSmsInformationElementIdentifier eleId = ems[i]->Identifier();
switch (eleId)
{
case CSmsInformationElement::ESmsEnhancedTextFormatting:
iConsole.Printf(_L("\n\tText Formatting"));
break;
case CSmsInformationElement::ESmsEnhancedPredefinedSound:
iConsole.Printf(_L("\n\tPredefined Sound"));
break;
case CSmsInformationElement::ESmsEnhancedUserDefinedSound:
iConsole.Printf(_L("\n\tUser-defined Sound"));
break;
case CSmsInformationElement::ESmsEnhancedPredefinedAnimation:
iConsole.Printf(_L("\n\tPredefined Animation"));
break;
case CSmsInformationElement::ESmsEnhancedLargeAnimation:
iConsole.Printf(_L("\n\tLarge Animation"));
break;
case CSmsInformationElement::ESmsEnhancedSmallAnimation:
iConsole.Printf(_L("\n\tSmall Animation"));
break;
case CSmsInformationElement::ESmsEnhancedLargePicture:
iConsole.Printf(_L("\n\tLarge Picture"));
break;
case CSmsInformationElement::ESmsEnhancedSmallPicture:
iConsole.Printf(_L("\n\tSmall Picture"));
break;
case CSmsInformationElement::ESmsEnhancedVariablePicture:
iConsole.Printf(_L("\n\tVariable Picture"));
break;
case CSmsInformationElement::ESmsEnhancedUserPromptIndicator:
iConsole.Printf(_L("\n\tUser Prompt Indicator"));
break;
case CSmsInformationElement::ESmsEnhancedODI:
iConsole.Printf(_L("\n\tODI"));
break;
default:
break;
};
}
}
Messaging provides the Send As API, whose principal class is
CSendAs
, as a simple-to-use interface that allows
applications to create outgoing messages. The SMS MTM supports this API.
The teleservice to which outgoing Send-As SMS messages belong is
set at the service level
(CSmsSettings::DefaultTeleservice()
).
Additional settings such as privacy indicator, reply options, alert on delivery, language indicator, and callback number, are set on the new message from the message settings defaults specified in the SMS service.
The cdmasms_eg
example, in the
Examples\Messaging\
directory, demonstrates many of the messaging
SMS CDMA APIs. It is a simple console-driven application. The main menu offers
the following options:
Create WMT
This creates a new outgoing message belonging to the WMT teleservice. On choosing this, you will be prompted to enter the message text, address, and a number of other message fields. Either enter a value in the suggested range for the field, or just press ENTER to not set the field. On completion, the new message will be saved to the outbox.
Create WEMT
This is similar to the above, but creates a new WEMT message. In addition to the WMT fields, you are prompted to select an animation element, and a message sound element, to insert into the message.
Send SMS messages
This initiates sending of any SMS messages that are waiting in the outbox. On completion of the send, it displays an info message saying how many messages were sent, and any error that occurred.
Get incoming messages
This sets the application to listen for selected new incoming SMS messages, and displays any that arrive. It prompts for:
Teleservice to get: WMT, or WEMT
This instructs the application what type of message should be listened for.
Text to match
The application filters incoming messages, and only handles those in which the beginning of the messgage body is equal to the entered match text (maximum of 5 characters).
At this point, listening is started. If a new message that meets the entered criteria is detected, the application will display its contents and various of its fields. A sub-menu is displayed that offers further options:
Simulate incoming WMT message:
This is to simplify experimentation and testing. It artificially creates a new "incoming" SMS message in the inbox that the application will detect and handle as if a genuine new incoming message had arrived. The message has the body text "simulated incoming message".
Note that the function to do this
(CSMSSession::SimulateIncomingL()
) uses lower-level CDMA SMS stack
APIs, which would not normally be used by a messaging application.
Simulate incoming WEMT message:
This is similar to the above, but creates a WEMT message with an animation and sound elements.
3. Cancel waiting for incoming messages
This stops listening, and returns to the main menu.
Quit
This exits the example application.
Quit
This exits the example application.
The application has the following classes:
Class |
Purpose |
|
Standard minimal application class. |
|
Standard minimal document class. |
|
Standard minimal app UI class. |
|
Console-type control for input and output. |
|
An active object that initiates sending of SMS messages in the outbox. On completion, it displays the final progress information for the operation. |
|
Encapsulates a session to the message server and an instance of the SMS client MTM object. |
|
Main UI class to write menus to the console and get user input. It also monitors session events for new incoming SMS messages. |
The application has the following files:
File |
Purpose |
|
Component build file |
|
Defines the standard application framework classes, and
|
|
This contains the SMS specific part of the example. It
defines the |
|
Component project file |
|
Defines standard minimal application resources |
The application can be built in the standard way using the
bldmake
and abld
commands, or from an IDE.
Note that when running in the emulator, the emulator should be set to CDMA mode, as described in Selecting CDMA or GSM SMS.
The application is started in the same way as other GUI
applications. It is called cdmasms_eg
.