Writing Mobile Code Essential Software Engineering for Building Mobile Applications [Electronic resources] نسخه متنی

اینجــــا یک کتابخانه دیجیتالی است

با بیش از 100000 منبع الکترونیکی رایگان به زبان فارسی ، عربی و انگلیسی

Writing Mobile Code Essential Software Engineering for Building Mobile Applications [Electronic resources] - نسخه متنی

Ivo Salmre

| نمايش فراداده ، افزودن یک نقد و بررسی
افزودن به کتابخانه شخصی
ارسال به دوستان
جستجو در متن کتاب
بیشتر
تنظیمات قلم

فونت

اندازه قلم

+ - پیش فرض

حالت نمایش

روز نیمروز شب
جستجو در لغت نامه
بیشتر
لیست موضوعات
توضیحات
افزودن یادداشت جدید











Communications and Networking Options


A mobile application can utilize many different communications mechanisms to move information onto or off the device. It is important to realize that there is no uniquely best communications mechanism. Each mechanism has its own strengths, weaknesses, and appropriate usage scenarios. Some communications mechanisms are peer to peer, some are body-area network oriented, and others are Internet or LAN oriented. When looking at a given communications need, it is helpful to draw up a list of the potential solution technologies and map out how a solution using those technologies would work. In almost all cases, there will be more than one potentially applicable solution, and deciding which mechanisms are best suited for your mobile application needs is a matter of both creativity and hard-nosed analysis. Below are described some of the most common communications mechanisms.

Wi-Fi: Local Area Networking


Also known as 802.11 (in all of its flavors, 802.11a, b, g, etc.), Wi-Fi is essentially short-distance Ethernet-based communication done wirelessly; it is a communications mechanism for local area networks (LANs). Wi-Fi has many things to recommend it: It is popular, conceptually easy to use, it supports relatively high-bandwidth communications (for example, often 10Mbps or better), it is easy to set up, and Wi-Fi communications tend to be inexpensive. A Wi-Fi base station connects to the network and usually provides wireless access in a diameter of a few hundred feet if not obstructed (see Figure 15.1). Communicating over Wi-Fi is generally programmatically identical to communicating over an Ethernet cable. As a general-purpose "I need network connectivity" solution, it is a great choice. There are, however, several things to consider when using Wi-Fi for communications:

Do you do Wi-Fi?
Not all mobile devices support Wi-Fi. Most laptops today have Wi-Fi built in, but most mobile phones do not. Some mobile devices will allow a Wi-Fi card to be added, commonly via a Compact Flash or Secure Digital card. In the future, more devices will support Wi-Fi, but this will not be a ubiquitous choice.

Your Wi-Fi or somebody else's?
If you have a fixed amount of area that needs network access, it is feasible to set up your own Wi-Fi connections. If your mobile application needs to work in the world at large but does not need continuous network connections, using a third-party Wi-Fi network is reasonable as well. In most places today, it is relatively easy to find a reputable "Wi-Fi hot spot" in a hotel or in a city at large if the mobile application's user is willing to look for one. However, despite user enthusiasm and a great deal of hype, it is unlikely that good Wi-Fi access options will blanket the earth any time soon. Even if there were more blanket Wi-Fi coverage, different Wi-Fi services would have different payment models and access rights, ranging from free to expensive. Free networks come with few guarantees. Some Wi-Fi networks will allow access to the Internet at large and some only to the local LAN. All Wi-Fi access is not equal. When traveling along large stretches of highway or making your way through a city of any reasonable size, you will find a lot of empty space dotted with a frequent but not ubiquitous patchwork of Wi-Fi base stations.

Security
Sending packets over a Wi-Fi connection is like shouting from the roof of a building; everyone who wants can hear you. This is not as bad as it sounds because Wi-Fi networks can offer various degrees of built-in encryption support, ranging from shared secret keys between the Wi-Fi base station and the devices to certificate/public keybased security (which is highly secure). Even when communicating over a public unencrypted Wi-Fi channel, it is easy to use SSL (Secure Sockets Layer) or HTTPS (Secure HTTP) communications to encrypt your application layer communication. If you are transmitting important data, be prepared to encrypt it.

Power consumption
Wi-Fi is not a particularly power-efficient communications mechanism. As devices and their batteries become smaller and smaller, the power budget to support Wi-Fi communications becomes smaller. This means that there is a practical limit to how small a device can be and still support usable Wi-Fi communications. Doubtless hardware and software innovation will occur in this area, but today problems remain.


Figure 15.1. The nomadic wanderings of a Wi-Fi user. Wi-Fi enables pockets of high bandwidth communications. Wi-Fi-dependent applications require the user to travel to a Wi-Fi hot spot to get connectivity. While the mobile application is synchronizing, the user is typically not moving in between Wi-Fi access points (that is, not roaming).

[View full size image]

A Few Words on WiMax


WiMax, also known as 802.16 and 802.20, is an emerging standard intended to blend the best of Wi-Fi with the best of mobile telephone networks and provide high-bandwidth Wi-Fi-like packet-based networking over large areas and potentially allow roaming between access points. Whereas 802.11 (Wi-Fi) is intended for wireless LANs (local area networks), these new standards are intended to enable wireless MANs (metropolitan area networks) covering much larger radiuses than Wi-Fi. Like any new standard, WiMax will almost certainly take some time to emerge but it does offer significant promise for faster communications at lower costs. Traditional fixed-line network operators, mobile network operators, and communications hardware manufacturers all have significant competitive interests in this area and how this communications landscape will develop is anyone's guess at this point. The author of this book makes no predictions other than to offer his opinion that it will be an interesting and wild ride for the next few years. As with all the wireless communications mechanisms discussed here, working with WiMax will require your application to deal with intermittent network access and heterogeneous networks consisting of Wi-Fi, WiMax, 2.5G, 3G, and other networking technologies.

See [http://grouper.ieee.org/groups/802/16/] and [http://grouper.ieee.org/groups/802/20/] for more information on these emerging standards.

Bluetooth: Personal Area Networking


Bluetooth, a communications mechanism for personal area networks (PANs), is intended to network together the kinds of devices users may have around themselves in their immediate environment. PDAs, laptops, mobile phones, printers and perhaps even vending machines and kiosks are all potential Bluetooth networking targets. Bluetooth's intent is to allow various different devices that come into proximity to one another to form ad hoc relationships. As Figure 15.2 shows, there are two kinds of computing devices that Bluetooth connects, personal devices carried by an individual and external devices that the owner of a Bluetooth-enabled device may come into contact with.

Figure 15.2. Personal area network schematic.

[View full size image]

A common misnomer about Bluetooth is that it is just "one thing" or a single communications protocol; actually it is not. Although built on top of a core networking stack, the most important thing about Bluetooth is the "profiles" that are built on top of it. Bluetooth itself is a low-level communications mechanism, but almost all the interesting work happens at the level of Bluetooth profiles. The practical implication of this is that unless two different devices happen to support the same Bluetooth profiles, they will have little to say to one another. For instance, a Bluetooth printer that supports the Bluetooth "Basic Printing Profile" may be dimly aware of the fact that there is a remote control in the same room that supports the "A/V Remote Control Profile," but the two devices have nothing meaningful to say to one another unless they share a common set of profiles. A list of supported profiles is available on the Bluetooth organization's Web site, [www.bluetooth.org].

In practice, the need for two devices to have matching profiles is not as limiting as it sounds because of two reasons: (1) Common devices that would benefit from talking to one another tend to support sets of overlapping profiles; and (2) Although there are many profiles, in practice a few dominate the areas interesting to mobile devices. Common profiles exist for synchronizing PDA-type information and for using your mobile phone as a network connections hub.

Importantly a profile also exists for using a Bluetooth device as a RS-232 serial port; this is appropriately called the Serial Port Profile. This allows a Bluetooth device to appear as a COM port and supports old-style serial communications. Many legacy information sources have traditionally used RS-232 serial port communication, and these communications protocols have gained wide acceptance over the years. Traditionally, these devices have hooked into computers using a RS-232 cable. A prime example of this that is relevant to mobility is GPS (Global Positioning System) receivers. These have for many years used a NMEA (National Marine Electronics Association) serial protocol to transfer global positioning information from a location sensor to a computing device. These devices are now going wireless; and instead of designing brand new protocols, many of the next generation of these devices have elected just to continue to communicate with the same proven serial protocols they have in the past but to do so over a wireless Bluetooth connection.

Programming using Bluetooth follows a similar pattern to working with the profiles listed above. A developer working with Bluetooth can either work with low-level Bluetooth APIs, possibly via sockets if the device supports a mapping between sockets and Bluetooth, or they can work using profile-specific APIs. For example, if a Bluetooth device is being accessed via the Serial Port Profile, the developer can dispense with any need to think about Bluetooth altogether and simply work with COM port APIs. The choice is up to you, but as noted earlier in this chapter more abstract higher-level APIs are almost always easier to work with. Even the serial port APIs can be much simpler to work with than delving into the details of Bluetooth communications. If you have the possibility of working with simpler, more abstracted APIs it is recommendable to do so.

If you are programming with the .NET Compact Framework version 1.1, you will need to call into native code to access Bluetooth functionality unless a third party has already built specific managed-code wrappers for you to use. The .NET Compact Framework version 1.1 has no built-in support either for working with Bluetooth or with the COM serial port. There is, however, good sample code on [www.gotdotnet.com] that can show you how to call into native code to accomplish low-level communications tasks such as serial port access.

Note: Because Bluetooth was designed specifically with mobile devices in mind, it tends to have fairly good power-consumption characteristics, but there are even more specialized communications mechanisms available if needed. In addition to personal area network technologies such as Bluetooth, there also exist lower-power-consumption body area network (BAN) technologies such as Zig-Bee (IEEE 802.15). These BAN networking protocols are suitable for embedded sensors and other kinds of devices that require very low power consumption.

Mobile Phone Networks/Cellular


The principal advantage of mobile phone network communication is broad area availability. The wide-area coverage of mobile phone networks is so pervasive that it is easy to forget how novel this facility really is; it truly offers the possibility of "data almost anywhere." This advantage is tempered by three disadvantages: generally lower bandwidth, generally higher data-transfer costs, and fragmented network standards. Even with these disadvantages, mobile phone networks are important potential conduits for your mobile application's data. It is important to understand something about them to make proper usage of the services they offer.

Modern mobile phone networks offer both voice and data channels for communications. Mobile phone network data channels offer applications the ability to send and receive data at moderate to good data rates. The actual data rate will vary considerably for different network technologies as well as due to local contention by other mobile devices to use the data facilities. Just as an unlimited number of phone conversations cannot be supported by a single mobile communications base station (a.k.a. "cell tower"), there is a fixed amount of data bandwidth that must be shared by different users. This is also true for other technologies such as Wi-Fi, but an important difference is that because a mobile phone network base station serves a much larger radius than a Wi-Fi base station, the bandwidth can more easily be diluted by a large number of users.

Mobile network technology is fragmented by region as well as by technical generation. A full discussion of this subject would fill its own book and probably be out of date before it was published. For reference, here are a few of the most relevant terms:

Mobile Network technology: GSM and CDMA phone networks
Traditionally, Europe and the Middle East have used GSM mobile technology standards, and North America and Korea have used CDMA. (Older North American networks used TDMA, and Japan used yet another standard.) This line is staring to blur as increasingly some North American mobile phone operators have started to offer GSM services; these services are typically first available in high-population areas. GSM radio frequencies used in North America and Europe differ, and to use a mobile phone in both environments an appropriate "dual-band" or "tri-band" phone is required; thankfully these phones are quite common today, and rich mobile devices commonly offer this capability. There are also efforts to produce single phones that can communicate using different standards (for example, CDMA and GSM on the same phone); these may or may not prove to be viable in the marketplace. At the same time, newer standards such as CDMA2000 (the 3G successor to CDMA) and W-CDMA (the 3G successor to GSM) are also replacing older standards. Mobile standards are converging, but it will be many years before the concept of an affordable phone that works anywhere in the world is a reality.

Technological generation: 2.5G, 3G, Beyond 3G.
These G numbers refer to the generation of the mobile network technology. Generally speaking, the higher the number, the faster the network. For most mobile device data purposes, 2.5G is the first generation that has practical value. 2.5G for GSM mobile networks is generally referred to as GPRS (General Packet Radio Service). 3G networks offer significantly higher data rates, but are relatively new, and there are business challenges in deploying these networks widely. 3G handsets can typically roam and operate in 2.5G environments with 2.5G data rates. UMTS (Universal Mobile Telecommunications System) is another name for 3G data services. Anything beyond this (4G and so on) is generally referred to as "Beyond 3G"; as of the writing of this book, these are still on the drawing board. Note: Mobile data communication is also possible on "2G" networks; 2G networks typically use the voice channel for data communications so that accessing the data network is akin to making a phone call. A 2G mobile phone network is a first-generation digital network; 1G = analog communication.


If all of this sounds confusing, it's because it is. The global world of mobile phone communications is a mess today! Moreover, it is likely to remain a global patchwork of different systems and generations of technologies for some time to come. The reason for this is primarily financial; it costs a huge amount of money to license radio spectrum from governments as well as to deploy and operate mobile networks. This means that rolling out new networks is a costly endeavor and is generally done in a patchwork "wire the most lucrative markets first" basis. Network upgrades are expensive, often requiring new base stations and customer handsets. Movement to a new generation of technology requires deploying parallel overlapping networks that allow network operators to continue supporting existing paying customers while developing new services. Further complicating this ecosystem is the fact that many mobile telephone network operators view Wi-Fi as both a threat and potential opportunity; different carriers are taking different approaches to giving their existing mobile telephone customers access to Wi-Fi hot spots with common billing mechanisms. The following are some guidelines for navigating the mobile network choices available for use by mobile applications:

Abstract the network technology.
Thankfully, as a mobile application developer, you can be abstracted from most of the lower-level details of mobile communications technologies. A socket connection to a Web server is the same on 2.5G or 3G networks, and the socket does not care whether the underlying radio technology is CDMA, GSM, or something else. The important learning here is to work at the highest level of technological abstraction that is possible. HTTP requests and responses are a good high level of abstraction, sockets are one level lower but also neutral to the networks used. The farther you can get away from the device's radio interface, the more portable your mobile application will be. There is no reason why a properly designed mobile application should not run unaltered on a GSM or CDMA network.

Deal gracefully with lower data rates.
Although 3G networks can offer considerably higher throughput, for the foreseeable future it is reasonable to assume that your target mobile devices will probably operate in a mixed 2.5G and better environment. For a 2.5G network, it is reasonable to assume a base communications speed of around 20Kb/second; 20 kilobits/s = 2.5KB a second. It is possible your application will get higher data rates when running on better networks, but equally possible your data rates will be lower on crowded networks; this is somewhere around the speed of an analog phone modem. A second consideration is latency; a 2.5G mobile data channel will almost certainly have higher communications latency than a wired Internet connection; this is important if you are expecting instant (below 1 second) response times. If your mobile device application is going to use mobile telephone network communications, it is important to be able to respond robustly to lower network data rates and higher latency. A reasonable rule of thumb to consider in your designs is "when downloading data larger than 20KB, it is appropriate to keep track of the amount of time the download is taking and to consider aborting the operation if the download will take an unreasonably long time." The actual size threshold and maximum wait time are of course determined by the nature of the application, the communications networks being used, and the end user's expectations. The mobile application's end user should not be left waiting an indefinite amount of time for data to arrive even if the data is being downloaded on a background thread; measure the download rate in progress and set the user's expectations appropriately.

Understand the monetary cost of communications.
Although some older (mostly 2G) data connections mechanisms charged by the time duration of a connection, most mobile telephone network data services charge based on the total number of bits transferred. Rates may vary significantly between home networks and roaming networks. All of this will have a direct effect on the cost to the user of using your mobile device application to communicate. There are no definitive rules about what cost of communication is appropriate or inappropriate; this will depend on the nature of your application. When choosing a mobile communications technology, it is worth measuring your upload and download sizes and comparing estimated prices using different models of communication.

Mobile Phone Network, Wi-Fi, or Both?


Increasingly, rich mobile phone devices are coming with Wi-Fi support either built in or available via a plug-in card; Compact Flash and Secure Digital Wi-Fi cards are two of the most popular formats. Alternatively, laptops and specialized mobile computing devices that have Wi-Fi support built in often have the ability of adding mobile telephone network access via plug-in cards.

Given that added features mean added price and power consumption, does it make sense to have a mobile device that communicates over mobile telephone and Wi-Fi networks? The answer is, "It depends on the application," which is another way of saying, "It depends on your design."

For many applications, it should be a design goal to work well when deployed to devices using either Wi-Fi or mobile telephone networks. Generally speaking, the more popular and useful an application, the more likely that users will want to run it on different kinds of network hardware. Users will want to take advantage of high bandwidth where it's available, but still need to use the applications acceptably on slower networks. As long as your application is using high-level networking technologies such as sockets or HTTP, this should not be a technical problem because both of these levels of communication abstract the underlying network protocols.

When working with different mobile telephone or Wi-Fi networks, it is important for your mobile application to be aware of the measured (not theoretical) throughput that the communications channel is providing. It is one thing to "work fine as long as the user has an infinite amount of time to wait" and quite another thing to "always provide the user an acceptable experience." If your mobile application is going to be run on devices that support both Wi-Fi and mobile telephone network communications, you may want to allow the application to run in two different modes, a low-bandwidth and high-bandwidth mode. The low-bandwidth mode should transfer only essential data and cache the rest of the data until a high-bandwidth connection can be established.

Consider the example of a traffic-accident investigator. Suppose that our investigator spends his or her days traveling to accident scenes generating accident reports and taking digital photographs as evidence. It is important that an accident be reported as quickly as possible; all parties to the accident have insurance claims that need to be filed, medical processes may need to be initiated, cars may need to be towed to various locations, and so on. For all of these reasons, a quickly submitted accident report is essential. Of longer-term importance is the evidence relating to the accident; for this, detailed photographs are invaluable. An application integrated into the mobile telephone the investigator carries with him could be of great use in making this process more efficient. Upon arriving on the scene of an accident, the investigator initiates a new accident report on a mobile device. The mobile device application enables the investigator to input the essential information about the accident, such as the license plate numbers of the cars involved, the driver's licenses of the drivers, passenger contact information, and an initial assessment of the accident. As soon as this information is ready, it can immediately be uploaded to a server using a mobile telephone connection. Because the information is mostly text and the size is relatively small, the upload process is quick and easily accomplished over a mobile telephone network. With this information entered into the system, the process of helping the parties involved recover can immediately begin; everyone benefits. Our accident investigator can now get down to the detailed work: taking detailed photographs, recording voice notes, and gathering additional information. Some of this information can be uploaded immediately if it is of use, but the bulk of the information can be cached on the device, saving the investigator from a time-consuming and expensive upload. Later, when our investigator returns to his or her office or goes to a location that offers Wi-Fi access, the investigator's mobile application can upload the digital photographs, recorded voice notes, and other large-size data.

It is important not to overdesign a network access model by trying to outguess the mobile application's user. It may be possible to gather a great deal of information about available networks and automatically perform smart high-bandwidth and low-bandwidth communications on behalf of the mobile application's user; alternatively, it may not. Trying to automate net work access decisions is a good thing, but not at the expense of offering the user the final choice. In the end, it is the end users who will need to use your mobile application in the field and they will be the best people to make the appropriate communications decisions. Your application should supply them with the right kind of information and empower them to make the communications decisions that make sense for them. Allowing the user to set communications preferences, enabling the user to attempt communications on demand, and allowing them to defer operations that are not meeting their expectations are good ways to do this. A proper balance must be struck between giving users too little control and giving them an overly complex array of options. Some guidelines include the following:

Allow the user to set basic communications preferences.
When possible, your mobile application should have a scalable set of information transfer options that allow the application's users to tune the application based on network bandwidth and their own needs. Allowing users to scale the number of database records for download (for example, small, medium, full) or allowing the users the option to download only text information and defer the download of related image data are two examples of user-settable preferences.

Give the user the ability to attempt communications"on demand."
Often the mobile application's end user will be in the best position to make connectivity decisions. For example, if Wi-Fi or mobile telephone network connectivity is required, a mobile device user can walk to a physical location that offers this connectivity. After the user has entered a space where she knows that the needed connectivity is available, she should immediately be able to command the mobile application to attempt synchronization. Putting the end user in the driver's seat is very empowering.

Allow users to defer operations that do not meet their expectations.
Try as you might, it is nearly impossible to predict and respond robustly to all communications challenges. A network may be congested and offer lower throughput, proxy servers may be having problems, or any number of other communications problems could occur that prevent your mobile application from meeting its user's expectations. You should write robust code to deal with these situations. Just as importantly, you should enable end users to take charge of the situation and command the application to stop trying to communicate and to defer operations until later. Your mobile application must provide the necessary information to enable users to make intelligent communications decisions, and then it must respond to the users' wants. Listing the number of attempts or the "% complete" of a communication operation and enabling users to cancel or defer the operation if it is not progressing at the rate they need are examples of empowering users to make these kinds of intelligent decisions.


Figure 15.3 shows a schematic example of mobile communications occurring using both mobile telephone network and Wi-Fi communications. As can be seen in the diagram, mobile telephone networks offer wide areas of coverage with relatively few "dead spots" where communication is not possible. In contrast, Wi-Fi networks have much lower area coverage but offer high-bandwidth data-transfer opportunities. Mobile device users can use the mobile telephone network to perform frequent small-sized data transfers as needed in the field, but can queue up larger transfers until they get to a high-bandwidth Wi-Fi hot spot.

Figure 15.3. The nomadic wanderings of a mobile phone and Wi-Fi user. Mobile phone network data connections offer broad coverage but usually at lower data rates than Wi-Fi connections. When the user is roaming in a wide area, the mobile network offers near-continual connectivity to server data. The user may choose to specifically go to a Wi-Fi network hot spot when large data transfers are required. In addition, Wi-Fi may be available in some "dead spots" (for example, underground) where broad mobile phone networks are not available.

[View full size image]

Cradle / PC Cable


Cradle-based communication is data transfer that occurs directly to or through an intermediary computer when the device is hooked up to that computer using a physical cable. Instead of having a direct network connection, the mobile device communicates to a desktop or laptop computer. The device either synchronizes data with the computer or uses it as its means to gain access to the network. Note: For network access through a host computer, the synchronization software must support this feature; for instance, starting with the Pocket PC 2002, versions of Microsoft's ActiveSync software support the ability for a device to tunnel through a desktop to get to the Internet. Different device technologies will have different software to enable this kind of "pass-through" support.

The benefit of cradle-based communication is its relative simplicity. Existing owners of rich mobile devices often have all the software and cables needed to make things work and the owners of these computers usually have their computers already hooked up to the Internet. Cradle-based communication is particularly useful for prototyping, testing, and debugging purposes because it allows easy access to networked resources in a controlled environment. Cradle-based communication is also inexpensive because it does not rely on any network access infrastructure that is not already present for laptops or desktops.

The major shortcoming of cradle-based communication is that it tethers a device to computers that support the required synchronization software. A mobile device solution that relies on a specific set of host computers to allow data transfer will not be able to access data "any time, anywhere." However, if the mobile solution you are developing does not require instantaneous access to networks, but instead only requires periodic synchronization of data that can be done through a PC's network connection, the PC-tethered communication model can be a good choice. As with Wi-Fi access, it is possible to use cradle-based communication to complement other communications mechanisms; for example, relatively small amounts of data can be sent and received in the field using mobile telephone networks while larger data items are left cached on the device for later synchronization via a PC connection.

Network Cable


Using Ethernet cable-based communications for mobile devices is very similar to Wi-Fi-based communication. Although mostly the same, the two models differ in the following ways:

Network cables are more location dependent than Wi-Fi.
A Wi-Fi base station has a communications diameter of a few hundred feet, which is significantly longer than most cables; in this sense, Wi-Fi is more mobile than network cable. As a practical matter, if flexible network access is required throughout a relatively bounded space such as the interior of a building, Wi-Fi is often less expensive than wiring the whole area with cables. However, anywhere you can reach a network cable is network accessible; in areas where a Wi-Fi signal cannot easily reach, a physical cable may be the only option for connectivity.

Network cables offer some security advantages over Wi-Fi.
Although Wi-Fi networks can be configured to communicate using encrypted channels, they are still broadcasting over the air. A wired scenario offers protection against others eavesdropping on the radio signals; this protection is not bulletproof, but it is one level of increased security. Note: If you are connecting to or through a public network, this increased security is minimal; you will need to rely on encrypted communications to meet your security needs. (This is a good idea in any case.)

Extra hardware will probably be required.
Although most of today's laptops have both wired and wireless networking capabilities built in, this is not true for most mobile devices. Due to added size, power consumption, and manufacturing cost, this is likely to remain the case. An external network card (usually Compact Flash or Secure Digital) will often be required to support network cable-based communication.


As with cradle-based communication, a physical network cable connection can prove very useful when prototyping and debugging mobile device solutions. However, it is important to realize that connectivity speeds and reliability characteristics will be much lower for many wireless communication mechanisms; although wired network connections are a useful tool, they are not sufficient to develop and test an application that will be run on wireless networks.

IrDA


At low levels of abstraction, IrDA (Infrared Data Association) is simply serial-based communication over an infrared channel; with higher-level programming models, it is significantly more than this. A sophisticated multichannel programming model has been built on top of IrDA, and it can be an excellent and flexible communications choice (see [www.irda.org] for full details).

IrDA is a useful technology for device peer-to-peer communications because it is inexpensive and nearly ubiquitous. Because IrDA technology does not cost much to manufacture, is small, and does not consume a lot of power, it is integrated into many mobile devices, including Pocket PCs and Smartphones. To communicate, two devices are physically lined up to one another and then a conversation is initiated.

For mobile application development, IrDA is of interest for two reasons: First, like Bluetooth, IrDA can be used to enable a device to communicate with external networks through another device; for example, my PDA can use my mobile phone to make a data connection; this tunnel-through communications capability is somewhat limited by the need to physically keep the devices lined up for the duration of the communication, a limitation Bluetooth does not have. Second, and perhaps more interestingly, IrDA can be used to share information between two different devices; the classic example of this is "beaming" or "squirting" an address book entry from one mobile device to another. Because the bandwidth of IrDA is reasonable, a fair amount of information can be transferred by "squirting" it from one device to another.

Point-to-Point Networking with IrDA


Before "peer-to-peer" networking, there came "point-to-point" networking, and for this IrDA is king. IrDA-based communication offers an easy and relatively high-bandwidth mechanism for exchanging data between adjacent devices. Although lacking some of the "luster of the new" that personal area networking technology such as Bluetooth has, it has the virtue of being tried, tested, and easy to work with. If your users do not mind pointing two devices at one another, IrDA may well be the right peer-to-peer technology for your mobile application's needs.

IrDA is a mature technology that often goes unnoticed and is underutilized by application developers. I believe this is due to a lack of awareness of how easy to use and flexible IrDA actually is. In the .NET Compact Framework, IrDA programming is exposed via a sockets interface very similar to the sockets interface used for TCP/IP (Internet) communication. The principal difference between using sockets for Internet communication and sockets for IrDA communication is the concept of a "named port."

When using TCP/IP and sockets, each machine has its own IP address (for example, 200.198.126.81) and a list of potential numbered ports it can use for communications. Servers open up the ports they want to listen for request on. A client device can then request a conversation with a server by specifying both the machine's IP address and the port it wants to connect to. With IrDA point-to-point communication, one device's IrDA port is lined up with another device's, so no addressing scheme is needed to locate a server. If an application wants to expose an IrDA socket interface to transmit its owner's contact information, it might open an IrDA socket it names OwnerContactInfo. Similarly, a photo album application that wants to allow other devices to download photos from it may open an IrDA socket called PhotoDownloadService. Client applications on other devices that want to connect to these services ask for them by name.

A conversation between a Web browser and server goes something like this:

Server:
Opens port 80 for listening for incoming requests.

Browser:
"Hello server number '200.198.126.81,' can I have a connection to Port 80?"

Server:
"Yes you can, here is a port connection for you to use for communications."

Browser:
Takes the connection it has been given and starts a conversation on it that results in the downloading of several files.

A similar conversation using sockets over IrDA would go as follows:

Receiving device:
Creates a named port ReceiveAppXYZData.

Sending device:
"Hello, I would like to make a connection to a device listening on port ReceiveAppXYZData."

Receiving device:
"Yes, I am listening on that port. Let's make a connection."

Sending device:
Takes the connection it has been given and starts a conversation on it that results in the sending of data.

When two devices are in physical proximity, socket-based IrDA communication is a simple and effective way to exchange information.

IrDA Sockets and the .NET Compact Framework


As noted previously, the .NET Compact Framework offers a socket interface for working with IrDA. If you are familiar with using sockets for Internet (TCP/IP) communications, there are only a few small differences you need to understand to make use of sockets over IrDA. The sample code shows how to use IrDA Sockets to communicate between two devices.


Presently .NET Sockets Support for IrDA Is Only Available in the .NET Compact Framework; It Is Not Available on the Desktop .NET Framework


IrDA support is built in to version 1.1 of the .NET Compact Framework, but is not available in version 1.1 of the desktop .NET Framework. This is a case where the .NET Compact Framework led the way in introducing a technology interesting to mobile devices. Future versions of the desktop .NET Framework may support IrDA sockets programming, but until then if you want to communicate between desktop computers and the .NET Compact Framework you will need to call into native code on the desktop to access IrDA functionality. On the positive side, the desktop native code should not be too complicated because the Windows native code sockets APIs support using IrDA; the C/C++ code should look relatively similar to the C# or VB.NET code you use on the device. For more information, look in the Windows Platform SDK under the topics "IrDA Programming with Windows sockets" and "IrDA and Windows sockets reference."

The code in Listings 15.3, 15.4, and 15.5 show how to transmit the contents of a file from one device onto another using IrDA. Do the following to build and run the application:


1.

Start Visual Studio .NET (2003 or later) and create a C# Smart Device Application.

2.

Choose Pocket PC as the target platform. (A project will be created for you and Pocket PC Form designer will appear.)

3.

Add a project reference to System.Net.IrDA. The System.Net.IrDA.DLL component is not referenced by projects by default, so a reference must explicitly be added so that this namespace is available to your application. Note: System.Net.IrDA.DLL is a core part of the .NET Compact Framework and is installed on any device that has the .NET Compact Framework present. It just happens not to be referenced by default in Visual Studio .NET device projects.

4.

Add the following controls to the form:

A button; rename it buttonTestFileSend.

A button; rename it buttonTestFileReceive.

5.

For each of the Button controls above, double-click the button in the Form designer. In the event handler function generated, enter the button<ButtonName>_Click in Listing 15.3. Note: Be sure also to include any code in Listing 15.3 that is outside the two function definitions.

6.

Set the MinimizeBox property of the form to false. At runtime this will give the form an OK box at the top right that makes it easy to close the form and exit the application; this is very useful for repeated testing.

7.

Add a new class to your project, name it IrDAFileSend, and enter the code in Listing 15.4 into the class.

8.

Add a new class to your project, name it IrDAFileReceive, and enter the code in Listing 15.5 into the class.

9.

Deploy and run the application to two different Pocket PCs (or smart phones).

10.

On the first Pocket PC, press the buttonTestFileReceive button. You should see the application's window caption display text indicating that it is waiting for an incoming file.

11.

On the second Pocket PC, press the buttonTestFileSend button. You should see the application's window caption display text indicating that it is waiting for a device to send the file to.

12.

Point the two devices' IrDA ports at one another. The file should get transferred from one device to the other and message boxes should pop up on both devices indicating the transmission was successful.


Result: A file from the second Pocket PC should be transmitted to the first Pocket PC. You can verify this by starting the Pocket PC File Explorer, going to the My Device root directory, and clicking the file myTestReceiveFile; this will open the file up in PocketWord and show the contents of the file.

After you have successfully tested the application synchronously, try to call the IrDA send and receive functions asynchronously. You will need to write code on both devices for your user interface thread to periodically poll the state of the IrDAFileSend or IrDAFileReceive classes to see whether it has completed.


Presently .NET Compact Framework IrDA Sockets Code Will Run on Physical Devices That Have IrDA Hardware Such as Pocket PCs and Smart Phones, but the Code Will Not Run Properly in the Emulator


If you try to create or connect to an IrDA socket with code running in a Pocket PC, Smartphone, or Windows CE emulator, your application will probably encounter a runtime exception. This means that unlike most other .NET Compact Framework features your IrDA code will need to be designed and tested using a real physical device. Although this is not a blocking difficulty, it does mean that the design and testing process will be a bit more complex because to test IrDA code you will need two physical devices running the .NET Compact Framework, one to act as the IrDA server and one to act as the client. Because of this added complexity, it is recommended to write and test your IrDA communications code separately from the rest of your application using the simplest possible application model to work out the kinks in the communication. After you have all the kinks worked out of your IrDA code, you can then bring it into your larger application.

Listing 15.3. Test Code to go Inside a Form Class to Test IrDA Transmit and Receive



//The name we want to give to our IrDA socket
const string myIrDASocketName = "IrDaTestFileTransmit";
private void buttonTestFileSend_Click(object sender,
System.EventArgs e)
{
//Create a simple text file we want to send
const string fileName = "\\myTestSendFile.txt";
System.IO.StreamWriter textFileStream;
textFileStream = System.IO.File.CreateText(fileName);
textFileStream.WriteLine("Today...");
textFileStream.WriteLine("is a nice day");
textFileStream.WriteLine("to go swim");
textFileStream.WriteLine("in the lake");
textFileStream.Close();
IrDAFileSend irdaFileSend;
irdaFileSend = new IrDAFileSend(fileName, myIrDASocketName);
//We have 2 options: 1 - Sync, 2 - Async
//1. Call the function synchronously
//and block the thread until the
//file is sent
//1a. Let the user know we're waiting to send
this.Text = "Trying to send...";
//1b. Wait until we find a client and then send the file
irdaFileSend.LoopAndAttemptIRSend();
//1c. Let the user the file has been transmitted
System.Windows.Forms.MessageBox.Show("File sent!");
this.Text = "IrDA: Sent!";
//2. Call the function async and set
//up a background thread to do the sending
//irdaFileSend.LoopAndAttemptIRSendAsync();
//NOTE: If we call the function async, we want to
//occasionally check if it is finished by
//calling 'irdaFileSend.Status'
}
private void buttonTestFileReceive_Click(object sender,
System.EventArgs e)
{
//If our destination file exists, delete it
const string fileName = "\\myTestReceiveFile.txt";
if (System.IO.File.Exists(fileName))
{
System.IO.File.Delete(fileName);
}
IrDAFileReceive irdaFileReceive;
irdaFileReceive = new IrDAFileReceive(fileName,
myIrDASocketName);
//We have 2 options: 1 - Sync, 2 - Async
//1. Call the function synchronously
//and block the thread until the
//file is received
//1a. Let the user know we're waiting to receive
this.Text = "Waiting to receive...";
//1b. Wait until someone contacts us and sends the file
irdaFileReceive.WaitForIRFileDownload();
//1c. Let the user know we've got the sent file
this.Text = "IrDA: received!";
System.Windows.Forms.MessageBox.Show("File received!");
//2. Call the function async and set
//up a background thread to do the receive
//irdaFileReceive.WaitForIRFileDownloadAsync();
//NOTE: If we call the function async, we want to
//occasionally check if it is finished by
//calling 'irdaFileReceive.Status'
}

Listing 15.4. IrDAFileSend class



//=============================================================
//This class is an IrDA client. It looks for an IrDA
//server with a matching IrDA service name and when found
//it streams the data of a file to it.
//=============================================================
class IrDAFileSend
{
private string m_descriptionOfLastSendAttempt;
private string m_IrDAServiceName;
private string m_fileToSend;
private bool m_wasSenderStopped;
public enum SendStatus
{
AttemptingToSend,
Finished_Successfully,
Finished_Aborted,
Finished_Error
}
private SendStatus m_SendStatus;
public SendStatus Status
{
get
{
//Lock prevents concurrent read/write to m_SendStatus
lock(this) {return m_SendStatus;}
}
}
private void setStatus(SendStatus newStatus)
{
//Lock prevents concurrent read/write to m_SendStatus
lock(this) {m_SendStatus = newStatus;}
}
public string ErrorText
{
get {return m_descriptionOfLastSendAttempt;}
}
//------------------------------------------------------------
//CONSTRUCTOR
//------------------------------------------------------------
public IrDAFileSend(string fileToSend, string irdaServiceName)
{
//The name of the IrDA socket we want to look for
m_IrDAServiceName = irdaServiceName;
//The file we want to send
m_fileToSend = fileToSend;
}
//-------------------------------------------------------------
//Starts a new thread to try to send the file
//-------------------------------------------------------------
public void LoopAndAttemptIRSendAsync()
{
//We are in send mode
setStatus(SendStatus.AttemptingToSend);
//User has not aborted us yet
m_wasSenderStopped = false;
//This is the function we want the new thread to start running
System.Threading.ThreadStart threadEntryPoint;
threadEntryPoint =
new System.Threading.ThreadStart(LoopAndAttemptIRSend);
//--------------------------------------------
//Create a new thread and start it running
//--------------------------------------------
System.Threading.Thread newThread =
new System.Threading.Thread(threadEntryPoint);
newThread.Start(); //Go!
}
//-------------------------------------------------------------
//Goes in loops and tries to send the file via IR
//-------------------------------------------------------------
public void LoopAndAttemptIRSend()
{
System.Net.Sockets.IrDAClient irDASender;
System.IO.Stream streamOutToIrDA ;
System.IO.Stream streamInFromFile;
//User has not aborted us yet
m_wasSenderStopped = false;
setStatus(SendStatus.AttemptingToSend);
//------------------------------------------------------------
//Continually loop and try to send the message until
//------------------------------------------------------------
while(true)
{
//These should all be null going in and out of the
//'sendStream(...)' call unless an exception is thrown!
irDASender = null;
streamOutToIrDA = null;
streamInFromFile = null;
//Attempt to send the stream
bool bSuccess;
try
{
bSuccess = sendStream(
out m_descriptionOfLastSendAttempt,
ref streamOutToIrDA,
ref irDASender,
ref streamInFromFile
);
}
catch(System.Exception eUnexpected) //Unexpected error!!!
{
setStatus(SendStatus.Finished_Error); //Note the failure
m_descriptionOfLastSendAttempt =
"Unexpected error in IR send loop. " +
eUnexpected.Message;
//---------------------------------------------------
//Clean up any resources we may have allocated
//---------------------------------------------------
if(streamOutToIrDA != null)
{
try {streamOutToIrDA.Close();}
catch{};//Swallow any error
streamOutToIrDA = null;
}
if(streamInFromFile != null)
{
try {streamInFromFile.Close();}
catch{};//Swallow any error
streamInFromFile = null;
}
if (irDASender != null)
{
try {irDASender.Close();}
catch{}; //Swallow any error
irDASender = null;
}
return; //Exit
}
//See if we succeeded
if (bSuccess == true)
{
m_descriptionOfLastSendAttempt = "Success!";
setStatus(SendStatus.Finished_Successfully);
return;
}
//See if there was a user driven abort
if (m_wasSenderStopped == true)
{
m_descriptionOfLastSendAttempt = "User Aborted.";
setStatus(SendStatus.Finished_Aborted);
return;
}
//Otherwise...We have not found an IrDA server with a
//matching service name yet. We will loop and keep
//looking for one.
}
//We will never hit this point in execution
}
//------------------------------------------------------------
//Attempt to send an I/O stream (for example, a file) over IR
//[ret]:
// true: We sent the file successfully
// false: The file was not sent successfully
//------------------------------------------------------------
private bool sendStream(out string errorDescription,
ref System.IO.Stream streamOutToIrDA,
ref System.Net.Sockets.IrDAClient irDASender,
ref System.IO.Stream streamInFromFile
)
{
errorDescription = ";
//----------------------------------------------------------
//Create a new IRDA client
//----------------------------------------------------------
try
{
//--------------------------------------------------------
//This will return pretty quickly. It will peek out there
//and will return if no one is listening.
//--------------------------------------------------------
irDASender =
new System.Net.Sockets.IrDAClient(m_IrDAServiceName);
}
catch (System.Exception eCreateClient)
{
//A number of things could have happened here
//#1: No devices may be listening
//#2: A device may be listening, but may not care
// (may refuse our conversation)
errorDescription = eCreateClient.Message;
return false;
}
//At this point a number of things could happen:
//#1: We have gotten a connection from an IR receiving device
//#2: The IR request has been canceled (someone called STOP).
if (m_wasSenderStopped == true)
{
irDASender.Close();
irDASender = null;
return false;
}
//==========================================
//SEND THE DATA!
//==========================================
//Open the file we want to send
streamInFromFile = System.IO.File.OpenRead(m_fileToSend);
//Open the IrDA socket we want to sent out to
streamOutToIrDA = irDASender.GetStream();
const int BUFFER_SIZE = 1024;
byte[] inBuffer = new byte[BUFFER_SIZE];
int bytesRead;
int iTestAll = 0;
int iTestWrite = 0;
do
{
//Read the bytes in from the file
bytesRead = streamInFromFile.Read(inBuffer, 0, BUFFER_SIZE);
iTestAll = iTestAll + 1;
//Write the bytes out to our output stream
if (bytesRead > 0)
{
streamOutToIrDA.Write(inBuffer, 0, bytesRead);
iTestWrite = iTestWrite + 1;
}
}while(bytesRead > 0);
//Clean up output stream
streamOutToIrDA.Flush(); //Finish writing any output
streamOutToIrDA.Close(); //Close the stream
streamOutToIrDA = null;
//Clean up local file
streamInFromFile.Close();
streamOutToIrDA = null;
//Clean up IrDA port
irDASender.Close();
irDASender = null;
//Success!!!
return true;
}
} //end class

Listing 15.5. IrDAFileReceive Class



//---------------------------------------------------------
//Allows the reception of a file over IrDA (infrared port)
//
//This class is NOT re-entrant and should not be called by more
//than one caller at a time. If multiple simultaneous IR
//sessions are desired, they should be done by creating
//different instances of this class.
//---------------------------------------------------------
public class IrDAFileReceive
{
private bool m_wasListenerStopped;
private string m_IrDAServiceName;
private string m_fileNameForDownload;
private string m_errorDuringTransfer;
private System.Net.Sockets.IrDAListener m_irListener;
private ReceiveStatus m_ReceiveStatus;
public string ErrorText
{get {return m_errorDuringTransfer;}}
//--------------------------------------------------------------
//This notes the status of the receive
//--------------------------------------------------------------
public enum ReceiveStatus
{
NotDone_SettingUp,
NotDone_WaitingForSender,
NotDone_Receiving,
Done_Success,
Done_Aborted,
Done_ErrorOccured
}
//---------------------------------------------------------
// Returns the state of transfer
//---------------------------------------------------------
public ReceiveStatus Status
{
get
{
//Thread safety to avoid read and write at same time
lock(this)
{
return m_ReceiveStatus;
} //end lock
} //end get
} //end property
private void setStatus(ReceiveStatus newStatus)
{
//Thread safety to avoid read and write at same time
lock(this)
{
m_ReceiveStatus = newStatus;
} //end lock
}
//-------------------------------------------------------------
// [in] filename: Filename we want to the IR file into
//-------------------------------------------------------------
public IrDAFileReceive(string filename, string irdaServiceName)
{
//The name of the IrDA socket we want to open
m_IrDAServiceName = irdaServiceName;
//The filename we want to save the received data to
m_fileNameForDownload = filename;
}
//-----------------------------------------------------------
//Allows you to receive a file asynchronously over IR
//
// [in] filename: Filename to write to
//-----------------------------------------------------------
public void WaitForIRFileDownloadAsync()
{
//Note that we are now in setup mode
setStatus(ReceiveStatus.NotDone_SettingUp);
//-----------------------------------------------------------
//Create a new thread
//-----------------------------------------------------------
System.Threading.ThreadStart threadEntryPoint;
threadEntryPoint =
new System.Threading.ThreadStart(WaitForIRFileDownload);
System.Threading.Thread newThread =
new System.Threading.Thread(threadEntryPoint);
//Start the thread running
newThread.Start();
}
//-----------------------------------------------------------
//Opens up an IR port and waits to download a file
//-----------------------------------------------------------
public void WaitForIRFileDownload()
{
System.IO.Stream outputStream = null;
System.Net.Sockets.IrDAClient irdaClient = null;
System.IO.Stream irStreamIn = null;
try
{
//=========================================================
//Setup and download the file!
//=========================================================
internal_WaitForIRFileDownload(ref outputStream, ref irdaClient,
ref irStreamIn);
}
catch //Swallow any errors that occurred
{
setStatus(ReceiveStatus.Done_ErrorOccured);
}
//=============================================
//Cleanup all resources
//=============================================
//Close our input stream
if(irStreamIn != null)
{
try {irStreamIn.Close();}
catch {} //Swallow any errors that occured
}
//Close the IrDA client
if(irdaClient != null)
{
try {irdaClient.Close();}
catch {} //Swallow any errors that occured
}
//Close the file we have been writing to
if(outputStream != null)
{
try {outputStream.Close();}
catch {} //Swallow any errors that occured
}
//Close the listener if it's running
if (m_irListener != null)
{
//Set first so code running on another thread will
//abort if it is set
m_wasListenerStopped = true;
try {m_irListener.Stop();} catch{} //Swallow any errors
m_irListener = null;
}
}
private void internal_WaitForIRFileDownload(
ref System.IO.Stream outputStream,
ref System.Net.Sockets.IrDAClient irdaClient,
ref System.IO.Stream irStreamIn
)
{
//----------------------------------------------------------
//Open an input file to stream into
//----------------------------------------------------------
outputStream = System.IO.File.Open(
m_fileNameForDownload,
System.IO.FileMode.Create);
//==========================================
//STATUS UPDATE
//==========================================
setStatus(ReceiveStatus.NotDone_WaitingForSender);
//-------------------------------------------------------------
//Open a listener
//-------------------------------------------------------------
try
{
m_wasListenerStopped = false;
m_irListener =
new System.Net.Sockets.IrDAListener(m_IrDAServiceName);
m_irListener.Start();
}
catch(System.Exception eListener)
{
m_errorDuringTransfer = "Error creating listener - " +
eListener.Message;
goto exit_sub_with_error;
}
//See if we got aborted
if (m_wasListenerStopped == true)
{ goto exit_sub_with_abort; }
//---------------------------------------------------------
//Accept a connection
//---------------------------------------------------------
try
{
//---------------------------------------------------------
//Execution will stop here until we get pinged by a device
//or the listener was halted on another thread
//---------------------------------------------------------
irdaClient = m_irListener.AcceptIrDAClient();
}
catch(System.Exception eClientAccept)
{
//If the listening is stopped by another thread calling cancel,
// an exception will be thrown and we will be here.
if (m_wasListenerStopped == true)
{goto exit_sub_with_abort; }
//If it was not a matter of the listening service being
//stopped, some other exception has occurred. Deal with it.
m_errorDuringTransfer = "Error accepting connection - " +
eClientAccept.Message;
goto exit_sub_with_error;
}
//At this point we will be in 1 of 2 states, ether:
//#1: We have gotten a connection from an IR sending device
//#2: The IR request has been canceled (by someone calling STOP)
// (in which the code below will throw an exception)
//See if we got aborted
if (m_wasListenerStopped == true)
{goto exit_sub_with_abort;}
//==========================================
//STATUS UPDATE
//==========================================
setStatus(ReceiveStatus.NotDone_Receiving);
//--------------------------------------------------------------
//Open a receiving stream
//--------------------------------------------------------------
try
{
irStreamIn = irdaClient.GetStream();
}
catch(System.Exception exGetInputStream)
{
m_errorDuringTransfer = "Error getting input stream - " +
exGetInputStream.Message;
goto exit_sub_with_error;
}
//Get ready to receive the data!
const int BUFFER_SIZE = 1024;
byte[] inBuffer = new byte[BUFFER_SIZE];
int bytesRead = 0;
do
{
//Read the bytes in from the IR port
bytesRead = irStreamIn.Read(inBuffer, 0, BUFFER_SIZE);
//Write the bytes out to our output stream
if (bytesRead > 0)
{outputStream.Write(inBuffer, 0, bytesRead);}
}while (bytesRead > 0);
outputStream.Flush(); //Finish writing any output
//==========================================
//STATUS UPDATE: SUCCESS
//==========================================
setStatus(ReceiveStatus.Done_Success);
return; //No errors
//==========================================
//FAILURE...
//==========================================
exit_sub_with_abort:
//STATUS UPDATE: Aborted (but no error)
setStatus(ReceiveStatus.Done_Aborted);
return;
exit_sub_with_error:
//STATUS UPDATE: ERROR!!!!
setStatus(ReceiveStatus.Done_ErrorOccured);
}
} //end class

Memory Cards


Before the advent of inexpensive and widely deployed networking technology, there was the concept of the "sneaker net." This literally meant walking the data from one computer to another with the data stored on a physical transferable medium such as a magnetic disk; people were the network transport and the physical media the packets. With all of the remarkable networking technology available today, it is easy to forget how useful physically movable storage is. Often the fastest practical way to move large amounts of data from one computer or mobile device to another is just to place it onto a storage card and physically transfer it between the devices.

Today removable memory cards come with staggeringly large capacities; 256MB of storage is common, 512MB is not uncommon, and 1GB storage cards are already available at reasonable prices. Storage capacity keeps growing exponentially. These cards come in a variety of form factors, including USB memory keys, Compact Flash cards that can plug easily into laptop PCMICA slots using an inexpensive pass-through sleeve, and Secure Digital cards. Most of these storage elements simply appear as a removable hard drive when inserted into a mobile device or computer.

There is a great deal of merit in a "sneaker net" approach when large amounts of data need to be transferred. On-device databases such as SQL CE can be stored on memory cards and prepopulated with large amounts of data along with any other data required such as directories full of images. Storage cards can be loaded with data on one machine and have data unloaded from them as needed by mobile devices; thus the data's server and the data's client do not need to be online at the same time. As a communications mechanism, think of storage cards as a batch processing solution; they provide the ability to move a large amount of data in bulk but do not offer a live connection to new data on the network. A useful model is to use storage cards to move lots of data initially without requiring prolonged network access and then subsequently use online communications to perform incremental updates to that data. Storage cards are a relatively simple and "low-tech" communications mechanism but they should not be overlooked because of this.


/ 159