Mobile Friendly Application Development Tricks (
Page 1 of 2 )
Battery life is a problem for most mobile users; the way you write your application can make a difference. Veteran Guru John Mueller shows you how to develop applications that are mobile-friendly!
Battery life is a problem for most mobile users; the way you write your application can make a difference.
For the first time ever, many organizations are predicting that laptop sales will overtake desktop computers by the end of 2008. That’s right. In a very short time, most of the users of your applications will be working on a mobile device of some sort! Mobile users are always looking for ways to increase battery life. After all, lugging along an extra battery pack isn’t any fun. One of the major reasons that mobile users have to lug that extra battery pack along is the inefficient use of system resources. The application you write today can improve mobile battery life immeasurably and it doesn’t require the use of fancy tricks, smoke, or mirrors.
Of course, it’s easy to say that no one using a mobile device will ever need your application. Perhaps you write hard-core database applications that only see use on servers or perhaps desktop machines owned by power users. Unfortunately, the excuse that your system connects to the power grid doesn’t hold much water any longer. The power companies are pressuring data centers everywhere to reduce their power consumption. In addition, some companies, such as Google have made a commitment to go green, which means using solar power in some cases (read more at Green Computing at Google). Consequently, even if you aren’t developing for mobile devices, you can discover some new techniques reading this article.
Let’s Get Physical
The biggest battery drain for any application is using a device that has movement, which includes CD, DVD, and hard drives as a minimum. Turning that spindle consumes a lot of power and reduces battery life. Starting the device actually takes the most power. Consequently, the worst-case scenario for reading data from the hard drive is to:
1.Read data
2.Let the hard drive stop
3.Start the drive back up
4.Read some more data
A better way to approach data reads is to perform as many of them as possible at one time, preferably when the application first starts and the hard drive is running anyway to load the application. The .NET Framework provides a number of data structures you can use to place the data in memory or you can create a custom data structure of your own. For example, careful use of a DataSet can make it easy to read data from disk into memory. Some very odd things fit within custom DataSets. One developer I know loads pages from paginated documents into DataSets. Each page is a separate record, making it trivial to move between pages. The point is that the data need not fit neatly within the usual definition of a database table to fit within a DataSet.
Not every piece of data will fit within a DataSet. Using XML data can make your programming chores easier when it comes to reading the data from disk. It’s possible to load an entire XML document with a single, simple method. The XML formatting makes it possible to move quickly between different areas of the document. The only negative for XML formatting is that it can become bulky, so memory use increases.
The .NET Framework also makes it possible to create data caches or even custom data storage classes. The important issue is to perform the data read all at one time whenever possible. Placing the data within memory makes it possible to work with the data without accessing the hard drive.
Saving Data Efficiently
The user who saves constantly can sabotage all of your efforts to read data efficiently. I’ve watched some users type a word, save, type another word, save, and so on. It’s incredible that they actually accomplish any work. Of course, all it takes is one user losing data to cause all kinds of turmoil at your company, so you have to approach the whole issue of saving data carefully.
One technique to conserve power is to save the data to a flash disk (assuming the user has one attached to the mobile device). Using a cache on the flash disk is considerably more efficient than writing the same data to disk. You can then move the data from the flash disk cache to the hard drive whenever you read data or the user closes the document. The idea is to use the power efficiency of the flash disk to your advantage.
A modern solution to the problem of saving data is to store it somewhere other than the local machine. For example, you could use an online storage solution for the user’s data. The user connects to the Internet, opens the data file stored there, and works as if the data is local. You store the application locally when using this solution for performance reasons. Of course, the down sides to this solution are that the user must have an Internet connection and you have to have a trustworthy online storage solution.
When you don’t have a flash disk to use and can’t rely on the Internet, you can always resort to saving at a specific interval. Your application could detect that the user is saving every 5 seconds and change those saves to once every 5 minutes to realize a power savings and a performance gain. The only problem is that this solution can lead to data loss. Any data that appears only in memory is subject to loss, so you’d need to think about this solution for a while and present it to management before you implement it. One way to mitigate the data writes is to perform a write when the hard drive is already spinning for some other task. Unfortunately, the .NET Framework doesn’t provide a way to perform this task directly. You must resort to P/Invoke to handle this situation. Start by adding the required references shown here:
using System.Runtime.InteropServices;
using System.IO;
using System.Reflection;
After you add the .NET references, you must create a reference to the external function. In this case, you use the GetDevicePowerState() function to perform the task as shown here:
// Access the Win32 GetDevicePowerState function.
[DllImport("Kernel32.DLL", CharSet=CharSet.Auto, SetLastError=true)]
public static extern Boolean GetDevicePowerState(
IntPtr hDevice, out Boolean fOn);
Notice that the GetDevicePowerState() function requires two variables and outputs status information as a Boolean. The first argument contains a handle to the device you want to check. When working with a hard drive, you can use the handle of a file on the hard drive. The second argument is actually an output, so you use the out keyword with it. This output contains the status information of the hard drive. Now that you can access the power status information, it’s time to check it out for the application hard drive. The code in Listing 1 displays a message showing the current hard drive state.
Listing 1: Obtaining the Hard Drive State
private void btnCheck_Click(object sender, EventArgs e)
{
// Holds the status information.
String Status = String.Empty;
// Holds the result of the request.
Boolean fOn = false;
// Obtain the application location.
FileStream[] Files = Assembly.GetExecutingAssembly().GetFiles();
// Check for files in the assembly.
if (Files.Length > 0)
{
// Obtain a handle for one file (normally the executable).
IntPtr hFile = Files[0].SafeFileHandle.DangerousGetHandle();
// Get the device power state and display the information
// when successful.
if (GetDevicePowerState(hFile, out fOn))
{
// When fOn is True, the disk is running.
if (fOn)
Status = "The Disk is Spinning";
else
Status = "The Disk is Sleeping";
}
else
{
// The call failed.
Status = "The Call Failed";
}
// Display the status.
MessageBox.Show(Status);
}
}
The code begins by creating some variables, one of which contains a list of files associated with the current assembly. The example only requires one of these files to determine the power status of the hard drive. The Win32 API uses a lot of handles, but Microsoft has locked them down in newer versions of the .NET Framework. Consequently, you must call the Files[0].SafeFileHandle.DangerousGetHandle() method to obtain the file handle that the GetDevicePowerState() function requires as input.
The GetDevicePowerState() call comes next. If this call fails, there’s a problem with the input and you need to debug the application. In most cases, the handle is incorrect. When the call succeeds, a value of true tells you that the disk is spinning, while a value of false tells you that the disk is sleeping. If you can reserve data writes to those times when the disk is spinning, you can save power.
You may be wondering, at this point, whether I have a problem with using the hard drive. After all, it’s local and it does do the job. As the number one power user within a mobile device, the hard drive is the device you want to avoid whenever possible. Of course, if you don’t have any alternative, then you need to face the power usage that the hard drive incurs.