Developing SMS Enabled Line-of-Business Applications

 

Christian Forsberg
businessanyplace.net

May 2003

Applies to:
    Microsoft® .NET Compact Framework
    Microsoft Visual Studio® .NET
    Microsoft Windows® Powered Pocket PC Phone

Summary: As a first class member of the world of mobile phones, the Windows Powered Pocket PC Phone with its built-in phone capabilities has multiple connectivity options. The ability to connect to the Internet is a core capability, but there are other options available, too. One common way to communicate in any Global System for Mobile (GSM) communications network is by using Short Message Server (SMS) messages. When designing connected mobile applications, this is an option you should not overlook, and this article will explain why.

Download sms_apps.exe

Contents

What is SMS?
Why SMS?
SMS API
SMS Anyplace Sample
Code Walkthrough
Conclusion

What is SMS?

Short Message Server enables mobile phones including the Pocket PC Phone to send short messages using the GSM network, and has a number of interesting features:

  • A single SMS message can be up to 160 characters (even binary) long.
  • SMS is a store and forward service. In other words, short messages are not sent directly from sender to recipient, but always via an SMS Center. If the receiver is not connected (perhaps the phone is turned off), the message will be delivered when the receiver connects again.
  • SMS features confirmation of message delivery. This means that unlike paging, users do not simply send a short message and trust that it gets delivered. Instead the sender of the short message can receive a return message back notifying them whether or not the short message has been delivered.
  • SMS messages can be sent and received simultaneously with GSM voice.
  • SMS messages are charged by the message and are therefore considerably more expensive (per byte) than data sent on an IP-based network, like using GPRS (General Packet Radio Service).

To use SMS, users need a subscription to a mobile network that supports it, and the use of SMS must be enabled for that user. The user needs to have a destination to send a short message to, or receive a message from. This is usually another mobile phone, but can also be a server. Finally, the user also needs a mobile phone that supports SMS and knowledge of how to send or read a short message using their specific model of mobile phone.

Why SMS?

For an application developer, the instant solution to connect a Pocket PC Phone to a server is probably via an IP-based network like the Internet. Among the advantages of doing so is the common standard protocols are there and the tools are prepared for the communication.

However, there are scenarios in which an IP-based network is not the most efficient transport. The need to actively, or even automatically, make a connection takes valuable time and cannot be made during a phone call. What if there were a way to instantly connect to the server even while talking? Since the Pocket PC Phone can send SMS messages, this could be a way to accomplish this.

Common scenarios in which instant connectivity is useful are when mobile workers need to notify the line-of-business applications of important events. It could be a salesman notifying the server of a new order, or it could be the truck driver who has just delivered a package.

On the server side, there are several solutions available to receive SMS messages and forward them to other systems. Examples are products from MobileSys, Inc. and Smartserv Online, Inc. In this article we will look closer at the SMS ability of the Pocket PC Phone.

SMS API

On the Pocket PC Phone you can access SMS messaging using a number of Microsoft® Windows® CE API calls:

Function Description
SmsOpen Opens the SMS Messaging component for send and/or receive access.
SmsSendMessage Sends an SMS message.
SmsGetMessageStatus Retrieves a status report for a sent message.
SmsReadMessage Reads a previously received SMS message.
SmsGetMessageSize Determines an upper-bound for the size of the buffer.
SmsGetSMSC Reads the default Short Message Service Center (SMSC) address.
SmsSetSMSC Sets the default SMSC.
SmsGetPhoneNumber Gets the phone number of the device associated with the SMS bearer.
SmsGetTime Gets an estimate of the current time approximated by the SMSC's clock.
SmsGetBroadcastMsgRanges Gets the range of broadcast messages the mobile will listen for.
SmsSetMessageNotification Starts your application when an SMS message arrives.
SmsClearMessageNotification Cancels registration for SMS notifications.
SmsSetBroadcastMsgRanges Sets the broadcast message range the mobile will listen for.
SmsClose Closes an existing SMS Messaging handle.

The session starts with a call to SmsOpen that returns an SMS handle that is needed in all subsequent calls to the SMS API functions. The session is terminated by passing this handle to SmsClose. This article will focus on the SmsSendMessage API using the P(latform) Invoke functionality in .NET CF, and similar techniques can be used to access the other APIs as well.

SMS Anyplace Sample

This is a sample application for the Pocket PC Phone created with Microsoft Visual Studio® .NET, C#, and the .NET Compact Framework. It shows how to send SMS messages using the SMS APIs. The application consists of one form:

Figure 1. SMS Anyplace sample

The idea behind this sample is the truck driver who makes a delivery and, without connecting to any IP-based network like the Internet, can instantly send a notification to the line-of-business application on the server.

Imagine that a selection is made in a list of packages, with the subsequent screen revealing the selected package identity along with the current date and time. All that is needed is to tap the Delivered button.

When it is tapped, the delivery information is compiled into an XML message string that you can see on the bottom half of the screen. This information will probably not be shown in a real world application, but is shown here for clarification. The XML format ensures that the receiving server can access the information in a standardized way. The XML is then sent to a server using SMS without making any connections or even interrupt an on-going voice conversation.

Code Walkthrough

Lets start off with the code behind the Delivery button:

// Create XML message
MemoryStream ms = new MemoryStream();
XmlTextWriter xmlw = new XmlTextWriter(ms, System.Text.Encoding.UTF8);
xmlw.WriteStartDocument();
xmlw.WriteStartElement("Delivery");
xmlw.WriteElementString("PackageID", lblPackageID.Text);
xmlw.WriteElementString("Delivered", txtDelivered.Text);
xmlw.WriteEndElement();
xmlw.WriteEndDocument();
xmlw.Flush();
ms.Seek(0, SeekOrigin.Begin);
StreamReader sr = new StreamReader(ms);
txtMessage.Text = sr.ReadLine();
lblMessage.Text = "Message (" + txtMessage.Text.Length.ToString() + " 
  chars):";
this.Refresh();
xmlw.Close();
sr.Close();

// Send message
if (0 == SMSHelper.SendSMS("+15555550123", txtMessage.Text))
  MessageBox.Show("Message sent!", this.Text, MessageBoxButtons.OK,
    MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1);
else
  MessageBox.Show("Could not send message!", this.Text);

The package identity and the time of delivery is transformed into XML. The .NET CF has native support for XML, and there are several classes available to work with. In this sample, the choice was the XMLTextWriter class. Using simple methods, it writes the XML to a memory stream. That stream is then reset to the beginning, and read by a StreamReader into the message text control. The message label is also updated with the message length. When the message is created it is sent off (second parameter) to the static SendSMS method of the SMSHelper class. The first parameter is the destination address (phone number) in international format.

The SMSHelper class starts with a number of declarations:

private const string SMS_MSGTYPE_TEXT = "Microsoft Text SMS Protocol";
private const int SMS_MODE_SEND = 2;          // Open in send mode
private const int SMSDE_GSM = 1;              // Use GSM encoding
private const int SMSAT_INTERNATIONAL = 1;    // International format
private const int PS_MESSAGE_OPTION_NONE = 0; // No message options
private const int PS_MESSAGE_CLASS0 = 0;      // Show but do not store
private const int PS_MESSAGE_CLASS1 = 1;      // Store and show
private const int PSRO_NONE = 0;              // No replacements
private const int SMS_OPTION_DELIVERY_NONE = 0; // No delivery options

[DllImport("sms.dll")]
private static extern int SmsOpen(
  string ptsMessageProtocol,
  int dwMessageModes,
  ref IntPtr psmshHandle,
  int phMessageAvailableEvent);

[DllImport("sms.dll")]
private static extern int SmsSendMessage(
  IntPtr smshHandle,
  int psmsaSMSCAddress,
  IntPtr psmsaDestinationAddress,
  int pstValidityPeriod,
  IntPtr pbData,
  int dwDataSize,
  IntPtr pbProviderSpecificData,
  int dwProviderSpecificDataSize,
  int smsdeDataEncoding,
  int dwOptions,
  int psmsmidMessageID);

[DllImport("sms.dll")]
private static extern int SmsClose(IntPtr smshHandle);

First, some SMS API specific constants are declared. This is just a subset of the available constants, and for a full reference please see the Windows CE API documentation. Then each SMS API is declared using the DllImport attribute (from the System.Runtime.InteropServices namespace) pointing to the DLL (Dynamic Link Library) where the function is implemented (in this case the sms.dll).

The core of the SendSMS method looks like this:

// Get handle
if (0 != SmsOpen(SMS_MSGTYPE_TEXT, SMS_MODE_SEND, ref smsHandle, 0))
  returnValue = -1; // Could not open

// Send message
if (0 != SmsSendMessage(smsHandle, 0, smsAddress, 0,
                 smsMessage, smsMessageTag.Length,
                 smsProviderData, smsProviderDataTag.Length,
                 SMSDE_GSM, SMS_OPTION_DELIVERY_NONE, 0))
  returnValue = -2;

// Release handle
if (0 != SmsClose(smsHandle))
  returnValue = -3; // Could not close

The SMS API handle (smsHandle) is set by a call to the SmsOpen API where message type and send mode is also specified. The handle, as well as some of the other required parameters (smsAddress, smsMessage and smsProviderData), is declared as an IntPtr. IntPtr is a structure that ensures that the length of the pointer (32 bit or 64 bit) is adapted to the native pointer size of the current platform. Finally, the SMS API handle is released with the call to the SmsClose API.

Conclusion

As the Pocket PC Phone is a premier citizen of the world of mobile phones, we can take advantage of its capabilities, like SMS messages. Consider this an interesting option when designing your connected applications.