白桦的天空

第一次的心动,永远的心痛!
  首页  :: 新随笔  :: 联系 :: 管理

在Windows Mobile中应用智能设备框架(Smart Device Framework)

=========================================================

本文为khler翻译,转载必须确保本文完整并完整保留原作者及译者信息及本文原始链接

E-mail: khler@163.com

QQ:     23381103

MSN:   pragmac@hotmail.com

本文英文/原文地址:

http://www.devx.com/wireless/Article/36134
=========================================================


 很遗憾,.Net Compact Framework 类库对于在 Windows Mobile 做应用程序开发是很不成熟的,有时候你不得不依赖于会引起诸多问题的Platform Invoke机制。 Smart Device Framework(SDF),一个对.NetCF 进行了扩展的功能库,覆盖了.Net Compact Framework所未触及的区域。

Wei-Meng Lee
2007.12.4
 
         如果你之前使用.NetCF为Windows Mobiel开发过应用程序,那么你就会发现仅仅依靠微软提供的类库是不能满足所有功能需要的。在这种情况下,你不得不依赖于Platform Invoke(即通常所说的P/Invoke)——一种为了与操作系统共享数据而不得不使用的令人不快的东西。幸运的是,OpenNetCF组织推出了一个叫 Smart Device Framework(SDF)的类库,它填补了微软.NetCF类库的不足,将所有对操作系统的服务的调用封装到了这个类库中,方便基于托管代码平台的开发者直接访问平台服务而不需要繁琐的P/Invoke调用。
         现在SDF有两个可用版本:
         一个包含了所有功能集的通用已编译版本,它可以直接应用到你的项目中而不用考虑付费问题。
         Smart Device Framework 2.1 Extensions,与Visual Studio 2005集成了的包含了所有功能集的二进制文件集,以及相应的源代码。
         
         本文主要关注通用版本,可以在这里下载到。
         
         本文将向你展示一些SDF的非常酷的特性,如:

         声音录制
         震动提示
         读取SIM卡信息
         读取电话记录
         图象处理
         检查可插拔设备的状态
         从文本文件中读取字符串

 
声音录制
当你需要录制一段谈话记录时,声音录制功能是一个非常有用的功能。要利用SDF添加录音功能,你就要在你的工程中添加一个对OpenNETCF.dll 库的参照,并申明如下变量:
 

    '---for audio recording---
    Private audioRecorder As OpenNETCF.Media.WaveAudio.Recorder
    
'---duration to record (in seconds)---
    Const RECORD_DURATION As Integer = 10000

 
要录制声音,首先打开一个文件用于记录数据,然后使用Recoder类中的RecordFor()方法:

    '---save the recording to storage---
    Dim audioStream As IO.Stream
    audioStream 
= System.IO.File.OpenWrite("\My Documents\Record1.wav")
    audioRecorder 
= New OpenNETCF.Media.WaveAudio.Recorder
 
    
'---save the audio to stream---
    audioRecorder.RecordFor(audioStream, RECORD_DURATION, OpenNETCF.Media.WaveAudio.SoundFormats.Mono16bit11kHz)
 

 
OpenNETCF.Media.WaveAudio.SoundFormats枚举类型枚举了大量的声音质量,用于对声音的品质进行控制。
可以通过指定第二个参数来指定录制的时间长短。当然,你也可以通过调用Stop()来结束录制:
 

       '---stop recording---
        audioRecorder.Stop()

 
一旦结束录音,你就可以在\My Documents\ folder (图1)下找到Record1.wav文件
 


图1 Record1.wav文件所在位置

 
振动提示
现在,几乎市面上的所有手机都具有静音提示(通过内嵌一个小马达驱动,使机体产生振动)。不幸的是,.NetCF并没有提供这样的接口。
为了达到这个目的,你可以使用OpenNETCF.WindowsMobile.dll库,如果你使用的是Window Mobile 6标准版(Windows Mobile 6 Standard),你可以使用Vibrate类的Play()方法使你的手机产生振动:
 
 

       OpenNETCF.WindowsMobile.Vibrate.Play()

 
    使用Stop()方法停止振动:
 

       OpenNETCF.WindowsMobile.Vibrate.Stop()


     不幸的是,在Pocket PC(比如Windows Mobile 6 专业版- Windows Mobile 6 Professional,以及更老的设备)中,上面的代码不起作用。对于这些设备,你可以使用OpenNETCF.WindowsCE.dll类库,通过通知LET来模拟震动。
下面显示了在Pocket PC中震动半秒的代码: 
 

        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)


     SetLedStatus()的第一个参数用于指明要被点亮的LED的int型索引,你必须通过错误跟踪来找到你的设备中正确的索引号.
 
读取SIM卡中的信息
在Windows Mobile中,SIM卡用来存储你的联系人的信息。有时候你需要定时备份这些信息并存储到另一个存储卡中。可以使用OpenNETCF.Phone.dll库来完成这项工作,下面的代码段利用Sim类打印出所有存储于SIM卡中的联系人的姓名和电话:

 

         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


 图2 显示了存储于SIM卡中的联系人的信息:

 

图2 存储在SIM卡中的联系人信息
 
    利用下面的代码,你也可以取得SIM卡的最大存储能力:

        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)

 
         图3 显示了SIM卡的输出:


图3 SIM卡输出信息
 
读取电话记录
每项呼入和呼出的信息都被记录在了你的Windows Mobile设备中。但是怎么取出这些信息呢?实际上,你只要简单的利用OpenNETCF.Phone.dll 库中的CallLog类就能达到目的,就象这样:
 

        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

 
     除了返回呼入人的姓名(通过在存储卡中查找与号码匹配的人的姓名,如果找不到,就在SIM卡中查找)和电话号码,你也可以找到开始时间(包括日期)、结束时间、是否漫游、呼叫类型(未接、已接、超时)。
 
图象处理
.NET Compact Framework并没有提供足够的图象处理功能,所以,如果你想实现简单的图象处理操作,你将停滞不前。幸运的是,OpenNETCF.Drawing.dll库提供了一些图象处理工具可以为你所用。
例如,一个PictureBox控件中容纳了一张图片:


        PictureBox1.Image 
= New Bitmap( "\My Documents\My Pictures\Waterfall.jpg")


     如果想顺时钟旋转90度,你可以使用ImageUtils类中的Rotate()方法,就象这样:

        Dim RotatedBitmap As Bitmap = OpenNETCF.Drawing.Imaging.ImageUtils.Rotate(PictureBox1.Image, 90)
        PictureBox1.Image 
= RotatedBitmap


     那么图像缩放呢?例如,你想把图像缩小到原始尺寸的1/4,你可以将其高度和宽度取半,然后调用CreateThumbnail() 方法:

        Dim fs As New System.IO.FileStream("\My Documents\My Pictures\Waterfall.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)


 检查可插拔设备的状态
    很多Windows Mobile都支持扩展存储,如闪存、SD卡等。一项比较普遍的需求就是怎样检查用户是否插入/移除了一张卡?你可以通过OpenNETCF.Net.dll类库达到目的。
    首先,申明一个DeviceStatusMonitor类型的成员变量:
  

Dim WithEvents DiskMonitor As New OpenNETCF.Net.DeviceStatusMonitor( _
       OpenNETCF.Net.DeviceStatusMonitor.FATFS_MOUNT_GUID, 
True)


     这里,你指明了要监视的文件类型,可能的选项有:

    ·         BLOCK_DRIVER_GUID: 当存储管理器的Block Driver被装载时触发
    ·         CDDA_MOUNT_GUID: 当CDDA文件系统被装载时触发
    ·         CDFS_MOUNT_GUID: 当CDFS 文件系统被装载时触发
    ·         FATFS_MOUNT_GUID: 当FAT文件系统被装载时触发
    ·         STORE_MOUNT_GUID: 当在存储管理器管理下的存储设备准备就绪时触发
    ·         UDFS_MOUNT_GUID: UDFS文件系统被装载时触发

    DeviceStatusMonitor的第二个参数指明是否接收在你启动监听之前就已经存在的设备的通知。

    通过调用StartStatusMonitoring()以启动监听:

       DiskMonitor.StartStatusMonitoring()

  
    无论何时,只要有存储设备插入,DeviceNotificat 事件就会被触发。因此,你只需要处理这个事件就可以了,就象这样:

    Private Sub DiskMonitor_DeviceNotification(ByVal sender As ObjectByVal e As OpenNETCF.Net.DeviceNotificationArgs)
        
Handles DiskMonitor.DeviceNotification
        
MsgBox("Device Name: " & e.DeviceName & ". Attached: " & e.DeviceAttached.ToString)
    
End Sub


    在这里,你可以通过返回存储设备名称来显示是插入还是取出了存储卡。图4显示了当你取出一个SD卡的时候的提示信息。


图4 当SD卡拔出时的提示信息


从文本文件中读取数据

    在Windows Mobile编成中的一项常见操作就是将文本文件中的内容读取到一个变量中。不像桌面系统的.Net Framework,你不能使用“My”命名空间去访问文件,就象这样:
        '---does not work as the My namespace is not supported in .NET CF---
        fileContents = My.Computer.FileSystem.ReadAllText("C:\Test.txt"
 
    你需要使用StreamReader去读取文件内容,就象这样(有点长):
 
        Dim s As New System.IO.StreamReader("C:\Test.txt")
        
Dim fileContents As String = s.ReadToEnd()
 
    为了简化这项操作,你可以使用OpenNetCF.dll 库中的FileHelper类的ReadAllText()方法,像这样:
 
        fileContents = OpenNETCF.IO.FileHelper.ReadAllText( "C:\Test.txt", System.Text.Encoding.ASCII)
 
再见,Platform Invokes!
    现在,你应该对Smart Device Framework(SDF)中的类有了基本了解,并利用它们为你解决之前不得不用P/Invoke解决的问题,那么为什么不立即下载并体验一下其中的类所提供的强大功能呢?你将为你这样的决定感到庆幸!

 
 Wei-Meng Lee ,微软MVP,Developer Learning Solutions创始人,主要从事微软技术培训及推广工作。有关作者的更详细信息,请访问他的blog。