March 21, 2019
Hot Topics:

BREW's Short Messaging Service Interfaces: Which to Use and Why

  • October 12, 2005
  • By Ray Rischpater
  • Send Email »
  • More Articles »

If you've downloaded the latest QUALCOMM BREW SDKs (see the resources section) and reviewed the documentation, you doubtless saw a bevy of new Short Messaging Service (SMS)-related interfaces including ISMS, ISMSMsg, ISMSNotifier, and ISMSStorage. If so, you're probably wondering: What do these classes offer that ITAPI doesn't, and why would you use them? You're not alone. In this article, I'll review how SMS sends and receives works in BREW, and explain why there are all of these new classes around the SMS protocol. Fortunately, as you will see, most applications can continue to use the existing ITAPI interfaces for managing SMS; the new interfaces are for a few very specific purposes.

The ITAPI Interface and SMS

For time immemorial (BREW time, anyway), the ITAPI interface has been your pathway to sending and receiving SMS. Sending is trivial, thanks to the ITAPI_SendSMS method, which takes the destination address, message, and an optional class ID to which the message should be delivered as well as a status callback, like this:

   ITAPI_SendSMS (pITapi, "8885551212", "Hello World",
                  0,MOSMSNotify, pThis );
void MOSMSNotify( void *p, int result )
   if ( result == AEEMOSMS_ERR_NO_ERR )
 5  else
      DBGPRINTF("Failure &d", result );

It's up to your application logic to determine how best to handle errors; some error codes returned by the ITAPI interface are temporary in nature (such as the network being unavailable), while others are more grievous—such as the message not being accepted by the network at all, or an internal configuration error (likely from a handset that's not been provisioned).

While sending SMS messages is trivial—all it requires is the message text and a callback—receiving messages presents you with a number of choices in how you wish to receive a message. All handsets have always had the ability to receive BREW-directed SMS messages (also called BDSMS), those messages which begin with the string //BREW:classid: where classid is your application's class id. When the handset receives a BDSMS to your application, it posts the payload of the message to your application using the EVT_APP_MESSAGE event.

More recent versions of BREW let you receive all SMS text messages, although you need to take care when doing this that you don't inadvertently hijack the handset's text messaging application, keeping the handset user from receiving any text messages. To do this, you must only register for with the TAPI class using the NMASK_TAPI_SMS_TEXT mask in your application's Module Information File (MIF). When a message comes in, your application receives an EVT_NOTIFY, and can get the contents of the message as an AEESMSTextMsg structure like this:

// In your application's event handler
   AEENotify *pNoti = (AEENotify *)dwParam;
   if ( pNoti->cls ==  AEECLSID_TAPI )
      AEESMSMsg pMsg = (AEESMSTextMsg *)pNoti->pData;
      // Do something with the payload here.

Text SMS messages are just one of a subset of messages deliverable via SMS; the SMS protocol provides for multiple addresses for SMS messages, called teleservice ids. These are analogous to the notion of a port number in the TCP/IP protocol; different teleservice ID's are used for different purposes, such as WAP push notifications or voicemail notifications. You can receive these messages with ITAPI, too, using a very similar mechanism; see the BREW documentation for details.

The ISMS Interface

New in the latest versions of BREW 3.1.2 is a suite of SMS interfaces, ISMS, ISMSNotifier, ISMSMsg, and ISMSStorage. These interfaces open up the entire suite of SMS on the phone, letting you:

  • Send SMS messages—text or binary—using ISMS and ISMSMsg
  • Receive SMS messages using ISMSNotifier, ISMS, and ISMSMsg
  • Insert and fetch messages from the handset's native message store

Looking at this list, you might surmise that these interfaces aren't for general consumption, and you'd be absolutely correct. These interfaces are provided largely for handset manufacturers, who now can write the handset's embedded messaging suite in BREW, something that couldn't easily be done before. Nonetheless, it's instructive to look at how these classes work, if only because they provide insight into how the handset's SMS functionality works under the hood.

Consider sending an SMS: Previously, as developers we've only been able to send SMS using ITAPI_SendSMS. By using ISMS and ISMSMsg, there's considerably more flexibility—at the cost of complexity, as you can imagine. Here's pseudocode to send a message:

// Make a new SMS message
   nResult = ISHELL_CreateInstance(pThis->sApplet.m_pIShell,
   if(nResult != SUCCESS )
      DBGPRINTF("Failed to create ISMSMsg %s", nResult);
      goto fail;
   // Make a new SMS service
   nResult = ISHELL_CreateInstance(pThis->sApplet.m_pIShell,
   if(nResult != SUCCESS )
      DBGPRINTF("Failed to create ISMS %s", nResult);
      goto fail;
   // Configure our options buffer. Options will be added
   // "one at a time"
   sOpts[1].nId = MSGOPT_END;
   sOpts[1].pVal = NULL;
   // We need to instruct the ISMSMessage to copy options that
   // are passed
   sOpts[0].nId = MSGOPT_COPYOPTS;
   sOpts[0].pVal = (void *)TRUE;
   ISMSMSG_AddOpt(pISMSMsg, (WebOpt *)&sOpts);
   // Set the destination address on our outbound sms message
   sOpts[0].nId = MSGOPT_TO_DEVICE_SZ;
   sOpts[0].pVal = (void *)"8885551212"
   ISMSMSG_AddOpt(pISMSMsg, (WebOpt *)&sOpts);
   // priority
   sOpts[0].nId = MSGOPT_PRIORITY;
   sOpts[0].pVal = (void *)AEESMS_PRIORITY_NORMAL;
   ISMSMSG_AddOpt(pISMSMsg, (WebOpt *)&sOpts);
   // sender address (from).  We get the sender's MDN from ITAPI
   nResult = ISHELL_CreateInstance(pThis->sApplet.m_pIShell,
                                   (void **)&pITapi);
   if(nResult != SUCCESS)
      DBGPRINTF("Failed to create ITAPI instance %s", nResult);
      goto fail;
   ITAPI_GetStatus(pITapi, &sStatus);
   sOpts[0].nId = MSGOPT_FROM_DEVICE_SZ;
   sOpts[0].pVal = (void *)&sStatus.szMobileID[5];
   ISMSMSG_AddOpt(pISMSMsg, (WebOpt *)&sOpts);
   sOpts[0].pVal = (void *)AEESMS_ENC_ASCII;
   ISMSMSG_AddOpt(pISMSMsg, (WebOpt *)&sOpts);
   sOpts[0].nId = MSGOPT_PAYLOAD_SZ;
   sOpts[0].pVal = (void *)"Hello World";
   ISMSMSG_AddOpt(pISMSMsg, (WebOpt *)&sOpts);
   sOpts[0].pVal = (void *)AEE_ENC_ISOLATIN1;
   ISMSMSG_AddOpt(pISMSMsg, (WebOpt *)&sOpts);
   // Prepare to send the message by init'ing callback and
   // setting status
   CALLBACK_Init(&pThis->m_sSendMessageCallback, SMSSendCB, pThis);
   ISMS_SendMsg(pThis->pISMS, pISMSMsg,
// And our callback
static void SMSSendCB(CApp *pThis)
   int  nResult = EFAILED;
   uint32  dwErrorType = 0;
   uint32  dwErrorCode = EFAILED;
   dwErrorType = AEESMS_GETERRORTYPE(pThis->m_dwSMSSendResult);
   DBGPRINTF("etype: 0x%x", dwErrorType);
   dwErrorCode = AEESMS_GETERROR(pThis->m_dwSMSSendResult);
   DBGPRINTF("ecode: 0x%x", dwErrorCode);
   case 0:
      // Should be a success!
   case 1:
      // SMSC Error type 1
   case 2:
      // SMSC Error type 2
   case 3:
      // SMSC Error type 3
      DBGPRINTF("invalid error type %d", dwErrorType);

Wow. That's a lot of code just to send a message! After creating an empty SMS message and an instance of ISMS (which will actually perform the sending operation), most of the code consists of configuring the SMS message with the options for the message, such as its destination address, sender address, encoding (ASCII, as opposed to a binary SMS message), message payload (the ubiquitous "Hello World", and how the payload is encoded (ISO-Latin character set). For users of IWeb, this interface should look familiar—under the hood, an ISMSMessage is actually a collection of WebOpts.

Page 1 of 2

Comment and Contribute


(Maximum characters: 1200). You have characters left.



Enterprise Development Update

Don't miss an article. Subscribe to our newsletter below.

Thanks for your registration, follow us on our social networks to keep up-to-date