Windows phone 8 学习笔记(7) 设备
本节主要涉及到 Windows phone 8 手机支持的各类设备,包括相机、设备状态,振动装置等。还有各类感应器,包括磁力计、加速度器和陀螺仪。通过设备状态可以获取内存、硬件、电源、键盘等状态;通过相机捕获照片和视频;各类感应器帮助我们获取设备的运动状态等。
快速导航:
一、设备状态
二、相机
三、罗盘传感器
四、加速度计
五、陀螺仪
六、如何振动手机
一、设备状态
通过DeviceStatus 类我们可以确定设备的相关状态信息,比如内存大小啊,固件版本啊,还有是否部署了物理键盘等信息,以及与电源的相关信息,当前是电池还是外部电源等。
我们通过下面的代码展示如何获取这些信息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) { var timer = new DispatcherTimer(); timer.Interval = new TimeSpan(0, 0, 10); timer.Tick += new EventHandler((a, b) => { //当前内存使用了多少字节 var x = Microsoft.Phone.Info.DeviceStatus.ApplicationCurrentMemoryUsage; textblock1.Text = "当前内存:" + convert(x); //高峰时内存使用了多少字节 var y = Microsoft.Phone.Info.DeviceStatus.ApplicationPeakMemoryUsage; textblock2.Text = "峰值内存:" + convert(y); }); timer.Start(); textblock3.Text = "设备制造商名:" + DeviceStatus.DeviceManufacturer; textblock4.Text = "设备名:" + DeviceStatus.DeviceName; textblock5.Text = "固件版本:" + DeviceStatus.DeviceFirmwareVersion; textblock6.Text = "硬件版本:" + DeviceStatus.DeviceHardwareVersion; textblock7.Text = "物理内存大小:" +convert( DeviceStatus.DeviceTotalMemory); textblock8.Text = "应用进程可分配最大额外内存:" + convert(DeviceStatus.ApplicationMemoryUsageLimit); textblock9.Text = "是否包含硬件键盘:" + DeviceStatus.IsKeyboardPresent.ToString(); textblock10.Text = "是否部署硬件键盘:" + DeviceStatus.IsKeyboardDeployed.ToString(); textblock11.Text = "电源状态:" + DeviceStatus.PowerSource.ToString(); //关闭或部署键盘时 DeviceStatus.KeyboardDeployedChanged += new EventHandler((a, b) => { textblock9.Text = "键盘变更,是否包含硬件键盘:" + DeviceStatus.IsKeyboardPresent.ToString(); }); //设备电源变更时 DeviceStatus.PowerSourceChanged += new EventHandler((a, b) => { textblock11.Text = "电源状态变更:" + DeviceStatus.PowerSource.ToString(); }); base .OnNavigatedTo(e); } private string convert( long x) { return Math.Round(x / (1024.0 * 1024.0), 2) + "M" ; } |
二、相机
有两个类可以调用相机,分别是PhotoCamera和PhotoCaptureDevice,一般如果要支持WP7以及对相机基本调用则使用前者,后者用于相机的高级捕获。
1.PhotoCamera
我们首先通过PhotoCamera来访问相机,我们可以实现一个具备拍照功能的基本相机,包含自动对焦、闪光灯、分辨率调整等功能,下面代码演示了如何使用。
[XAML]1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 | < Grid x:Name="LayoutRoot" Background="Transparent"> < Canvas x:Name="canvas1" Margin="0,0,0,0" Tap="canvas1_Tap" Width="800" Height="480"> < Canvas.Background > < VideoBrush x:Name="viewfinderBrush" /> </ Canvas.Background > < TextBlock x:Name="focusBrackets" Text="[ ]" FontSize="40" Visibility="Collapsed"/> </ Canvas > < ListBox x:Name="listbox1" Margin="95,394,538,59" SelectionChanged="listbox1_SelectionChanged"> < ListBox.ItemTemplate > < DataTemplate > < TextBlock Text="{Binding}"></ TextBlock > </ DataTemplate > </ ListBox.ItemTemplate > < ListBox.ItemContainerStyle > < Style TargetType="ListBoxItem"> < Setter Property="Margin" Value="0,0,10,0" /> </ Style > </ ListBox.ItemContainerStyle > < ListBox.ItemsPanel > < ItemsPanelTemplate > < StackPanel Orientation="Horizontal"></ StackPanel > </ ItemsPanelTemplate > </ ListBox.ItemsPanel > </ ListBox > < TextBlock x:Name="textblock1" Foreground="Red" HorizontalAlignment="Left" Margin="584,22,0,0" TextWrapping="Wrap" VerticalAlignment="Top"/> < TextBlock HorizontalAlignment="Left" Margin="10,394,0,0" TextWrapping="Wrap" Text="闪光灯:" VerticalAlignment="Top"/> < TextBlock HorizontalAlignment="Left" Margin="273,394,0,0" TextWrapping="Wrap" Text="分辨率:" VerticalAlignment="Top"/> < ListBox x:Name="listbox2" Margin="350,394,10,59" SelectionChanged="listbox2_SelectionChanged"> < ListBox.ItemTemplate > < DataTemplate > < TextBlock Text="{Binding}"/> </ DataTemplate > </ ListBox.ItemTemplate > < ListBox.ItemContainerStyle > < Style TargetType="ListBoxItem"> < Setter Property="Margin" Value="0,0,10,0" /> </ Style > </ ListBox.ItemContainerStyle > < ListBox.ItemsPanel > < ItemsPanelTemplate > < StackPanel Orientation="Horizontal"/> </ ItemsPanelTemplate > </ ListBox.ItemsPanel > </ ListBox > < Button Content="对焦" HorizontalAlignment="Left" Margin="517,410,0,0" VerticalAlignment="Top" Click="Button_Click_1"/> < Button Content="拍照" HorizontalAlignment="Left" Margin="623,410,0,0" VerticalAlignment="Top" Click="Button_Click_2"/> < TextBlock Width="500" x:Name="textblock2" HorizontalAlignment="Left" Margin="10,434,0,0" TextWrapping="Wrap" VerticalAlignment="Top"/> </ Grid > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 | public partial class MainPage : PhoneApplicationPage { // 构造函数 public MainPage() { InitializeComponent(); } PhotoCamera photoCamera; MediaLibrary library = new MediaLibrary(); protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) { //判断是否支持相机 if (PhotoCamera.IsCameraTypeSupported(CameraType.Primary)) { textblock1.Text = "当前取景:后置摄像头" ; photoCamera = new PhotoCamera(CameraType.Primary); } else if (PhotoCamera.IsCameraTypeSupported(CameraType.FrontFacing)) { textblock1.Text = "当前取景:前置摄像头" ; photoCamera = new PhotoCamera(CameraType.FrontFacing); } else { textblock1.Text = "设备不支持相机" ; return ; } textblock2.Text = "相机正在初始化中." ; viewfinderBrush.SetSource(photoCamera); //相机初始化完成时 photoCamera.Initialized += (a, b) => { if (b.Succeeded) { this .Dispatcher.BeginInvoke(() => { SupportedFlashModesInit(); AvailableResolutionsInit(); textblock2.Text = "相机初始化完成." ; }); } }; //有图像可用时(拍摄完成) photoCamera.CaptureImageAvailable += (a, b) => { this .Dispatcher.BeginInvoke(() => { textblock2.Text = "正在保存照片." ; }); library.SavePictureToCameraRoll(Guid.NewGuid().ToString() + ".jpg" , b.ImageStream); this .Dispatcher.BeginInvoke(() => { textblock2.Text = "照片保存成功." ; }); }; //对焦完成时 photoCamera.AutoFocusCompleted += (a, b) => { this .Dispatcher.BeginInvoke(() => { textblock2.Text = "自动对焦完成." ; focusBrackets.Visibility = Visibility.Collapsed; }); }; base .OnNavigatedTo(e); } /// <summary> /// 显示支持的闪光模式 /// </summary> private void SupportedFlashModesInit() { List< string > flashModes = new List< string >() { "关" }; if (photoCamera.IsFlashModeSupported(FlashMode.On)) flashModes.Add( "开" ); if (photoCamera.IsFlashModeSupported(FlashMode.Auto)) flashModes.Add( "自动" ); if (photoCamera.IsFlashModeSupported(FlashMode.RedEyeReduction)) flashModes.Add( "红眼" ); listbox1.ItemsSource = flashModes; } /// <summary> /// 显示支持的分辨率 /// </summary> private void AvailableResolutionsInit() { listbox2.ItemsSource = photoCamera.AvailableResolutions; } //对焦 private void Button_Click_1( object sender, RoutedEventArgs e) { //是否支持自动对焦 if (photoCamera.IsFocusSupported == true ) { try { photoCamera.Focus(); } catch (Exception ex) { this .Dispatcher.BeginInvoke(() => { textblock2.Text = "对焦错误:" + ex.Message; }); } } else { this .Dispatcher.BeginInvoke(() => { textblock2.Text = "相机不支持自动对焦." ; }); } } //拍照 private void Button_Click_2( object sender, RoutedEventArgs e) { if (photoCamera != null ) { try { photoCamera.CaptureImage(); } catch (Exception ex) { this .Dispatcher.BeginInvoke(() => { textblock2.Text = "拍照错误:" + ex.Message; }); } } } //特定点对焦 private void canvas1_Tap( object sender, GestureEventArgs e) { if (photoCamera == null ) return ; if (!photoCamera.IsFocusAtPointSupported) { textblock2.Text = "不支持特定点对焦" ; return ; } try { Point tapLocation = e.GetPosition(canvas1); focusBrackets.SetValue(Canvas.LeftProperty, tapLocation.X - 30); focusBrackets.SetValue(Canvas.TopProperty, tapLocation.Y - 28); double focusXPercentage = tapLocation.X / canvas1.Width; double focusYPercentage = tapLocation.Y / canvas1.Height; focusBrackets.Visibility = Visibility.Visible; photoCamera.FocusAtPoint(focusXPercentage, focusYPercentage); this .Dispatcher.BeginInvoke( delegate () { textblock2.Text = String.Format( "针对位置 [{0:N2} , {1:N2}] 开始对焦" , focusXPercentage, focusYPercentage); }); } catch (Exception focusError) { this .Dispatcher.BeginInvoke( delegate () { textblock2.Text = "对焦错误:" + focusError.Message; focusBrackets.Visibility = Visibility.Collapsed; }); } } //切换闪光灯模式 private void listbox1_SelectionChanged( object sender, SelectionChangedEventArgs e) { if (e.AddedItems.Count == 0) return ; switch (e.AddedItems[0].ToString()) { case "关" : photoCamera.FlashMode = FlashMode.Off; break ; case "自动" : photoCamera.FlashMode = FlashMode.Auto; break ; case "红眼" : photoCamera.FlashMode = FlashMode.RedEyeReduction; break ; case "开" : photoCamera.FlashMode = FlashMode.On; break ; } textblock2.Text = "已将闪光模式设置为:" + e.AddedItems[0].ToString(); } //切换分辨率 private void listbox2_SelectionChanged( object sender, SelectionChangedEventArgs e) { if (e.AddedItems.Count == 0) return ; photoCamera.Resolution = (Size)e.AddedItems[0]; textblock2.Text = "已将分辨率设置为:" + photoCamera.Resolution.ToString(); } } |
2.PhotoCaptureDevice
PhotoCaptureDevice对相机的高级捕获很多都是用于支持后续版本的,下面我们简单演示下通过PhotoCaptureDevice捕获照片并显示出来的方法。
[XAML]1 2 3 4 5 6 7 8 9 | < Grid x:Name="LayoutRoot" Background="Transparent"> < Canvas x:Name="canvas1" Margin="0,0,0,0" Width="800" Height="480"> < Canvas.Background > < VideoBrush x:Name="viewfinderBrush" /> </ Canvas.Background > < Button Content="拍照" Canvas.Left="653" Canvas.Top="383" Click="Button_Click_1"/> < Image x:Name="img1" Height="231" Canvas.Left="508" Canvas.Top="87" Width="220"/> </ Canvas > </ Grid > |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | public partial class MainPage : PhoneApplicationPage { // 构造函数 public MainPage() { InitializeComponent(); } PhotoCaptureDevice photoCaptureDevice; CameraCaptureSequence cameraCaptureSequence; MemoryStream captureStream = new MemoryStream(); protected async override void OnNavigatedTo(NavigationEventArgs e) { if (PhotoCaptureDevice.AvailableSensorLocations.Contains(CameraSensorLocation.Back)) { var SupportedResolutions = PhotoCaptureDevice.GetAvailableCaptureResolutions(CameraSensorLocation.Back); photoCaptureDevice = await PhotoCaptureDevice.OpenAsync(CameraSensorLocation.Back, SupportedResolutions[0]); } else if (PhotoCaptureDevice.AvailableSensorLocations.Contains(CameraSensorLocation.Front)) { var SupportedResolutions = PhotoCaptureDevice.GetAvailableCaptureResolutions(CameraSensorLocation.Front); photoCaptureDevice = await PhotoCaptureDevice.OpenAsync(CameraSensorLocation.Front, SupportedResolutions[0]); } else { return ; } viewfinderBrush.SetSource(photoCaptureDevice); cameraCaptureSequence = photoCaptureDevice.CreateCaptureSequence(1); // Set camera properties. photoCaptureDevice.SetProperty(KnownCameraPhotoProperties.FlashMode, FlashState.On); photoCaptureDevice.SetProperty(KnownCameraGeneralProperties.PlayShutterSoundOnCapture, true ); photoCaptureDevice.SetProperty(KnownCameraGeneralProperties.AutoFocusRange, AutoFocusRange.Infinity); cameraCaptureSequence.Frames[0].DesiredProperties[KnownCameraPhotoProperties.SceneMode] = CameraSceneMode.Portrait; cameraCaptureSequence.Frames[0].CaptureStream = captureStream.AsOutputStream(); await photoCaptureDevice.PrepareCaptureSequenceAsync(cameraCaptureSequence); base .OnNavigatedTo(e); } public async void Capture() { await cameraCaptureSequence.StartCaptureAsync(); var b = new BitmapImage(); b.SetSource(captureStream); img1.Source = b; } private void Button_Click_1( object sender, RoutedEventArgs e) { Capture(); } } |
三、罗盘传感器
罗盘传感器用于感知地球磁场,功能主要是用于确定方向,有了它,我们可以开发类似指南针的应用。
不是每个设备都必须支持罗盘传感器的,所以我们需要在使用前判断设备是否支持。
[C#]1 2 3 4 5 | if (!Compass.IsSupported) { MessageBox.Show( "设备不支持罗盘" ); return ; } |
如果设备支持,我们还需要判断罗盘的精度,如果精度不高,需要提醒用户校对精度。当罗盘获取数据时,通过CurrentValueChanged事件处理获取的数据。
[XAML]1 2 3 4 5 | < Canvas x:Name="canvas1" Background="Black" Visibility="Collapsed"> < Image x:Name="image3" Canvas.Top="12" Canvas.Left="70" Source="Image/3.png"/> < TextBlock TextWrapping="Wrap" Width="450" Canvas.Top="240" Text=" 您的罗盘需要校验,请按照上图所示的方式移动您的手机,系统将自动完成校验过程。" /> < Button Content="完成校验" Canvas.Left="154" Canvas.Top="596" Click="Button_Click_1"/> </ Canvas > |
[C#]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | compass = new Compass(); //指定数据更新时间间隔. compass.TimeBetweenUpdates = TimeSpan.FromMilliseconds(20); //从罗盘传感器获取数据时发生 compass.CurrentValueChanged += new EventHandler<SensorReadingEventArgs<CompassReading>>(compass_CurrentValueChanged); //罗盘需要校验时发生 compass.Calibrate += new EventHandler<CalibrationEventArgs>(compass_Calibrate);<br>compass.Start(); //从传感器获取新数据时发生 void compass_CurrentValueChanged( object sender, SensorReadingEventArgs<CompassReading> e) { //获取到地球地理北极顺时值偏移角度 trueHeading = e.SensorReading.TrueHeading; } //罗盘需要校验时发生 void compass_Calibrate( object sender, CalibrationEventArgs e) { Dispatcher.BeginInvoke(() => { //罗盘需要校验,canvas1指示用户校验 canvas1.Visibility = Visibility.Visible; }); } |
四、加速度计
加速度计用于测试某个时刻设备在空间中的姿态。它与重力相关。它的取值在分为x、y、z三个方向取值,下面我们理解下这些取值含义。我们假设设备正面向上平躺在水平桌面为参照标准:
x:设备左倾的趋势越大,值越小,左倾90度时,值为-1;相反,右倾时值越大,最大为1。
y:设备后倾的趋势越大,值越小,后倾90度时,值为-1;相反,前倾时值越大,最大为1。
z:设备下倾的趋势越大,值越大,下倾180度(翻面了)时,值为1;正面朝上(不动)时,最为-1。
总的说来,x控制左右,y控制前后,z控制上下。下面我们在看看如何使用。
[C#]1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | //校验设备是否支持 if (!Accelerometer.IsSupported) { MessageBox.Show( "设备不支持重力感应" ); } var accelerometer = new Accelerometer(); accelerometer.TimeBetweenUpdates = TimeSpan.FromMilliseconds(20); //从加速度传感器获取数据时发生 accelerometer.CurrentValueChanged += new EventHandler<SensorReadingEventArgs<AccelerometerReading>>(accelerometer_CurrentValueChanged); accelerometer.Start(); //从加速度传感器获取数据时发生 void accelerometer_CurrentValueChanged( object sender, SensorReadingEventArgs<AccelerometerReading> e) { //获取到设备加速度矢量 vector3 = e.SensorReading.Acceleration; } |
五、陀螺仪
陀螺仪用于检测设备在空间中的旋转趋势。它的三个取值即为设备绕三个坐标轴的旋转速度。
x:水平左右向轴的旋转速度。
y:水平前后向轴的旋转速度。
z:垂直上下向轴的旋转速度。
然后我们看看如何调用陀螺仪。
[C#]1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | //判断设备是否支持陀螺仪 if (!Gyroscope.IsSupported) { MessageBox.Show( "设备不支持陀螺仪" ); } gyroscope = new Gyroscope(); gyroscope.TimeBetweenUpdates = TimeSpan.FromMilliseconds(20); //从陀螺仪获取数据时发生 gyroscope.CurrentValueChanged += new EventHandler<SensorReadingEventArgs<GyroscopeReading>>(gyroscope_CurrentValueChanged); //启动陀螺仪,实际使用可能启动失败需要捕获异常 gyroscope.Start(); //从陀螺仪获取数据是发生 void gyroscope_CurrentValueChanged( object sender, SensorReadingEventArgs<GyroscopeReading> e) { //获取设备绕每个轴的旋转速度 var rotationRate = e.SensorReading.RotationRate; } |
六、如何振动手机
手机的振动可以通过一句简单的API完成,在某些情况下可能还需要设置振动的世界,以及提前结束振动。下面代码演示了如何操作。
[C#]1 2 3 4 5 | VibrateController testVibrateController = VibrateController.Default; //定义振动时间 testVibrateController.Start(TimeSpan.FromSeconds(3)); //在振动时间达到前停止振动 testVibrateController.Stop(); |
出处:[http://www.cnblogs.com/lipan/]
版权声明:本文的版权归作者与博客园共有。转载时须注明原文出处以及作者,并保留原文指向型链接,不得更改原文内容。否则作者将保留追究其法律责任。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· .NET Core 中如何实现缓存的预热?
· 三行代码完成国际化适配,妙~啊~
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?