Hands-On Lab
设备状态应用程序
Lab version: 1.0.0
Last updated: 2/29/2012
内容
由于所有Windows Phone设备都要符合一个最低功能的硬件规格,所以设备之间会有一些略微的不同,因为硬件厂商会超过最低硬件规格来定义自己的设备硬件。所以,在Windows Phone 7 Mango版本中,一些新的可选硬件组件(即陀螺仪)会被添加进来。
应用程序应该能够通过编程接口来检测并获取这些硬件规格上的略微不同。
本次实验将向您展示如何创建一个简单的应用程序来实验获取设备的功能,并显示给最终用户。
目标
本次实验将帮助您完成下列目标:
· 编写一个应用程序来显示Windows Phone Mango设备的功能兼容性;
· 熟悉查询设备信息的编程接口。
提示:本次实现仅展示如何获取手机的功能兼容性和状态(电池、网络等),但不会解释在这种情况下如何去做。这将会提升应用程序开发者对于当前情况的理解,能够在应用程序里加入设备兼容性的功能。
前提条件
您在开始本次动手实验前,请先确认达到下列前提条件:
· Microsoft Visual Studio 2010 或者 Microsoft Visual C# Express2010, 和 Windows® Phone 7 Codenamed “Mango” Developer Tools,下载地址:http://go.microsoft.com/?linkid=9772716
· 如何创建 Windows® Phone 7应用程序的支持
(如果您是新的Windows® Phone 7开发者,您可以首先阅读: http://msdn.microsoft.com/en-us/gg266499).
实验提纲
这个动手实验将包括一个完整的实验,包括下列的任务:
1. 获取和显示设备通用信息
2. 获取和显示网络信息.
3. 获取和现实硬件传感器功能.
预计完成时间
完成该实验预计花费15到30分钟的时间。
任务 1. 获取和显示设备通用信息
该实验的起始点工程文件包括在实验安装目录的Source\Begin目录下。
该解决方案包括了一个基本的Model –View–ViewModel应用程序(参考http://msdn.microsoft.com/en-us/magazine/dd419663.aspx),该应用展示了符合Windows Phone 7 Mango设备用户体验需求的用户界面,包含了实现各种兼容性功能需求的界面。
如果您查看解决方案中的工程,您会注意到几个工程文件夹:
· Model – 包含数据模块,展现从设备中收集到的信息。该文件家包括下列类定义:
◦ Information – 代表对象的抽象类,该对象的属性提供设备的信息
◦ CapabilityInformation – 继承自Information 的抽象类,添加属性来描述设备的兼容性功能
◦ NetworkInformation – 继承自Information的抽象类,添加属性来描述设备的网络状态和设备兼容性
◦ DeviceInformation –继承自Information的抽象类,添加属性来描述设备自身信息(硬件版本,模块名称,等)
· Service – 包含ViewModel 所需要的获取设备信息的对象,这个文件家里包括下列子目录和接口定义:
◦ IInformationProvider – 定义一个提供设备自身信息的入口点,包括设备本身功能、网络兼容性和状态等
◦ Fake – 这个文件夹包含的代码将提供模拟数据,用于在设计期展示。这将使得用户界面能够更好地在设计期虚拟化,而无需运行应用程序查看结果
◦ Real – 这个文件家包含查询设备信息、获取兼容性的实际代码
· ViewModel – 包含应用程序的ViewModel, 将数据绑定到用户界面上。该文件家包括一个单独的类:
◦ DeviceInformationViewModel – 该类提供来自IInformationProvider的设备信息;它提供Fake(模拟)数据,在设计器模拟真实数据,运行时将用实际数据替代。
本次实验的关注点在于实现Real 文件夹中包含的类,使之能够执行实际的查询。
这些任务将展示如何使用Microsoft.Phone.Info.DeviceStatus类的功能,来获取设备的基本信息,其中包括设备版本号、键盘、内存和电源等。
提示:使用DeviceStatus类需要添加对Microsoft.Phone程序集的引用。该引用将会默认出现在Windows Phone 7 Mango的应用程序工程中。
1. 打开Service\Real工程文件夹中 RealDeviceInformation.cs 文件。
2. 根据下列的代码来实现RealDeviceInformation 类:
C#
public class RealDeviceInformation: DeviceInformation
{
publicoverride void RefreshData()
{
PowerSource =
Microsoft.Phone.Info.DeviceStatus.PowerSource.ToString();
FirmwareVersion =
Microsoft.Phone.Info.DeviceStatus.DeviceFirmwareVersion;
HardwareVersion =
Microsoft.Phone.Info.DeviceStatus.DeviceHardwareVersion;
Manufacturer =
Microsoft.Phone.Info.DeviceStatus.DeviceManufacturer;
Name = Microsoft.Phone.Info.DeviceStatus.DeviceName;
TotalMemory =
(Microsoft.Phone.Info.DeviceStatus.DeviceTotalMemory/
1048576).ToString() + "MB";
HasKeyboard = Microsoft.Phone.Info.DeviceStatus.IsKeyboardPresent;
}
}
提示:这些代码从Microsoft.Phone.Info.DeviceStatus类中的属性值中获取信息,保存到information对象中,允许用户界面进行显示。
任务 2. 获取和显示网络信息
该任务演示如何获取设备的网络信息、状态和兼容性,主要使用两个类:Microsoft.Phone.Net.NetworkInformation命名空间中的DeviceNetworkInformation和NetworkInterface。这些类允许我们检测设备是否已经连接到了某个网络中,并允许我们查看网络连接的类型。当你的应用程序需要依赖活动网络连接,或者下载相当数量的数据时,网络信息将十分有用,你可以等到Wi-Fi有效时再进行下载。
提示:通过移动电话的数据连接来下载大数据量数据时,要考虑用户会使用相当部分的数据流量。另外,使用移动电话网络数据下载,设备电池的消耗也大于使用无线Wi-Fi网络。
1. 打开位于Service\Real的 the RealNetworkInformation.cs 文件.
2. 在文件顶部添加下列代码:
C#
using Microsoft.Phone.Net.NetworkInformation;
3. 使用下列代码实现RealNetworkInformation 类:
C#
public class RealNetworkInformation: NetworkInformation
{
publicoverride void RefreshData()
{
IsConnected = Microsoft.Phone.Net.NetworkInformation.
DeviceNetworkInformation.IsNetworkAvailable;
ConnectionType =
GetInterfaceTypeString(Microsoft.Phone.Net.NetworkInformation.
NetworkInterface.NetworkInterfaceType);
MobileOperator = Microsoft.Phone.Net.NetworkInformation.
DeviceNetworkInformation.CellularMobileOperator;
if (String.IsNullOrEmpty(MobileOperator))
{
MobileOperator = "N/A";
}
IsCellularDataEnabled = Microsoft.Phone.Net.NetworkInformation.
DeviceNetworkInformation.IsCellularDataEnabled;
IsCellularDataRoamingEnabled = Microsoft.Phone.Net.NetworkInformation.
DeviceNetworkInformation.IsCellularDataRoamingEnabled;
IsWifiEnabled = Microsoft.Phone.Net.NetworkInformation.
DeviceNetworkInformation.IsWiFiEnabled;
}
privatestring GetInterfaceTypeString(Microsoft.Phone.Net.
NetworkInformation.NetworkInterfaceType networkInterfaceType)
{
switch(networkInterfaceType)
{
caseNetworkInterfaceType.AsymmetricDsl:
return"Asymmetric DSL";
caseNetworkInterfaceType.Atm:
return "Atm";
caseNetworkInterfaceType.BasicIsdn:
return "BasicISDN";
caseNetworkInterfaceType.Ethernet:
return "Ethernet";
caseNetworkInterfaceType.Ethernet3Megabit:
return "3Mbit Ethernet";
caseNetworkInterfaceType.FastEthernetFx:
return "FastEthernet";
caseNetworkInterfaceType.FastEthernetT:
return "FastEthernet";
caseNetworkInterfaceType.Fddi:
return "FDDI";
caseNetworkInterfaceType.GenericModem:
return "GenericModem";
caseNetworkInterfaceType.GigabitEthernet:
return "GigabitEthernet";
caseNetworkInterfaceType.HighPerformanceSerialBus:
return "HighPerformance Serial Bus";
caseNetworkInterfaceType.IPOverAtm:
return "IPOver Atm";
caseNetworkInterfaceType.Isdn:
return "ISDN";
caseNetworkInterfaceType.Loopback:
return "Loopback";
caseNetworkInterfaceType.MobileBroadbandCdma:
return "CDMABroadband Connection";
caseNetworkInterfaceType.MobileBroadbandGsm:
return "GSMBroadband Connection";
caseNetworkInterfaceType.MultiRateSymmetricDsl:
return "Multi-RateSymmetrical DSL";
caseNetworkInterfaceType.None:
return "None";
caseNetworkInterfaceType.Ppp:
return "PPP";
caseNetworkInterfaceType.PrimaryIsdn:
return "PrimaryISDN";
caseNetworkInterfaceType.RateAdaptDsl:
return "RateAdapt DSL";
caseNetworkInterfaceType.Slip:
return "Slip";
caseNetworkInterfaceType.SymmetricDsl:
return "SymmetricDSL";
caseNetworkInterfaceType.TokenRing:
return "TokenRing";
caseNetworkInterfaceType.Tunnel:
return "Tunnel";
caseNetworkInterfaceType.Unknown:
return "Unknown";
caseNetworkInterfaceType.VeryHighSpeedDsl:
return "VeryHigh Speed DSL";
caseNetworkInterfaceType.Wireless80211:
return "Wireless";
default:
return "Unknown";
}
}
}
提示:你也许注意到大部分代码是一个函数,将网络接口类型的枚举变量转换为更加友好的字符串。注意我们可以直接在GetInterfaceTypeString方法中使用NetworkInterfaceType类型,以增加代码的可读性。
RefreshData方法是用Microsoft.Phone.Net.NetworkInformation .DeviceNetworkInformation类来获取设备连接状态,使用Microsoft.Phone.Net.NetworkInformation.NetworkInterface类获取网络连接类型。
任务 3. 获取和现实硬件传感器功能
该任务演示如何获取设备的硬件传感器信息和摄像头类型等信息。我们使用Microsoft.Devices和Microsoft.Devices.Sensors命名空间,这些类允许我们检测设备包含的传感器,例如检测摄像头的兼容性。如果你计划写应用程序使用重力感应输入,我们要首先确认设备包含重力感应传感器。
1. 添加 Mircosoft.Devices.Sensors 程序集引用.
2. 打开位于Service\Real的 RealCapabilityInformation.cs 文件.
3. 根据下列代码实现RealCapabilityInformation 类:
C#
public class RealCapabilityInformation: CapabilityInformation
{
publicoverride void RefreshData()
{
IsGyroSupported = Microsoft.Devices.Sensors.Gyroscope.IsSupported;
IsAccelerometerSupported =
Microsoft.Devices.Sensors.Accelerometer.IsSupported;
IsCompassSupported = Microsoft.Devices.Sensors.Compass.IsSupported;
IsMotionSupported = Microsoft.Devices.Sensors.Motion.IsSupported;
}
}
提示:这部分代码中访问Microsoft.Devices.Sensors命名空间下的几个类,并测试对于设备是否有效:Gyroscope,指示设备方向的传感器, Accelerometer,指示设备在3D空间中的运动趋势;Compass,检测设备所处的地球磁场所在的方向;Motion,一个综合了以上所有功能的传感器。
4. 打开位于程序根目录的MainPage.xaml下的 MainPage.xaml.cs 文件.
5. 在文件头部添加下列代码:
C#
using Microsoft.Devices;
using System.Collections.ObjectModel;
using System.Windows.Navigation;
6. 用下列代码替换MainPage类中的 PanoStatus_SelectionChanged:
C#
private void PanoStatus_SelectionChanged(objectsender, SelectionChangedEventArgs e)
{
if (PanoStatus.SelectedItem== null)
{
return;
}
if((PanoStatus.SelectedItem as PanoramaItem).Header.ToString()==
"capabilities")
{
Camera = new PhotoCamera();
Camera.Initialized += camera_Initialized;
videoBrush = new VideoBrush();
videoBrush.Stretch = Stretch.Uniform;
videoBrush.SetSource(Camera);
cameraPreview.Fill = videoBrush;
}
else
{
UninitializeCamera();
}
}
提示:PanoStatus_SelectionChanged方法是事件处理函数,当应用程序主界面的panorama控件改变显示的项目时会触发该参数。显示Capabilities项时,初始化设备的摄像头,并且在屏幕上显示预览。这些允许你获得摄像头支持的分辨率。当其他的界面显示时,反初始化摄像头。
7. 在MainPage类中添加一系列的附加方法。这些方法初始化设备的摄像头,允许我们查询其支持的分辨率,当我们不再需要时,需要释放摄像头对象。
8. 使用下列代码:
C#
protectedoverride void OnNavigatedTo(NavigationEventArgs e)
{
// The application was restored
if(e.IsNavigationInitiator == false)
{
// Simulate a panorama change, in case we are viewing the
// capabilities item
PanoStatus_SelectionChanged(this, null);
}
base.OnNavigatedTo(e);
}
protectedoverride void OnNavigatedFrom(NavigationEventArgs e)
{
// The application was sent to the background
if(e.IsNavigationInitiator == false)
{
UninitializeCamera();
}
base.OnNavigatedFrom(e);
}
private void UninitializeCamera()
{
cameraPreview.Fill = null;
if(Camera != null)
{
Camera.Dispose();
Camera = null;
}
}
private void camera_Initialized(object sender,
CameraOperationCompletedEventArgs e)
{
Dispatcher.BeginInvoke(() =>
{
CapabilityInformationinfo =
(App.Current.Resources["DeviceInformationViewModel"] as
DeviceInformationViewModel).InformationProvider.Capabilities;
ObservableCollection<string> resolutions =
newObservableCollection<string>();
foreach(Size resolution inCamera.AvailableResolutions)
{
resolutions.Add(String.Format("{0}x{1}",resolution.Width,
resolution.Height));
}
info.SupportedResolutions = resolutions;
});
}
让我们查看我们添加的方法:
· OnNavigatedTo 和 OnNavigatedFrom 当应用程序切换到后台/前台,并显示Capabilities页面时,用于初始化和反初始化摄像头。
· UninitializeCamera 是一个简单的辅助方法,用于尽可能将摄像头预览与用户界面相分离
· camera_Initialized 是一个事件处理函数,当摄像头初始化完成,或者更新ViewModel中摄像头支持的分辨率时,该事件将会被触发。
我们已经完成了应用程序的开发,如果你现在运行在一个模拟器上,运行效果如下:
Figure 1
应用程序显示模拟器的品牌和硬件版本
Figure 2
模拟器检测的网络状态和兼容性
Figure 3
模拟器的兼容性报告
Figure 4
拖拽 capabilities 视图,显示 camera preview.另外几个视图也支持拖动。.
尝试运行在您的Windows Phone 设备上,运行应用程序。根据WindowsPhone设备的不同,您将会看到不同的结果。
Windows Phone支持通过API检测硬件兼容性和设备状态。在本次实验中,您使用了:
· Microsoft.Devices.Sensors 命名空间下的Capability API 用来检测是否支持 Gyro, compass, accelerometer 和 combined motion sensors等。
· Microsoft.Phone.Info.DeviceStatus类用于检测硬件开发商兼容性和有效物理内存等功能
· DeviceNetworkInformation 和 NetworkInterface类检测设备的网络连接
正如您已经学会了,在很少的几行代码中如何检测兼容性。适当地获取这些兼容性对于创建良好用户体验的应用程序至关重要(不管设备的制造商和型号)。