f you have been developing Windows Mobile applications using the .NET Compact Framework for some time, there will be a day when you will realize that not all the functionalities you need can be satisfied by the class libraries provided by Microsoft. In such cases, you have to rely on Platform Invoke (commonly known as P/Invoke), which is a somewhat painful thing to do due to the need to perform data marshalling between your application and the operating system services. Fortunately, a group of kind souls at OpenNETCF Consulting has released a set of .NET Compact Framework extensions known as the Smart Device Framework (SDF) to complement the set of class libraries provided by Microsoft. All the hard work of calling the OS services are now wrapped and packaged so that managed developers can have directly access to them without having to resort to P/Invoke.
Two versions of the SDF are available:
- A Community Edition which includes all the compiled assemblies that you can use in your project free of charge.
- The Smart Device Framework 2.1 Extensions for Visual Studio which integrates with Visual Studio 2005 and not only includes the compiled assemblies but also includes the source code for all assemblies.
This article will focus on the Community Edition, which can be downloaded here.
Specifically, this article will show you some of the cool stuff that you can do using the SDF, like:
- Recording Sound
- Vibrating Your Windows Mobile Device
- Retrieving SIM card Information
- Retrieving Phone Logs
- Manipulating Images
- Detecting the Status of Removable Storage Devices
- Reading Strings from Text Files
The ability to record sound is very useful in situations where you need to say, record a phone conversation. To use the sound recording capability in the SDF, add a reference to the OpenNETCF.dll library in your project. Declare the following variables:
'---for audio recording--- Private audioRecorder As OpenNETCF.Media.WaveAudio.Recorder '---duration to record (in seconds)--- Const RECORD_DURATION As Integer = 10000
To record voice, first open a file for voice recording and then use the RecordFor() method available in the Recorder class:
'---save the recording to storage--- Dim audioStream As IO.Stream audioStream = System.IO.File.OpenWrite("My DocumentsRecord1.wav") audioRecorder = New OpenNETCF.Media.WaveAudio.Recorder '---save the audio to stream--- audioRecorder.RecordFor( _ audioStream, _ RECORD_DURATION, _ OpenNETCF.Media.WaveAudio.SoundFormats.Mono16bit11kHz)
The OpenNETCF.Media.WaveAudio.SoundFormats enumerations contain the various sound qualities that you can use for recording. Also, you can specify the duration of the recording via the second parameter (in seconds). Alternatively, to stop the recording prematurely simply call the Stop() method:
'---stop recording--- audioRecorder.Stop()
Once you have finished recording, you’ll be able to find the Record1.wav file stored in the My Documents folder (see Figure 1).
|Figure 1. Record1.wav: Locating the sound file.|
Vibrating Your Windows Mobile Device
Almost all devices sold in the market today supports silent alert (by spinning a miniature motor inside the device, thereby vibrating the phone). Unfortunately, the .NET Compact Framework does not provide any library for you to vibrate your phone.
For this purpose, you can use the OpenNETCF.WindowsMobile.dll library. If you are using a Windows Mobile 6 Standard device (a.k.a Smartphone), use the Play() method in the Vibrate class to vibrate your phone:
To stop the vibration, use the Stop() method:
Unfortunately, the above lines of code do not work for Pocket PC devices (now known as Windows Mobile 6 Professional and Classic devices). For Pocket PCs, you need to use the OpenNETCF.WindowsCE.dll library. You will use the notification led to emulate vibration.
The following code shows how to cause your Pocket PC to vibrate for half a second:
Dim vib As New OpenNETCF.WindowsCE.Notification.Led '---start vibration--- vib.SetLedStatus(1, OpenNETCF.WindowsCE.Notification.Led.LedState.On) System.Threading.Thread.Sleep(500) '---stop vibration--- vib.SetLedStatus(1, _ OpenNETCF.WindowsCE.Notification.Led.LedState.Off)
The first parameter of the SetLedStatus() method takes in an integer representing the led number. You may need to trial-and-error to find the number that works correctly on your device.
Retrieving SIM Card Information
The SIM card that you used for your Windows Mobile device can be used to store your contact’s information. And sometimes you might need to programmatically retrieve them from the SIM card and perhaps back them up in a storage card. To do so, you can use the classes provided in the OpenNETCF.Phone.dll library. The following code segment prints out the name and telephone numbers of all the contacts stored in the SIM card using the Sim class:
Dim mySim As New OpenNETCF.Phone.Sim.Sim For i As Integer = 0 To mySim.Phonebook.Count - 1 ListBox1.Items.Add(mySim.Phonebook(i).Text & "-" & _ mySim.Phonebook(i).Address) Next
Figure 2 shows the contacts stored in the SIM card:
|Figure 2. Contacts: Stored in a SIM card.|
You can also find out the maximum storage capacity of your SIM card using the code below:
Dim str As String = String.Empty str += "Max. Phonebook address length: " & _ mySim.MaximumPhonebookAddressLength & vbCrLf str += "Max. Phonebook index: " & _ mySim.MaximumPhonebookIndex & vbCrLf str += "Max. Phonebook text length: " & _ mySim.MaximumPhonebookTextLength & vbCrLf str += "Min. Phonebook index: " & _ mySim.MinimumPhonebookIndex & vbCrLf MsgBox(str)
Figure 3 shows the output for the SIM card.
|Figure 3. Output: The storage capacity of a SIM card.|
Retrieving Phone Logs
Every call that you make or receive is logged in your Windows Mobile device. But how do you get all this information out of the device? Well, you simply use the CallLog class, which is in the OpenNETCF.Phone.dll library, like this:
Dim CallLog As New OpenNETCF.Phone.CallLog For i As Integer = 0 To CallLog.Count - 1 Dim CallInfo As String If CallLog(i).Outgoing Then CallInfo = "Outgoing: " Else CallInfo = "Incoming: " End If CallInfo &= CallLog(i).Name & "(" & CallLog(i).Number & ")" ListBox1.Items.Add(CallInfo) Next
Besides retrieving the name of the caller (the phone tries to match the number with the contacts stored in the phone; if it is not found it will then compare with the contacts stored in the SIM card) and its number, you can also find out about the start time (including the date as well), end time, roaming (whether the call is a roaming call), and call type (whether the call was missed, answered or outgoing).
The .NET Compact Framework does not provide much functionality for image manipulations, so if you need to perform simple image processing, you are stuck. Fortunately, the OpenNETCF.Drawing.dll library provides some image utilities that you can use.
For example, you have a PictureBox control containing an image:
PictureBox1.Image = New Bitmap( _ "My DocumentsMy PicturesWaterfall.jpg")
If you want to rotate the image 90 degrees clockwise, you can use the Rotate() method in the ImageUtils class, as follows:
Dim RotatedBitmap As Bitmap = _ OpenNETCF.Drawing.Imaging.ImageUtils.Rotate(PictureBox1.Image, 90) PictureBox1.Image = RotatedBitmap
What about image scaling? For example, you want to scale the image down to a quarter of its original size, you can half its width and height, and then use the CreateThumbnail() method to reduce the image:
Dim fs As New System.IO.FileStream( _ "My DocumentsMy PicturesWaterfall.jpg", IO.FileMode.Open) Dim NewSize As Size = PictureBox1.Size With NewSize .Width /= 2 .Height /= 2 End With Dim bi As OpenNETCF.Drawing.Imaging.IBitmapImage bi = OpenNETCF.Drawing.Imaging.ImageUtils.CreateThumbnail( _ fs, NewSize) PictureBox1.Image = _ OpenNETCF.Drawing.Imaging.ImageUtils.IBitmapImageToBitmap(bi)
Detecting the Status of Removable Storage Devices
Most Windows Mobile devices support external storage, such as Compact Flash, SD cards, etc. One common request is how do you detect whether the user has inserted (or removed) one? You can do so via the OpenNETCF.Net.dll library.
First, declare a member variable of type DeviceStatusMonitor:
Dim WithEvents DiskMonitor As New OpenNETCF.Net.DeviceStatusMonitor( _ OpenNETCF.Net.DeviceStatusMonitor.FATFS_MOUNT_GUID, True)
Here, you indicate the type of file systems you want to monitor. Possible types of monitors are:
- BLOCK_DRIVER_GUID: This fires when the block driver for a Storage Manager device is loaded.
- CDDA_MOUNT_GUID: This fires when a CDDA file system is loaded.
- CDFS_MOUNT_GUID: This fires when a CDFS file system is loaded.
- FATFS_MOUNT_GUID: This fires when a FAT file system is loaded for a device.
- STORE_MOUNT_GUID: This fires when the store, managed by the Storage Manager, is ready.
- UDFS_MOUNT_GUID: This fires when a UDFS file system is loaded.
The second parameter of the DeviceStatusMonitor class indicates if you should receive notifications for devices that are currently attached before you start the monitoring.
To start the monitoring, call the StartStatusMonitoring() method:
Whenever a storage card is inserted into the device, the DeviceNotification event will fire. Hence, you just need to service this event, like this:
Private Sub DiskMonitor_DeviceNotification( _ ByVal sender As Object, _ ByVal e As OpenNETCF.Net.DeviceNotificationArgs) _ Handles DiskMonitor.DeviceNotification MsgBox("Device Name: " & e.DeviceName & ". Attached: " & _ e.DeviceAttached.ToString) End Sub
Here, you can retrieve the name of the storage card as well as indicate whether it is attached (inserted) or not (removed). Figure 4 shows the prompt when you remove a SD card from the Windows Mobile device.
|Figure 4. The Prompt: This shows when a SD card is removed from the Windows Mobile device.|
Reading Strings from Text Files
One common task in the Windows Mobile development is reading contents from a text file into a string variable. Unlike the desktop version of the .NET framework, you cannot use the My namespace, like this:
'---does not work as the My namespace is not supported in .NET CF---fileContents = My.Computer.FileSystem.ReadAllText("C:Test.txt")
You need to use a StreamReader class to read from the file, like this (which is a little lengthy):
Dim s As New System.IO.StreamReader("C:Test.txt") Dim fileContents As String = s.ReadToEnd()
To simplify this task, you can use the ReadAllText() method from the FileHelper class located in the OpenNetCF.dll library, like this:
fileContents = OpenNETCF.IO.FileHelper.ReadAllText( _ "C:Test.txt", System.Text.Encoding.ASCII)
Goodbye Platform Invokes!
Now you’re familiar with some of the classes in the Smart Device Framework and how they help solve your programming problems for which you’d usually perform Platform Invokes. Why not download the framework today and explore the wealth of classes contained within it? You will be grateful you did!