Smartphones

Design Robust Apps that Take Advantage of Windows CE-powered Smartphone Devices

Chris Dellinger

This article assumes you are familiar with C++, Windows CE, and XML

Level of Difficulty123

SUMMARY

Smartphone applications promise to be at the crest of a new wave of cell phone advances as the familiar process of using Microsoft dev tools can produce cutting-edge mobile phone applications. Because Smartphones are Windows-powered devices, developers can easily and inexpensively extend both new and time-tested business applications to mobile users. These applications will possess the necessary levels of enterprise functionality while integrating mobile phone features through the use of several easy to use APIs. This article looks at the basics of building a real-world business application for the Smartphone.

Contents

Smartphone Versus Pocket PC Phone Edition
Building Smartphone Applications
Data Retrieval
Storing Data Locally
Database Options
Synchronizing Data
Accessing Phone Features
Conclusion

T he release of the Windows®-powered Smartphone, which is currently available in Europe and expected in the US in the first half of 2003, raises the bar for mobile application development. The Smartphone is a state-of-the-art mobile phone that provides voice, wireless, and Internet capabilities in a familiar Windows environment. Unlike existing mobile phones, Smartphone devices have expansion slots to add memory and hardware, allow you to synchronize with your desktop computer through ActiveSync®, and provide features such as instant messaging, Outlook® contacts and calendaring, and a unified Inbox. And best of all, Smartphones pack these features into devices as small as existing mobile phones.

The Smartphone OS is based on Windows CE 3.0, so developers can quickly create a wide variety of powerful and exciting applications with the same tools and APIs they have been using for the Pocket PC. While games and personal productivity tools will surely represent large markets for the Smartphone, enterprise applications will also be a large development arena. There are many benefits to providing workers with mobile phones and the Smartphone leverages these benefits by allowing access to internal enterprise applications without expensive hardware. In addition, new types of applications that marry existing features with telephony will now be possible.

In this article, I'm going to build a real-world business application for the Smartphone. For topics outside the scope of this article, such as voice recognition, instant messaging, and Pocket Outlook, check out Windows Mobile.

Smartphone Versus Pocket PC Phone Edition

You may have heard of the Pocket PC Phone Edition, another phone powered by Microsoft® software. To avoid confusion, I will clarify the differences between the Pocket PC Phone Edition and the Smartphone. For a look at the differences between the two, see Figure 1. (If you are interested in more detailed information on building a Smartphone GUI, check out "Developing an Effective Smartphone User Interface".) The Pocket PC Phone Edition is a fully functioning Pocket PC device with mobile phone capabilities built in. It is similar in size to other Pocket PC devices and has a larger body than the Smartphone. The Pocket PC Phone Edition comes with more horsepower than a Smartphone in that it has more memory; in addition, it has a touch screen that's larger than the regular display screen on the Smartphone (which does not have touch-screen technology). User interaction with the devices is handled by separate methods: the Pocket PC Phone Edition uses a stylus for the touch screen while the Smartphone uses a phone keypad.

Figure 1 The Screens

Figure 1** The Screens **

Which device best fits your needs boils down to three main issues: cost, functionality, and ease of use. Microsoft estimates that Smartphones will be priced comparably to other high-end mobile phones, but less than Pocket PC Phone Edition devices. The functionality you require will depend on what you design your application to do. For most mobile applications, the Smartphone and Pocket PC Phone Edition will perform equally well. However, if your application requires large amounts of disk space and memory, additional hardware, or a larger screen, then the Pocket PC Phone Edition is probably the right choice.

Whether the device, and the application you build to run on it, will be easy to use will depend in part on data entry considerations. First, you should decide whether you need a stylus or keypad data entry, or whether it matters at all. Data entry through menu options is easily handled by either device. However, for entering textual information, the Pocket PC Phone Edition is obviously easier to use. Fortunately, both devices support Windows CE APIs, allowing you to easily create one code base for both.

Building Smartphone Applications

What will your real-world Smartphone application need to deliver? Well, there are some tasks common to most mobile business applications. They include retrieving data from a remote data store, processing it, storing and manipulating it locally while offline, uploading changes, and interacting with phone features. If you are able to understand and build these elements when needed, you're ready for real-world Smartphone development.

The first step towards building your application is to download a copy of the Smartphone 2002 SDK. The next step is to decide what type of application you want to create: browser-based or standalone.

Browser-based solutions on the Smartphone consist of Web content that is accessed by Pocket Internet Explorer. This type of application is a great option for existing content providers who want to expand their offerings to Smartphone owners. Browser-based applications on the Smartphone offer the same benefits they do on other platforms, including easy software distribution and maintenance, since all code resides on the Web server. Of course, one drawback is that a connection to the Internet is not always guaranteed. Another is that Pocket Internet Explorer applications cannot access or interact with the built-in features of the device. Fortunately, however, browser-based applications can be developed with your existing Web devel- opment toolkits, such as ASP.NET Mobile Controls.

Instead of a Web application, you can build a custom application with a tool such as eMbedded Visual C++® (also downloadable from Tools and Downloads). Fortunately, the Smartphone and the Pocket PC platform are quite similar. Since many of the APIs are the same, existing applications written in eMbedded Visual C++ for the Pocket PC platform can easily be ported to the Smartphone, resulting in significant savings for organizations wanting to deploy a single application to both devices. I've ported two applications: one was simply a recompile, and the other took only a few hours to work around some slight differences between the platforms.

You have much greater flexibility when developing standalone applications, and such applications tend to be much more robust and can be used in both connected and disconnected modes. For most business uses, standalone applications are probably the best choice. They work in offline situations, yet provide a mechanism for passing data between remote systems when necessary.

In addition, standalone applications can take advantage of device-specific features including telephony features and access to local data stores such as Pocket Outlook and the Windows CE Database (CEDB) engine. When offline, data can be cached for later synchronization. As always, however, standalone applications come with more distribution and maintenance headaches. Also, creating standalone applications require C++ skills, which are more costly and harder to find for development shops. While this has not happened yet, it is expected that the Microsoft .NET Compact Framework and Smart Device Extensions will eventually be supported on Smartphones. Once that happens, developers will be able to use languages such as C# and Visual Basic® .NET for building Smartphone applications.

Data Retrieval

Since one of the most basic features of any business app is the retrieval of data, some of your design challenges will center around the type of connectivity available. Can you depend on a continuous connection or will connectivity be intermittent? Will your system have connectivity at only certain times or access points?

Smartphone devices offer several options for retrieving data from remote data sources. One is ActiveSync, which you can use to manually push and pull documents between a desktop computer and a Smartphone. Another option is to programmatically access the device from a PC and copy files by way of the Remote API (RAPI). While both of these methods get the job done, I do not believe they are the best choice. The built-in Internet connectivity of the Smartphone is far better.

It is very simple to retrieve remote data via the Internet on a Smartphone device. In fact, if you have already developed a Pocket PC application that retrieves data across the Internet, you may already know everything you need to know. The basic methods for communicating with a remote server on a Smartphone are the WinInet functions (HTTP or FTP), the XMLDOM APIs to load data remotely, and Microsoft Internet Explorer (see Figure 2).

Figure 2 Retrieving Remote Data on a Smartphone

Figure 2** Retrieving Remote Data on a Smartphone **

The XMLDOM provides several methods for data retrieval which should be familiar to Web developers. With the DOM, you have can retrieve data through two main methods: the Load method of the document object and the XMLHTTP object. Both objects allow for data retrieval in an XML format from remote Web servers. The biggest difference between the two is that the XMLHTTP objects allow you to pass an XML object as part of your call, while the Load command does not. In cases where data must be passed in order to retrieve data, you should use the XMLHTTP object.

Regardless of which method you use on the XMLDOM, you will need to make a few adjustments in your code. First you need to include the correct headers:

#include <objsafe.h> namespace MSXML { #include <msxml.h> } #include <ocidl.h>

The objsafe.h and ocidl.h files are required since they contain GUID descriptions that are necessary to make smart pointers work in COM. You need to create the MSXML namespace and include msxml.h in order to make COM calls into the MSXML parser. In addition, you need to add the ole32.lib and oleaut32.lib libraries to your linker settings for the project to compile correctly.

Once you have the code set up to use the XMLDOM, you easily retrieve data from a remote server by using the load method of the DOMDocument. This method simply requires a URL where it can find and retrieve an XML document. It iterates through the document to populate a spinner control on the form as shown in Figure 3. Upon completion, it displays a message box that contains the entire XML document.

Figure 3 XML Load Method Example

MSXML::IXMLDOMDocument *iXMLDoc = NULL; MSXML::IXMLDOMParseError *pParsingErr = NULL; MSXML::IXMLDOMElement *iXMLElm = NULL; MSXML::IXMLDOMNodeList *iXMLChild = NULL; MSXML::IXMLDOMNode *iXMLItem = NULL; short tEmpty; BSTR bStr; VARIANT vXMLSrc; HRESULT hr; HWND hListBox; long lLength; hr = CoInitializeEx(NULL,COINIT_MULTITHREADED); if(!SUCCEEDED(hr)) return 0; hr = CoCreateInstance (MSXML::CLSID_DOMDocument, NULL,CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, MSXML::IID_IXMLDOMDocument, (LPVOID *)&iXMLDoc); if(iXMLDoc) { iXMLDoc->put_async(VARIANT_FALSE); // Smartphone 2002 workaround: // Remove document safety options IObjectSafety *pSafety; DWORD dwSupported, dwEnabled; if ( SUCCEEDED(iXMLDoc->QueryInterface( IID_IObjectSafety, (void**)&pSafety))) { pSafety->GetInterfaceSafetyOptions( MSXML::IID_IXMLDOMDocument, &dwSupported, &dwEnabled ); pSafety->SetInterfaceSafetyOptions( MSXML::IID_IXMLDOMDocument, dwSupported, 0 ); } VariantInit( &vXMLSrc ); vXMLSrc.vt = VT_BSTR; iXMLDoc->put_async(VARIANT_FALSE); vXMLSrc.bstrVal = SysAllocString(L"https://localhost/ smartphonearticledata.xml"); hr = iXMLDoc->load(vXMLSrc, &tEmpty); SysFreeString(vXMLSrc.bstrVal); iXMLDoc->get_documentElement(&iXMLElm); iXMLElm->selectNodes(L"//DATA/STATUS/S",&iXMLChild); //iXMLElm->get_childNodes(&iXMLChild); iXMLChild->get_length(&lLength); hListBox = GetDlgItem( hWnd, IDC_LISTISSUES); for (int x=0;x<lLength;x++){ iXMLChild->get_item(x,&iXMLItem); iXMLItem->get_text(&bStr); SendMessage (hListBox, LB_ADDSTRING, 0, (LPARAM) bStr); } //iXMLChild->get_item(1,&iXMLItem); iXMLDoc->get_xml(&bStr); MessageBox(NULL,bStr,TEXT("Article Demo"),MB_OK);

Storing Data Locally

After retrieving data to the Smartphone, the next step is to explore methods for storing data locally on the device. One option is to not store it at all. You could retrieve the data, perform some operation, and then release the data from memory. Unfortunately, in most situations it's not that simple, so you are forced to decide what format is appropriate for your application. You may save your data to a file store such as a flash card, or you can save it in a local data store such as CEDB.

For most business applications, you will need to persist your data to a file system. While it is possible to write data to the RAM file system, it is not recommended since all data would be lost when the device is turned off or loses power. For persisted storage, Smartphone devices provide a flash file system known as the IPSM memory space. This space will be limited on most Smartphones, but many devices will include a storage card slot that will allow for removable memory cards.

Programmatically determining where to save your data on a Smartphone is quite easy, thanks to a few APIs that you might recognize if you have developed on a Windows CE platform. These calls can be found in the Windows Shell API documentation. For now, I'm going to focus on SHGetSpecialFolderPath. This function allows you to access the main Smartphone file system and retrieve a full path at run time. Upon retrieving this path, you can use it to store data associated with your application. This function requires a CSIDL_ constant as an input parameter. These constants represent common folders (application data, favorites, programs, startup, and so on) within the Smartphone OS. Since the locations of these common areas may differ on each device, the CSIDL constants provide a unique system-independent way to identify these special folders. It is recommended that custom applications store data in a subdirectory of the directory returned using the CSIDL_APPDATA constant, as shown here:

#ifdef CSIDL_APPDATA if(!SHGetSpecialFolderPath(NULL, szFolderPath, CSIDL_APPDATA, TRUE)) { ASSERT(FALSE); hr = HRESULT_FROM_WIN32(GetLastError()); } #else // Pocket PC doesn't have this defined so put our directory // at the root. This will likely change // in the future and this code should still work. _tcscpy(szFolderPath, TEXT("\\")); #endif

As I mentioned earlier, sometimes devices will require add-on storage cards. Unlike your desktop computer's hard drives, the Smartphone does not assign drive letters to storage cards. Instead, the OS creates directories in the root directory that represent each partition on each storage card. In order to access the various cards in a device, use the FindFirstFlashCard and FindNextFlashCard functions. FindFirstFlashCard returns a search handle and a pointer to the first storage card if any is found. If the handle returned is valid, you can pass it to FindNextFlashCard, which will return a pointer to the next storage card and a BOOL value indicating whether the search was successful.

Once you have found the flash card you want to use, your next step will be to find a location to store your data. The SHGetDocumentsFolder function should always be used when accessing documents on the device. It works equally well with both new and previously used storage cards. Here's an example of the use of SHGetDocumentsFolder:

TCHAR szDocPath[250]; if (!SHGetDocumentsFolder(L"\\",szDocPath)) MessageBox(NULL,L"Retrieveing Path Failure",L"Call Failure",MB_OK); else MessageBox(NULL,szDocPath,L"Documents Folder Path",MB_OK);

One quick note on emulators: the Smartphone emulator does not emulate storage cards. It also does not support real cards that are attached to the PC that is running the emulator.

Database Options

For almost all business applications, saving data to a local database is a necessity; the same will be true for many Smartphone applications. Compared to Windows CE and the Pocket PC, there are a few differences when it comes to database options on the Smartphone. For the first Smartphone release, Smartphone 2002, only the native Windows CE database will be supported. Unfortunately, there is no support for SQL Server™ CE or Pocket Access at this time. In addition, your only option for accessing the Windows CE database will be to use the database APIs that are included in Windows CE 3.0. The good news is that the code to access the Windows CE database is nearly identical to code written for other Windows CE-powered devices.

Synchronizing Data

After working out the connection and manipulating data, the next step is synchronizing with a remote data store. Since I have already looked at retrieving data across the Internet with the XMLDOM, I will continue with that model and send my changes back to a remote server by way of the XMLHTTP object.

Before I dig into the details of using XMLHTTP, let's look at how Smartphones can consume Web Services. Currently, there are no built-in libraries or components on the Smartphone platform that provide SOAP client functionality. However, a SOAP client for the Smartphone is not out of the realm of possibility since all the necessary building blocks are supported by the Smartphone 2002 SDK. If you want to have a SOAP client on the Smartphone, I would suggest looking into several third-party libraries that might be ported to the Smartphone without too much trouble. Also you should keep in mind that once the .NET Compact Framework becomes available on the Smartphone, you should be able to use its SOAP client functionality.

The first step in synchronizing data from a Smartphone back to a remote data store is to retrieve all changed data from main memory and to put it into an XML format. Once this has been completed, the XMLHTTP object will be instantiated and the data will be passed to the specified URL that handles synchronization.

As mentioned previously, the XMLHTTP object will be used since it has the ability to send information to the remote server in XML format. The XMLHTTP object is another one of the objects available in the MSXML library that was included in the project previously. The code for using this object is shown in Figure 4. It is quite simple to use, employing an object created from the IXMLHttpRequest interface. In addition, a VARIANT is created to hold the IXMLDOMDocument object that is being based. In order to pass this complex type, the VARIANT must be set to a VT_DISPATCH type. The only remaining steps are to call the open and send methods of the XMLHTTP object.

Figure 4 XMLHTTP Example

MSXML::IXMLDOMDocument *iXMLDoc = NULL; MSXML::IXMLHttpRequest *iXMLHttp = NULL; HRESULT hr; BSTR bStr = NULL; VARIANT vUserID; VARIANT vPassword; VARIANT vPassValue; VARIANT vAsync; short tEmpty; hr = CoInitializeEx(NULL,COINIT_MULTITHREADED); if(!SUCCEEDED(hr)) return 0; hr = CoCreateInstance (MSXML::CLSID_DOMDocument, NULL, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, MSXML::IID_IXMLDOMDocument, (LPVOID *)&iXMLDoc); if(iXMLDoc) { iXMLDoc->put_async(VARIANT_FALSE); // Smartphone 2002 workaround: // Remove document safety options IObjectSafety *pSafety; DWORD dwSupported, dwEnabled; if ( SUCCEEDED(iXMLDoc->QueryInterface(IID_IObjectSafety, (void**)&pSafety))) { pSafety->GetInterfaceSafetyOptions( MSXML::IID_IXMLDOMDocument, &dwSupported, &dwEnabled ); pSafety->SetInterfaceSafetyOptions( MSXML::IID_IXMLDOMDocument, dwSupported, 0 ); } iXMLDoc->put_async(VARIANT_FALSE); iXMLDoc->loadXML(L"<customer><first_name>Joe</first_name> <last_name>Smith</last_name></customer>", &tEmpty); } VariantInit(&vAsync); vAsync.vt = VT_BOOL; vAsync.boolVal = false; VariantInit(&vUserID); vUserID.vt = VT_BSTR; vUserID.bstrVal = L""; VariantInit(&vPassword); vPassword.vt = VT_BSTR; vPassword.bstrVal = L""; VariantInit(&vPassValue); vPassValue.vt = VT_DISPATCH; vPassValue.pdispVal = iXMLDoc; hr = CoInitializeEx(NULL,COINIT_MULTITHREADED); if(!SUCCEEDED(hr)) return 0; hr = CoCreateInstance (MSXML::CLSID_XMLHTTPRequest, NULL, CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER, MSXML::IID_IXMLHttpRequest, (LPVOID *)&iXMLHttp); iXMLHttp->open(L"GET", L"https://localhost/smartphonesavetest.asp", vAsync,vUserID,vPassword); hr=iXMLHttp->send(vPassValue); iXMLHttp->get_responseText(&bStr);

Accessing Phone Features

Through the Windows CE APIs, developers can easily add phone capabilities to their applications. Features such as automatic dialing, interaction with the call log, the ability to access the SIM card, and sending and receiving of SMS messages can easily be added to an application. One quick note: most of the telephony APIs require a real device or GSM radio attached to the emulator in order to work properly, so if you plan to develop these types of features, be prepared to test against the actual device.

One of the simplest phone features that can be added is the ability to establish a voice call from within an application. It is literally one line of code, thanks to the Assisted TAPI that ships with the Smartphone. All you need to do is include the astdtapi.h file in your code, add cellcore.lib to your linker settings, and call the tapiRequestMakeCall function, as shown here:

TCHAR szDefaultNum[] = TEXT("+1 (555) 555-5555"); LONG lResult; lResult = tapiRequestMakeCall((LPTSTR) szDefaultNum, NULL, NULL, NULL); return TRUE;

Sending SMS messages is almost as simple. As with Assisted TAPI, you will need to add a reference to one include file in the code (sms.h) and to one library in the linker settings (sms.lib). The first step when sending or receiving messages is to call the SmsOpen function. Next, initialize the source and destination addresses. After completing these steps, the SmsSendMessage function is called. The last step is to call SmsClose to clean up the SMS_HANDLE that was created. This can be seen in Figure 5.

Figure 5 SMS Code Sample

SMS_HANDLE smshHandle; SMS_ADDRESS smsaSource; SMS_ADDRESS smsaDestination; TEXT_PROVIDER_SPECIFIC_DATA tpsd; SMS_MESSAGE_ID smsmidMessageID; // try to open an SMS Handle if(FAILED(SmsOpen(SMS_MSGTYPE_TEXT, SMS_MODE_SEND, &smshHandle, NULL))) { MessageBox(NULL,L"Call to SmsOpen failed.",L"Error",MB_OK | MB_ICONERROR); return; } // Create the source address if(!bUseDefaultSMSC) { smsaSource.smsatAddressType = SMSAT_INTERNATIONAL; _tcsncpy(smsaSource.ptsAddress, lpszSMSC, SMS_MAX_ADDRESS_LENGTH); } // Create the destination address smsaDestination.smsatAddressType = SMSAT_INTERNATIONAL; _tcsncpy(smsaDestination.ptsAddress, lpszRecipient, SMS_MAX_ADDRESS_LENGTH); // Set up provider specific data tpsd.dwMessageOptions = bSendConfirmation ? PS_MESSAGE_OPTION_STATUSREPORT : PS_MESSAGE_OPTION_NONE; tpsd.psMessageClass = PS_MESSAGE_CLASS1; tpsd.psReplaceOption = PSRO_NONE; // Send the message, indicating success or failure if(SUCCEEDED(SmsSendMessage(smshHandle, ((bUseDefaultSMSC) ? NULL : &smsaSource), &smsaDestination, NULL, (PBYTE) lpszMessage, _tcslen(lpszMessage) * sizeof(TCHAR), (PBYTE) &tpsd, sizeof(TEXT_PROVIDER_SPECIFIC_DATA), SMSDE_OPTIMAL, SMS_OPTION_DELIVERY_NONE, &smsmidMessageID))) { MessageBox(NULL, L"Message sent", L"Success",MB_OK); } else { MessageBox(NULL, L"SmsSendMessage Failed", L"Error",MB_OK | MB_ICONERROR); } // clean up VERIFY(SUCCEEDED(SmsClose(smshHandle)));

There are many more phone APIs available; unfortunately, I have enough space here to cover only a few of the basics. With these capabilities, applications can be greatly extended with features that were not previously possible in mobile applications. For example, automatic calls or messages can be triggered by applications when certain events occur within an application.

Conclusion

In this article, I've covered the basics of building real-world Smartphone applications. As you can see, the types of applications Smartphone makes possible in the world of enterprise computing are quite compelling. In the near future, you should see a wave of Smartphone applications, the inevitable result of the introduction of an inexpensive device with a familiar, easy development platform into the preexisting user base of mobile phones.

For related articles see:
Developing Applications For Windows Mobile-Based Smartphones
Smartphone 2002 SDK

For background information see:
Wireless Web: Microsoft Mobile Internet Toolkit Lets Your Web Application Target Any Device Anywhere
Windows Mobile

Chris Dellingeris a senior architect at Vytek Solutions in Raleigh, NC where he specializes in mobile technologies. He can be reached at dellinger_chris@hotmail.com.