Windows Mobile: Communicating with the Outside World

n last month’s DevX special report, I showed you how you can develop for the Windows Mobile platform using the .NET Compact Framework. Now, you’ll expand on those concepts and learn how you to explore the various communication options available on this platform so that your applications can connect to the outside world. In particular, this article will discuss:

  • Short-range communications technologies such as:
    • Infrared
    • Bluetooth/serial port
  • Long-range communications technologies such as:
    • GPRS/EDGE
    • WIFI

You’ll also learn how you can use the managed APIs in the .NET Compact Framework to program:

  • Infrared communications
  • Serial communication over Bluetooth
  • Sockets communications
  • Web services

The last section of this article shows how to develop a Windows Mobile application to take pictures using the built-in camera and then upload the picture to a web service.

IrDA
Infrared communication is one of the most common forms of communication for devices today. If you’ve ever used a TV remote control, you’ve experienced the convenience of using infrared communications. While infrared communications require line-of-sight between the sending and receiving devices, they are a quick and cheap way of communicating between devices.

The beauty of infrared is that it requires no pairing of devices, and certainly does not require the hassles of exchanging secret pin numbers (unlike Bluetooth). For this reason, it is suitable for applications that require fast exchanges of information. For example, you might want to use infrared to exchange electronic business cards with a business associate. In the .NET Compact Framework, the core classes for infrared functionalities are located in the System.Net.Irda.dll DLL. Hence, you’d need to add a reference to this file in your project.

For the code described below, you need to import the following namespaces:

using System.IO;using System.Net;using System.Net.Sockets;

Receiving Data
To receive data on a Windows Mobile device using infrared, you need to use the IrDAListener class’s AcceptIrDAClient() method to listen for and then accept an incoming infrared connection. Once a connection is established, you will use a Stream object to read the incoming data into a byte array.

The following code snippet shows how you can listen for incoming infrared data and then print out the received data to the output window (see Listing 1).

Sending Data
To send data to another device using infrared, you first try to establish a connection with the remote device using the IrDAClient class. Once a connection is established, you can send the dataover to the remote device using a Stream object.

The code in Listing 2 shows how you can connect to a remote device using infrared and then send a string to the device.

Note that two communicating devices must have the same service name (defined by the constant SERVICE_NAME), as specified in the constructor of the IrDAListener and IrDAClient classes.

Bluetooth/Serial Port
While infrared communication is a quick and dirty way of exchanging information, the downside is it requires line-of-sight in order to work correctly. In addition, infrared communication is inherently slow, and is thus only suitable for exchanging small amounts of information.

Another popular wireless technology widely used today is Bluetooth. Bluetooth is a short-range wireless technology that does not require line-of-sight to work. Once two devices are paired, information can be exchanged between the two devices within a distance of 10 to 100 meters.

The .NET Compact Framework does not include any managed classes for dealing with Bluetooth devices, so it’s not easy to manage Bluetooth communication within your Windows Mobile application without resorting to using the native APIs via P/Invoke. However, most Bluetooth devices support the serial port profile, which means you can communicate with these devices over a serial connection. Fortunately, beginning with .NET CF v2.0, you can use the SerialPort class to manage serial communications.

Here’s a list of some of the devices that you can communicate with using the serial port:

  • Windows Mobile to Windows Mobile (through Bluetooth)
  • GPS receivers (through Bluetooth)
  • Mobile phones (through Bluetooth and using AT commands)
  • RFID readers and writers (through direct hardware connection)

To use the SerialPort class in the .NET CF, you need to import the following namespace:

using System.IO.Ports;

The following statement creates an instance of the SerialPort class:

        SerialPort sp = new SerialPort();

Sending Data
Before you can use the serial port, you first need to setup the required communication parameters. Next, open the connection and once the connection is established, you can send data to the remote device using the Write() or WriteLine() method:

            const string MESSAGE_TO_SEND = "hello world!";            //---close the port if it is open---            if (sp.IsOpen)            {                sp.Close();            }            try            {                //---set all the required comms parameter---                sp.PortName = "COM1";                sp.BaudRate = 9600;                sp.Parity = Parity.None;                sp.DataBits = 8;                sp.StopBits = StopBits.One;                //---open the connection---                sp.Open();                //---send some data over---                sp.WriteLine(MESSAGE_TO_SEND);            }            catch (Exception ex)            {                throw ex;            }

Receiving Data
Receiving data from a serial port could not be easier. You simply need to handle the DataReceived event of the SerialPort class and this event is fired every-time there is incoming data:

            SerialPort sp = new SerialPort();            //---wire up the DataReceived event handler---            sp.DataReceived += new                SerialDataReceivedEventHandler(sp_DataReceived);

You can read the incoming data using the Read(), ReadByte(), ReadChar(), ReadExisting(), ReadLine(), or ReadTo() methods:

        void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)        {            //---read all incoming data and write it to the output window---            Console.WriteLine(sp.ReadExisting());        }

Sockets
The previous two sections discussed about the short-range communications using infrared and Bluetooth (and serial port). Besides these two communication options, your device may also be connected to the Internet using GPRS, EDGE, or WIFI. In such cases, your applications will now be able to connect to servers and exchange information.

There are primarily two ways to connect to servers for data exchange:

  • Using sockets (TCP/IP)
  • Using Web services (covered in the last section of this article).

A socket is an abstract description of a means of sending and receiving data between computers/applications on a network. It describes a connection between two communicating points (which may be on different computers or within the same computer).

In practice, socket programming is commonly associated with TCP/IP and UDP/IP communications. TCP is a connection-oriented network protocol that guarantees reliable and in-order delivery of packets (through acknowledgements). Coupled with IP, TCP is adopted as a popular networking protocol by applications such as web browsers and email clients. In contrast, UDP is a connection-less network protocol that sends packets from one point to another, with one exception?it does not provide reliable and guaranteed delivery.

Sockets programming using TCP/IP is straight-forward?one party listens for incoming data and the other party sends the data (both parties can listen for data and send data at the same time). When using sockets, you send the data in raw directly without needing to encapsulate the data using a messaging medium (such as XML), and because of this socket is an efficient way to exchange data between a device and a server (or another client). The downside to using sockets is that it is relatively more complex and requires the programmer to write the code for the server and the client.

To use sockets in your .NET CF application, import the following namespace:

using System.Net.Sockets;

For the purposes of this article, you will learn how to write a server and client application using a TCP socket.

Receiving Data
You can listen for incoming data using the TcpListener class’s AcceptTcpClient() method (if you recall the code for infrared communication the concept is similar). However, like the infrared example, the AcceptTcpClient() method is a blocking call, which means that the method will block until a client is connected. While this is alright for infrared communication (you only communicate with one device at a time), this is not really practical for sockets communication. For sockets communication, it is likely that you have multiple clients connected to your server at any one time and hence you need to do some extra work to ensure that your server supports multi-users.

To do so, create a class called Client and code it as shown in Listing 3.

Here, the constructor takes in a TcpClient object and starts to read from it asynchronously using the receiveMessage() method. Once the incoming data is read, it continues to wait for more data.

To ensure that the server supports multi-user, you use a TcpListener class to listen for incoming client connections and then use an infinite loop to accept new connections. Once a client is connected, you create a new instance of the Client object and continue waiting for the next client. This is shown in the code below:

            const string SERVER_IP = "192.168.1.1";            const int PORT_NO = 500;            IPAddress localAddress = IPAddress.Parse(SERVER_IP);            //---listen at the specified address---            TcpListener listener = new TcpListener(localAddress, PORT_NO);            //---start listening---            listener.Start();            while (true)            {                Client user = new Client(listener.AcceptTcpClient());            }

Sending Data
To connect to the server using a TCP socket, you will use the Socket class. Listing 4 shows how you can use the Socket class to connect to a TCP server and then sends some data using a byte array.

A Sample Application Using Web Services
Besides the connectivity options above, you can also use web services for transferring data if you have WIFI or GPRS connectivity. In this section, you will learn how you can use web services to transfer binary data.

As you are probably aware, web services are inherently text-based as it uses XML as the messaging medium. Hence, if you want to transfer binary data using web services, you would need to “flatten” the binary data before you can send them over using XML text.

The project you will build in this section shows how you can use the built-in camera of your Windows Mobile device to take pictures and then upload the pictures to a web service.

Using Visual Studio 2008, create a new ASP.NET Web Service project and name it http://localhost/FilesUploadWS (see Figure 1).

Figure 1. Your Camera: Create a new ASP.NET Web Service project.

Import the following namespace:

using System.IO;

Define the UploadFile() web method so that users can upload the picture to the server (see Listing 5).

In the above method, the first parameter takes in a base64 encoded string (of the picture) and the second parameter is the filename of the picture. The base64 encoded string is first decoded into a byte array and then saved into the publishing directory of the web service. That’s all you need to do for the web service.

You will now build the Windows Mobile application to take pictures and then send them over to the web service.

First, add a new Smart Device project to the current solution and name the project PictureTaker.

Next, add a reference to the Microsoft.WindowsMobile.Forms.dll DLL to your project. Then, add a PictureBox control to the form and create the two MenuItem controls as shown in Figure 2.

Figure 2. Form1: Populating the default Form1.

Switch to the code-behind of Form1.cs and import the following namespaces:

using System.IO;using Microsoft.WindowsMobile.Forms;

Define the following member variables:

    public partial class Form1 : Form    {        string _fileName = string.Empty;        string _fileNameWithPath = string.Empty;

Define the ConvertToBase64() method so that you can convert a binary file into its base64 equivalent (see Listing 6).

To consume the web service project you have created earlier, add a web reference to the project. Be sure to use the IP address (or machine name) of the computer hosting the web service; specifying “localhost” will cause the application to fail during runtime. Name the web reference FilesUploadWS (see Figure 3).

Figure 3. FilesUploadWS: Adding a web reference to the project.

Double-click on the Take Picture MenuItem control to reveal its Click event handler. Code it as follows:

        private void mnuTakePicture_Click(object sender, EventArgs e)        {            CameraCaptureDialog ccd = new CameraCaptureDialog()            {                Resolution = new Size(100, 200),                Mode = CameraCaptureMode.Still,                [email protected]"My DocumentsMy Pictures"            };            //---show the CameraCapture Dialog---            ccd.ShowDialog();            if (ccd.FileName != string.Empty)            {                //---save the filename---                _fileName = ccd.FileName.Replace(ccd.InitialDirectory,"");                _fileNameWithPath = ccd.FileName;                //---load the image---                pictureBox1.Image = new Bitmap(ccd.FileName);            }        }

You can use the CameraCaptureDialog class to activate the built-in camera of your Windows Mobile device and then display the picture using the PictureBox control.

To send the picture to the web service, double-click on the Upload Picture MenuItem control and code it as follows:

        private void mnuUploadPicture_Click(object sender, EventArgs e)        {            FilesUploadWS.Service ws = new                PictureTaker.FilesUploadWS.Service();            try            {                //---upload to web service---                ws.UploadFile(ConvertToBase64(_fileNameWithPath), _fileName);            }            catch (Exception ex)            {                MessageBox.Show(ex.Message);            }        }

You need to encode the picture into base64 encoding first, then send it over to the web service using the UploadFile() web method.

That’s it! To test the application, deploy the application to a Windows Mobile device. Ensure that the device has connectivity and is able to reach the web server hosting the web service. You can now take a picture using the camera and once a picture is taken you can send it to the web service. If you use the default web publishing directory C:inetpubwwwroot for your web service, the uploaded picture would be found from: C:InetpubwwwrootFilesUploadWS.

Choose Wisely!
In this article, you have seen the various ways in which your Windows Mobile application can communicate with the outside world. Which technology you choose depends on the type of data and the devices with which you are trying to communicate:

  • If you need a quick and dirty way to exchange data with another Windows Mobile device, use infrared.
  • If you have some external devices (such as GPS receivers, RFID snap-ons, etc), use the serial port connection.
  • If you are on an expensive connection (such as GPRS where you pay by the amount of data you transfer), use sockets where you can send the data in the raw.
  • If you are on a free connection (such as WIFI), use web services for sending and retrieving data from servers. This is easier to develop and does not add much to your application’s running cost.
Share the Post:
Share on facebook
Share on twitter
Share on linkedin

More From DevX