any people no longer even own a desktop; instead they love laptops, whether entry-level or expensive mobile workstations, and work on them exclusively. But laptops are too heavy to carry all the time, and too slow and cramped to be the equivalent of a desktop. Personally, I keep a desktop for heavy tasks, but carry a handheld with me all the time for less-demanding tasks—because modern handhelds are capable enough to handle many of the tasks I need to do. Sure, you can’t (or wouldn’t want to) write a long document or browse the web and get the full desktop experience, but the handheld can run my IMAP client and, most importantly, it can run specific vertical applications that make performing out-of-office field tasks fast and simple.
Mobile Devices and Mobile Workers
Most mobile devices today are mobile phones, or—if you prefer—many mobile phones are also powerful handhelds. However you prefer to think about the devices, they all provide a mobile computing platform with communications capability. I live in Italy (for now, at least until I can afford to move), where there are more mobile phones than people. Essentially, everyone has a mobile platform available. Therefore, everyone can run applications to handle some tasks without needing a laptop or desktop. In addition, most mobile phone can take good photos, and some can even detect your location, using an integrated GPS. Finally, most modern handhelds can connect to a Wi-Fi network and, of course, can connect to the Internet with wireless technology (for example Universal Mobile Telecommunications System (UMTS), which provides several megabits per second of bandwidth).
While many people need to work away from the office, not all are truly mobile workers. Instead, when in the field they typically need to complete some specific task: collect sales orders, check product availability, create invoices, collect field data, and so forth. And what they’re finding is that the more specific the tasks, the easier it is to eschew heavy devices and use a lightweight, simple, handheld device with custom software.
Windows Mobile and NET CF
Microsoft has a complete line of operating systems ranging from small devices that run a full copy of Windows Embedded, to those that run the lighter-weight Windows Mobile, which has been a strong applications platform since version 5.0 (the current release is version 6.0). Microsoft also provides a .NET framework compliant runtime for Windows Mobile, called the “.NET Compact Framework”, or .NET CF for short, now at version 3.5. .NET CF is a subset of the full .NET framework, but still includes most .NET features. The result is a platform familiar to millions of developers, programmable with Visual Studio, that uses the same software models and languages those developers use to create Windows laptop and desktop software.
For .NET developers, these features make getting into mobile software a breeze.
The biggest problem in using handhelds for work-related tasks is that the generic software available for handhelds doesn’t match their needs. Some applications fail because they aren’t specific enough; others fail to meet business needs because they assume users must complete all tasks using only the mobile device. That’s a mistake: a handheld becomes truly useful only when it’s running “connected applications;” otherwise, it’s suitable only for maintaining schedules or for playing games. A “connected application” is essentially a client-server application; the smart-client software runs on the handheld device, using a rich GUI, and provides some of the application functionality, but it’s connected to a remote server, where the bulk of the application runs. When you start thinking of mobile devices as platforms for running connected applications, you open up a whole new world of software possibilities.
For example, some time ago I wrote an application (“PalmBUS RW“) that bus ticket inspectors use to collect reports about bus status and to issue paper fines. The handhelds print fines immediately, using a small mobile printer, then transmit the collected bus status and fine data to a central server when each bus inspector returns to headquarters, using a standard Wi-Fi connection. This application makes data collection both more affordable and keeps records more up to date than using a hand-written paper system, where data had to be typed into the main system by hand. The bus inspectors have adjusted well to the handhelds; their light weight makes them perfect for a “real mobile” application such as this.
A Travelogue Application
As an example of creating a mobile connected application, the rest of this article describes the construction of a simple travelogue program. The program could serve as a personal application, but it’s architected so it could also be the basis of a more complex business application.
Here are the goals for the application:
- Users should be able to create, save, and browse “travel records.” The meaning of a travel record can vary. For a tourist, it might be simply a place to remember; for an insurance or police investigator, it might be an accident scene; for a salesperson, it might be information about a customer, and so on. For demonstration purposes, each record contains only a title, a description, a date and time, a location, and a picture.
- Users should be able to take a photo, using the handheld device, and associate that with a record.
- Users should be able to capture the record location using the device’s GPS capabilities. Each record will contain the exact position when the record was created. The position data can be used for later analysis on the server side.
- The application should be able to send all collected data to a central server. The server stores records in a database, and potentiallly makes them accessible to all users of the application.
- The application should be able to retrieve and edit existing records. Users should be able to retrieve and browse or update records stored previously.
The sample application will be a true smart client application, not just a web application that the mobile device access with a browser.
|Author’s Note: Binding GPS data to other collected data is an interesting operation that opens the door to creating geographically enabled business applications. A full discussion of managing geographic data, or associating that data with maps is out of the scope of this article, however you can find useful information in my earlier DevX articles, “Give Your Applications Mapping Capabilities” parts 1, 2, and 3.
|Figure 1. The Sample Application’s Main Screen: When users launch the sample application, they have the choice of creating new records or browsing existing records.
To follow along for development purposes, you need only Visual Studio 2008 and VB.NET, nothing else (VS includes a full emulator). However, if you want to test the functionality by loading the application onto a real device, you’ll also need a Windows Mobile 5 or 6 device, with an internal or external GPS receiver, and photo capability. The Windows Mobile 6 SDK includes an emulator that can provide GPS functionality, so you can also download that as a testing platform. I strongly suggest you download and install the Windows Mobile 6 SDK, because you’ll find a working example showing how to take a photo programmatically from .NET CF.
The application consists of a main form (see Figure 1) where users select an operation to perform, an entry form that collects user-entered data for new records, and a form for searching and displaying existing records.
A simple web service architecture serves to connect the mobile software with the central server application. It’s worth mentioning that you could create this using many different technologies—including the new .NET 3.x Windows Communication Foundation (WCF)—but this example uses a simpler ASMX web service, a technology that’s also available to VS 2005 users.
The data collection form collects user-entered data for all the required fields and makes the call to the remote web service to submit the collected data.
|Author’s Note: Creating the server side application is out of the scope of this article, which concentrates on creating the client. However, the downloadable sample application provides a simple dummy server-side component so you can see how a “real” central application would work with the mobile application.
Calling a web service from a .NET client application is quite trivial, as you’ll see later; you just need to add a web reference in Visual Studio by selecting the “Add Web Reference…” item from the Project menu. You’ll need to provide the current URL (obviously this URL can change later, for example when you go in production environment) of a working web service. Visual Studio decodes the web service’s manifest and creates a lot of code for you. After successfully adding a web reference, you can call the methods exposed by the web service just as you would any local method. Behind the scenes, Visual Studio handles all the required operations to create the “real” interaction with the web service.
The Web Service
To supply the mobile application with a connection to the central server, you need a simple web service. The web service example used here exposes a Travelogue object and two methods. Remember, a Travelogue is a record that contains a title, a description, a date and time, a location, and a picture. The first method, LoadData, accepts a new object to save, assigns it a unique ID, and saves it to a back-end database (this is the dummy function, because there’s no central application for it to connect to). Finally, LoadData returns the assigned ID to the caller.
The second method, GetTravelogues, takes a string used as a filter on the Title property, and returns a list of Travelogues according to filter. To simulate the name search, the dummy implementation returns a fixed list of Travelogue objects from a private function (GetDummyList), and filters that. So you will never see the objects you saved, because the list is immutable for this demonstration.
|Author’s Note: I used the new Language Integrated Query (LINQ) features to create a very quick and simple filter and retrieve function. This code works only on .NET 3.5, but LINQ is a very powerful feature. Creating the same functionality without LINQ requires both more work and results in less-intuitive code.
Here’s some stub code for the two web methods:
_ Public Function LoadData( _ ByVal newItem As Travelogue) As Guid ' -- assign a new guid newItem.ID = Guid.NewGuid ' TODO: saves data ' -- returns assigned guid Return newItem.ID End Function _ Public Function GetTravelogues( _ ByVal filterName As String) _ As List(Of Travelogue) ' -- retrieves a filter output list from the dummy db Dim out = From t As Travelogue In GetDummyList() _ Where t.Title.Contains(filterName) _ Select t Return out.ToList End Function
The form that collects data has two parts. The first part collects data from the user and from device peripherals (the photo and GPS data). The second sends the collected data to the server.
To collect the Title and Description for each record, the application just needs a couple of TextBoxes (see Figure 2). Users can enter required values, and the application can read the entered values from the TextBox.Text property—in other words, the code is identical to standard .NET applications. Obtaining the date and time is also standard; you can get the current date and time using the DateTime.Now shared property.
|Figure 2. Adding a New Record: To create a new record, users enter a title and description, and then click Send.
Getting a GPS position is slightly more difficult; you need to access the GPS receiver, read data, and then parse it to obtain latitude and longitude values. This could be a complicated process, but fortunately, Windows Mobile provides a GPS API that makes it easy. You can call the API from managed code just as you would any other unmanaged API. If you aren’t familiar with calling unmanaged code, there’s some good news: the Windows Mobile SDK download includes a full working example showing the code required to access the GPS API and retrieve the devices’s current position. You need only subscribe to an event, and you get the data, ready to use.
The example application uses the project provided with the Windows Mobile 6 SDK, but version 5 has the same code. Using this approach, you only need to configure the GPS API on the device to connect it to a GPS serial port (for example, the virtual serial port defined with a Bluetooth connection). You can get the current position with this code:
' -- reads the position from GPS Dim gps As Microsoft.WindowsMobile.Samples.Location.Gps Try ' -- opens GPS device connected to GPS API gps = New Microsoft.WindowsMobile.Samples.Location.Gps gps.Open() Dim pos As Microsoft.WindowsMobile.Samples.Location.GpsPosition = _ gps.GetPosition() newItem.Latitude = pos.Latitude newItem.Longitude = pos.Longitude gps.Close() Catch ex As Exception ' -- position is unavailable Finally If gps IsNot Nothing AndAlso gps.Opened Then gps.Close() End Try
In this example, if GPS data is unavailable (for example, the GPS device is off, or there is some configuration error), the code just ignores the problem and doesn’t provide a position in its record. However, in real-world applications in which position is critical, you may need to handle this scenario better, for example, require the user to turn on the GPS functionality, or reboot the device.
Taking a photo is a more complex operation. But again, the Windows Mobile SDK includes a managed object that can do most of the work, the Microsoft.WindowsMobile.Forms.SelectPictureDialog. The dialog provides all the UI and background code for taking a photo and saving it in a file, or for selecting an existing image file on the device’s memory. So your application just needs to wrap this to display the dialog and read any saved files. Those files hold the photos needed for the sample application. Note that there are other ways to take a photo programmatically that range from calling the device’s API directly to creating a custom dialog that doesn’t save any file but would simply take a photo and manage it in memory (this is probably the best solution, and certainly the most flexible). However, for this application a simple solution will suffice, so it uses the ready-made SelectPictureDialog method.
You can also check if the device has a camera by calling the Microsoft.WindowsMobile.Status.SystemState.CameraPresent method, which you can access by referencing the Microsoft.WindowsMobile.Status assembly. The required code is quite simple: you show the dialog, and then read from memory the file that the dialog has selected (which, in fact, is the photo taken with the camera and saved to disk by the dialog itself).
If Microsoft.WindowsMobile.Status.SystemState.CameraPresent Then Using selectPictureDialog As _ Microsoft.WindowsMobile.Forms.SelectPictureDialog = _ New Microsoft.WindowsMobile.Forms.SelectPictureDialog() selectPictureDialog.Title = "Travelogue example" selectPictureDialog.CameraAccess = True If DialogResult.OK = selectPictureDialog.ShowDialog() Then ' -- reads image from file Dim image() As Byte Using stream As System.IO.FileStream = _ System.IO.File.OpenRead(selectPictureDialog.FileName) ReDim image(CInt(stream.Length) - 1) stream.Read(image, 0, image.Length) End Using ' -- assigns image to item to upload newItem.Image = image End If End Using End If
|Author’s Note: Running the code to take a photo targeted to Windows Mobile 5.0 requires that you test your application on a real device that has a camera. Device emulators cannot provide a virtual camera, so they will present just a form to select an existing image file from your memory. Windows Mobile Standard 6.0 emulator can provide a better experience by emulating camera controls, but clearly it cannot provide real camera emulation.
After collecting all the data, you need to send the record to the remote server for permanent storage. Visual Studio and the .NET framework provide robust web service integration, so calling a remote function and passing data is quite trivial. All the heavy work gets delegated to .NET libraries.
Here’s the required code:
Dim assignedID As Guid ' -- prepares data to send Dim newItem As New Travelogue.Travelogue ' -- [omitted: assigns value to newItem's properties: ' Title, Description, Latitude, Longitude, Image, etc.] Try ' -- calls the remote web service to upload new record Dim assignedID As Guid Dim remote As New Travelogue.TravelogueService assignedID = remote.LoadData(newItem) ' -- reports operation has completed MessageBox.Show("Data uploaded succesful with ID " & _ assignedID.ToString, "Operation Complete", MessageBoxButtons.OK, _ MessageBoxIcon.None, MessageBoxDefaultButton.Button1) ' -- closes current form and releases resource Me.Dispose() Catch ex As Exception MessageBox.Show("Unexpected error during upload." & vbCrLf & _ ex.Message, "Error", _
MessageBoxButtons.OK, _ MessageBoxIcon.Exclamation, _ MessageBoxDefaultButton.Button1) End Try
Figure 3. Sucessful Send: This corroborating message appears after a user successfully submits a new record.
As the preceding code shows, all you need to do is create an instance of the WS proxy that Visual Studio creates for you when you add a web reference to an existing web service. Then you can simply call the remote method as if it were a standard, local object. The preceding code displays any return message (see Figure 3) or error message if the operation fails. Note that you cannot distinguish the remote call from a standard call.
Retrieving Old Data
The form that retrieves old data has two goals: call the remote web service with (optionally) some user-entered filter values, and show data on the GUI.
The first task is quite trivial, and it’s very similar to the data-inserting function that you saw in the preceding section. The second task is also quite trivial, because you just need to bind the list of Travelogue objects returned by the web service to a standard DataGrid (see Figure 4 and Figure 5). As you can see, the programming model is exactly same as writing a standard .NET desktop application.
Here’s the code:
Dim results As List(Of Travelogue.Travelogue) Try ' -- create the proxy to remote web server Dim remote As New Travelogue.TravelogueService ' -- make the remote call results = remote.GetTravelogues(txtTitle.Text).ToList Catch ex As Exception MessageBox.Show("Error during download" & vbCrLf & _ ex.Message, "Error", MessageBoxButtons.OK, _ MessageBoxIcon.Exclamation, _ MessageBoxDefaultButton.Button1) End Try ' -- bind the result to GUI control dgResults.DataSource = results
From Example to Real World
In a real-world application you would need to add some additional features to create a truly useful application. For example, adding a client side cache would avoid multiple round trips to the server; using compression techniques to compact data transferred over the wireless network could improve application performance; and a security system to protect the data and both ends of the application would be required. However, adding these features won’t require a change to the underlying architecture, which you can expand to fit any requirement.
Mobile devices are not expensive toys. They can be a mobile worker’s best friend if he or she works in the field and needs a really portable, lightweight, yet powerful tool.
From an enterprise’s prospective, it may be more cost effective to develop an integrated and focused application that runs on mobile devices and integrate that with a business-class central system than to buy laptops and run generic “datasheet” applications on them, or use Terminal Services or Citrix sessions that execute software on a remote server. The mobile applications require tightly-controlled project management, of course, but they can make everyday tasks easier and more palatable for users.
From a programmer’s prospective, Microsoft has made a great effort to provide a development platform that is both powerful and easy to use. Developers familiar with .NET can start developing mobile applications using .NET CF without learning a new development environment or language. As usual, knowing a programming language or a development tool doesn’t necessarily mean that new mobile developers will be able to create production-level business applications immediately; moving to mobile development isn’t trivial. In particular, connected applications require architectural knowledge that can impact the application, not just programming. However, Microsoft has opened the door to the mobile development world, and now is a good time to enter.