Channels ▼
RSS

Mobile

Smart clients know their limitations

Source Code Accompanies This Article. Download It Now.


Hari is a technical architect for Infosys Technologies Limited. He can be contacted at harigopal_ponnapalli@infosys.com.


Smart clients that work offline when in disconnected mode, but seamlessly synchronize with the enterprise back end when connected, are gaining in popularity. The challenges in making this possible, however, involve issues such as constrained memory, limited battery power, and intermittent network connectivity. Consequently, designing smart clients for mobile devices that can dynamically and intelligently adapt their behavior based on the changing status of the constrained resources is critical to success. For example, a well-designed smart client should sense the network connectivity status and adapt its behavior accordingly, either by connecting to a network resource or a local resource hosted on the device. Similarly, a smart client should monitor available memory on the device, initiate a synchronization session with a back-end data store, and free device memory under low-memory availability. Likewise, on sensing short battery life, smart clients should disable some of their power-draining features, such as network connectivity.

Displaying intelligence such as this requires that smart clients be aware of the changing context (status) of the device's available resources. The direct way of embedding this intelligence into clients involves using underlying API calls, either constantly or periodically. However, a more elegant way involves notifying clients regularly about the dynamic resource context via asynchronous callback mechanisms. An asynchronous notification mechanism such as this helps you write code for listeners at a single place that handles the changing resource context, making the design more clean and maintainable.

In this article, I present ResourceMonitor, a resource status monitoring component for the .NET Compact Framework, and show how you can use it to develop resource-aware, smart-client applications for Pocket PC devices.

Component Requirements and Design

Windows CE provides unmanaged, low-level APIs to get the device memory, power, and network connectivity status. There is no direct managed .NET Compact Framework API available for this functionality, and you are required to use the limited P/Invoke capabilities of the .NET Compact Framework to call the underlying native APIs from managed code. In addition to presenting an asynchronous callback mechanism, ResourceMonitor provides a managed API to determine the status of device resources.

Windows CE supports several notifications for changing application resource status. To the best of my knowledge, however, the thresholds for deciding the changing status are predetermined by Windows CE, and you cannot define/control what is low battery or low memory for specific applications. ResourceMonitor is designed to give you this flexibility.

To make ResourceMonitor flexible, configurable, and powerful, I had several requirements:

  • ResourceMonitor should be developed as a managed .NET Compact Framework class library. Application developers using ResourceMonitor should be shielded from learning the nuances of calling native API features using P/Invoke.
  • ResourceMonitor should monitor and notify the status of network connectivity, battery power, and device memory.
  • ResourceMonitor should support an asynchronous callback mechanism that notifies the client of the changing status of the resources.
  • Application developers should be able to configure, both statically and dynamically, the resources to be monitored by ResourceMonitor. For example, in a specific case, you can choose to monitor only network connectivity initially, and later update ResourceMonitor dynamically to monitor memory and battery also.
  • Application developers should be able to configure the frequency of the notifications. However, the callback events will be raised only when there is a change in the resource status.
  • ResourceMonitor should provide the facility to dynamically start and stop the notifications.

In ResourceMonitor, the CMemoryInfo, CBatteryInfo, and CNetworkInfo types provide abstractions to Memory, Battery, and Network resources, respectively, and can be used independently to determine the resource status. ICommonEvents is the interface that declares all callback events supported by ResourceMonitor. CResourceMonitor is the main class that initiates a background thread, which monitors the status of the configured resources at the configured frequency. Smart clients interested in receiving resource notifications must implement this interface and register that object with CResourceMonitor.

Monitoring Battery Power

For the most part, mobile devices are battery-powered devices with limited battery life. Typical battery life ranges from a few hours to a few days. Computationally intensive tasks such as network access, looping conditions, and the like, consume more power. Consequently, we design smart clients that adapt our behavior, based on device power status. Windows CE provides native API function calls to determine the device power status—GetSystemPowerStatusEx and GetSystemPowerStatusEx2. Each function fills a structure SYSTEM_POWER_STATUS_EX and SYSTEM_POWER_STATUS_EX2, respectively, supplied to them. ResourceMonitor uses SYSTEM_POWER_STATUS_EX2.

The CBatteryInfo class is a managed wrapper that internally uses P/Invoke to determine the power status, but exposes only important power characteristics as public methods. Some of this supported functionality includes determining battery status, battery life, AC power status, and the like. You can directly instantiate this class to determine the device power status. Listing One shows how you use CBatteryInfo directly (without callbacks) to determine the device power status in the .NET Compact Framework.

Monitoring Memory

Handheld devices come with limited memory that's insufficient for storing enterprise application data. Thus, the traditional handheld applications are based on a thin-client paradigm, which assumes "always connectivity." With advancements in mobile hardware technologies, however, today's devices have more memory (32 to 64 MB of RAM), as well as facilities to add more memory if necessary (via Compact Flash). This advancement in memory capabilities of small devices lets enterprise mobile application architects design solutions that can host the required enterprise data on the device itself. This memory capability is the key enabler of smart-client applications because this means that the applications need not always be connected. In addition, it means that data created and hosted locally on devices can be synchronized with the enterprise back end when the network is available. In short, effective designs of smart-client applications dictates that applications be aware of available memory on the device.

Windows CE provides GlobalMemoryStatus, a native function to determine memory status, and the MEMORYSTATUS structure, which holds memory status characteristics. The CMemoryInfo class is a managed wrapper that internally uses P/Invoke to determine the memory status, but exposes only important memory characteristics as public methods. Some of the functionality includes determining total memory, available memory, and the like. You can directly instantiate this class to determine the device memory status. Listing Two shows using CMemoryInfo directly (without callbacks) to determine the device-memory status in the .NET Compact Framework.

Monitoring Network Availability Status

Wireless is the only possible communication mechanism for handhelds for remote connectivity from the field. But again, wireless connectivity in handhelds is intermittent because of network outage, low-battery power, and the like. Well-designed mobile applications should adapt their behavior seamlessly and work smoothly, even when they are turned offline. Network status can be determined using either the native Windows CE API calls or the System.Net managed assembly. ResourceMonitor uses System.Net library calls of the .NET Compact Framework. One prominent technique to determine the network availability status is to determine the IP address of the host (device). For instance, if the IP address is 127.0.0.1 (localhost), the network is not available. Any address other than 127.0.0.1 can be treated as the condition where the network is available. The static GetHostByName function of the System.Net.Dns class is used to determine the current IP address of the host. (See the .NET Compact Framework documentation for more information about the System.Net.Dns API.)

If the network available status is True (that is, the host is assigned an address other than 127.0.0.1), it doesn't necessarily mean that the application will successfully make a network connection. Applications can still fail to make connections with network servers for any number of reasons. Consequently, applications must support error handling, depending on the underlying transport protocol.

The CNetworkInfo class provides methods to determine the network availability status and the host IP address. Listing Three uses CNetworkInfo directly (without callbacks) to determine the network connectivity status in the .NET Compact Framework.

Callback Mechanism

While the resource status can be determined directly by using the System.Net library, a more elegant, programmer-friendly, and reusable way of implementing this is through asynchronous notifications. This mechanism lets you write the logic related to handling the changing resource status at a single place in event handlers, which is invoked only when there is a change in the status of the resource being monitored.

One way of implementing this application-level event notification in .NET is via a callback mechanism. Another way is through the use of delegate functions as defined in the .NET Framework. ResourceMonitor uses the first approach and implements notifications through callbacks.

ICommonEvents, the interface that defines all ResourceMonitor events, contains declarations for all memory, power, and network status-related events. Typically, events are raised only when there is a change in resource status; for instance, power turning from high to low, network availability status changes, and so on. You must implement a class that provides an implementation of this interface, and register an instance of it with ResourceMonitor to receive notifications. This way, you have the flexibility to implement only those events in which the application is interested. You should provide a default null implementation for event methods that are not required. Events supported by this interface include battery events, memory events, and network events; see Table 1.

CResourceMonitor is the main class that provides the callback notification mechanism. This class starts a background thread that runs when the ResourceMonitor component instance is created. This thread polls the resource status at configured intervals and provides callback notifications to the application whenever there is a change in the resource status. It provides options to statically (at the time of instance creation) and dynamically change the background thread polling interval, resources to be monitored, and the like. This lets you tune the scheduling of background threads appropriately so as not to burden the processor. ResourceMonitor also lets applications monitor application-specific memory and battery values. For example, an application can specify that events be raised when the available memory crosses, say, 60 percent and battery memory left crosses 40 percent.

The CResourceMonitor class provides a public constructor that takes an application-specific implementation of ICommonEvents object, polling interval, and the resource-monitoring options. The SetPollingInterval method lets applications set the polling interval to seconds. This method can be used to dynamically change the polling interval. The SetMonitorOption method lets applications change the resources to be monitored. SetCfgBValue takes an integer parameter that sets the percent of remaining battery life to be monitored. Similarly, SetCfgMValue lets applications specify the percent of available memory to be monitored. The StopThread function stops the background thread and allows applications to choose not to receive further notifications. StartCallback starts the background thread and lets applications start receiving callback notifications.

I've included an application (available electronically; see "Resource Center," page 5) that demonstrates how the different configuration options of ResourceMonitor can be adjusted. This test application lets users interact with the program, and change the resource-monitoring options, polling interval, and battery and memory percent values.

Conclusion

Well-behaving, smart-client applications require that the application be constantly aware of the changing status of the constrained devices resources. Currently, you have to use low-level APIs to determine the resource status. The .NET Compact Framework does not expose any managed API to extract these features, and mandates use of the P/Invoke (platform invoke) features of the .NET Compact Framework.

Acknowledgments

Thanks to Rama Krishna for providing implementation support for this component in the .NET Compact Framework; Puneet Gupta and Abdul Sakib Mondal of Infosys Technologies Limited for their feedback.

DDJ



Listing One
(a) Visual Basic

Imports Infosys.PervasiveIT.ResourceMonitor
 ...
Try
Dim objBattery As New CBatteryInfo
Dim retVal As Integer
retVal = objBattery.acPwrStatus
If (retVal = 1) Then
    MessageBox.Show("Online", "AC Power Status")
ElseIf (retVal = 0) Then
    MessageBox.Show("Offline", "AC Power Status")
Else
    MessageBox.Show("Unknown", "AC Power Status")
    End If
Catch ex As Exception
      MessageBox.Show ("Exception caught ")
End Try
 ...

(b) C#
using Infosys.PervasiveIT.ResourceMonitor;
 ...
try
{
CBatteryInfo objBattery = new CBatteryInfo();
int retVal = objBattery.acPwrStatus;
if (retVal == 1)
    MessageBox.Show("Online", "AC Power Status");
else if(retVal == 0)
    MessageBox.Show("Offline", "AC Power Status");
else
    MessageBox.Show("Unknown", "AC Power Status"); 
}catch(System.Exception exception)
{
MessageBox.Show("Exception caught ");
}
 ..
Back to article


Listing Two
(a) Visual Basic

Imports Infosys.PervasiveIT.ResourceMonitor
 ...
Try
Dim objMemory As New CMemoryInfo
Dim retVal As Long
retVal = objMemory.MemoryUsed
MessageBox.Show(retVal.ToString() + " Bytes", "Memory Used")
Catch ex As Exception
      MessageBox.Show("Exception caught ")
End Try
 ..

(b) C#
using Infosys.PervasiveIT.ResourceMonitor;
 ...
try
{
CMemoryInfo objMemory = new CMemoryInfo();
long retVal = objMemory.MemoryUsed;
MessageBox.Show(retVal.ToString() + " Bytes", "Memory Used");
}catch(System.Exception exception)
{
   MessageBox.Show("Exception caught ");
}
 ..
Back to article


Listing Three
(a) Visual Basic

Imports Infosys.PervasiveIT.ResourceMonitor
 ...
Try
Dim objNetwork As New CNetworkInfo
Dim retVal As String
retVal = objNetwork.IPAddress
MessageBox.Show(retVal, "IP Address")
Catch ex As Exception
    MessageBox.Show("Exception caught ")
End Try
 ..

(b) C#
using Infosys.PervasiveIT.ResourceMonitor;
 ...
try
{
CNetworkInfo objNetwork = new CNetworkInfo();
string retVal = objNetwork.IPAddress();
MessageBox.Show(retVal , "IP Address");
}catch(System.Exception exception)
{
    MessageBox.Show("Exception caught ");
}
 ..
Back to article


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.
 

Video