與眾不同 windows phone (20) - Device(設備)之位置服務(GPS 定位), FM 收音機, 麥克風, 震動器
作者:webabcd
介紹
與眾不同 windows phone 7.5 (sdk 7.1) 之設備
- 位置服務(GPS 定位)
- FM 收音機
- 麥克風
- 震動器
示例
1、演示如何使用位置服務(GPS 定位)
GpsDemo.xaml
<phone:PhoneApplicationPage x:Class="Demo.Device.GpsDemo" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone" xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" FontFamily="{StaticResource PhoneFontFamilyNormal}" FontSize="{StaticResource PhoneFontSizeNormal}" Foreground="{StaticResource PhoneForegroundBrush}" SupportedOrientations="Portrait" Orientation="Portrait" mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480" shell:SystemTray.IsVisible="True"> <Grid x:Name="LayoutRoot" Background="Transparent"> <StackPanel Orientation="Vertical"> <!--跳轉到隱私聲明頁(如果使用了 GPS 則必須要有“隱私聲明”,否則不會通過微軟的審核)--> <HyperlinkButton Content="隱私聲明" NavigateUri="/Device/PrivacyPolicy.xaml" FontSize="{StaticResource PhoneFontSizeNormal}" Margin="10,6" HorizontalAlignment="Left" /> <TextBlock Name="lblStatus" /> <Button Name="btnLow" Content="低精度定位" Click="btnLow_Click" /> <Button Name="btnHigh" Content="高精度定位" Click="btnHigh_Click" /> <Button Name="btnClose" Content="關閉定位" Click="btnClose_Click" /> <TextBlock Name="lblMsg" /> </StackPanel> </Grid> </phone:PhoneApplicationPage>
GpsDemo.xaml.cs
/* * 演示如何使用位置服務(GPS 定位) * * GeoCoordinateWatcher - 用於提供地理位置數據 * Start() - 啟動位置服務 * TryStart(bool suppressPermissionPrompt, TimeSpan timeout) - 嘗試啟動位置服務,返回值為位置服務是否啟動成功 * suppressPermissionPrompt - 是否禁用權限提示對話框。true為禁用,false為啟用 * timeout - 啟動位置服務的超時時間 * Stop() - 停止位置服務 * * DesiredAccuracy - 指定提供位置服務的精度級別(System.Device.Location.GeoPositionAccuracy 枚舉) * Default - 低精度定位 * High - 高精度定位 * Permission - 位置提供程序的權限,只讀(System.Device.Location.GeoPositionPermission 枚舉) * Unknown - 權限未知 * Granted - 授予定位權限 * Denied - 拒絕定位權限 * Status - 位置服務的狀態(System.Device.Location.GeoPositionStatus 枚舉) * Ready - 已經准備好相關數據 * Initializing - 位置提供程序初始化中 * NoData - 無有效數據 * Disabled - 位置服務不可用 * Position - 定位的位置數據,只讀(Position.Location 是一個 System.Device.Location.GeoCoordinate 類型的對象) * MovementThreshold - 自上次觸發 PositionChanged 事件后,位置移動了此屬性指定的距離后再次觸發 PositionChanged 事件(單位:米) * 此屬性默認值為 0,即位置的任何改變都會觸發 PositionChanged 事件 * * PositionChanged - 經緯度數據發生改變時所觸發的事件(系統會根據 MovementThreshold 屬性的值來決定何時觸發 PositionChanged 事件,當位置服務被打開后第一次得到位置數據時也會觸發此事件) * StatusChanged - 位置服務的狀態發生改變時所觸發的事件 * * * * GeoCoordinate - 地理坐標 * Altitude - 海拔高度(單位:米) * VerticalAccuracy - 海拔高度的精度(單位:米) * Longitude - 經度 * Latitude - 緯度 * IsUnknown - 是否無經緯度數據。true代表無數據,false代表有數據 * HorizontalAccuracy - 經緯度的精度(單位:米) * Course - 行進方向(單位:度,正北為 0 度) * Speed - 行進速度(單位:米/秒) */ using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using Microsoft.Phone.Controls; using System.Device.Location; using System.Threading; namespace Demo.Device { public partial class GpsDemo : PhoneApplicationPage { private GeoCoordinateWatcher _watcher; public GpsDemo() { InitializeComponent(); _watcher = new GeoCoordinateWatcher(); } private void btnLow_Click(object sender, RoutedEventArgs e) { // 開啟低精度位置服務 StartLocationService(GeoPositionAccuracy.Default); } private void btnHigh_Click(object sender, RoutedEventArgs e) { // 開啟高精度位置服務 StartLocationService(GeoPositionAccuracy.High); } private void btnClose_Click(object sender, RoutedEventArgs e) { StopLocationService(); } private void StartLocationService(GeoPositionAccuracy accuracy) { _watcher = new GeoCoordinateWatcher(accuracy); // 位置每移動 20 米觸發一次 PositionChanged 事件 _watcher.MovementThreshold = 20; _watcher.StatusChanged += new EventHandler<GeoPositionStatusChangedEventArgs>(_watcher_StatusChanged); _watcher.PositionChanged += new EventHandler<GeoPositionChangedEventArgs<GeoCoordinate>>(_watcher_PositionChanged); lblStatus.Text = "GPS 服務啟動中..."; new Thread((x) => { // 啟動 GPS 服務,會阻塞 UI 線程,所以要在后台線程處理 if (!_watcher.TryStart(true, TimeSpan.FromSeconds(30))) { Dispatcher.BeginInvoke(delegate { lblStatus.Text = "GPS 服務無法啟動"; }); } }).Start(); } private void StopLocationService() { if (_watcher != null) _watcher.Stop(); lblStatus.Text = "GPS 服務已關閉"; } void _watcher_PositionChanged(object sender, GeoPositionChangedEventArgs<GeoCoordinate> e) { // 在 UI 上顯示經緯度信息 Dispatcher.BeginInvoke(delegate { lblMsg.Text = "經度: " + e.Position.Location.Longitude.ToString("0.000"); lblMsg.Text += Environment.NewLine; lblMsg.Text += "緯度: " + e.Position.Location.Latitude.ToString("0.000"); }); } void _watcher_StatusChanged(object sender, GeoPositionStatusChangedEventArgs e) { // 在 UI 上顯示 GPS 服務狀態 Dispatcher.BeginInvoke(delegate { switch (e.Status) { case GeoPositionStatus.Disabled: if (_watcher.Permission == GeoPositionPermission.Denied) lblStatus.Text = "GPS 服務拒絕訪問"; else lblStatus.Text = "GPS 服務不可用"; break; case GeoPositionStatus.Initializing: lblStatus.Text = "GPS 服務初始化"; break; case GeoPositionStatus.NoData: lblStatus.Text = "GPS 無有效數據"; break; case GeoPositionStatus.Ready: lblStatus.Text = "GPS 接收數據中"; break; } }); } } }
2、演示如何使用 FM 收音機
FMRadioDemo.xaml
<phone:PhoneApplicationPage x:Class="Demo.Device.FMRadioDemo" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone" xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" FontFamily="{StaticResource PhoneFontFamilyNormal}" FontSize="{StaticResource PhoneFontSizeNormal}" Foreground="{StaticResource PhoneForegroundBrush}" SupportedOrientations="Portrait" Orientation="Portrait" mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480" shell:SystemTray.IsVisible="True"> <Grid x:Name="LayoutRoot" Background="Transparent"> <StackPanel Orientation="Vertical"> <TextBlock Name="lblStatus" /> <Button Name="btnStart" Content="打開收音機" Click="btnStart_Click" /> <Button Name="btnClose" Content="關閉收音機" Click="btnClose_Click" /> <TextBlock Name="lblMsg" /> </StackPanel> </Grid> </phone:PhoneApplicationPage>
FMRadioDemo.xaml.cs
/* * 演示如何使用 FM 收音機 * * FMRadio - 用於操作 FM 收音機的類 * Instance - 返回 FMRadio 實例 * CurrentRegion - 收音機的區域信息(Microsoft.Devices.Radio.RadioRegion 枚舉) * UnitedStates - 美國 * Japan - 日本 * Europe - 其他地區 * Frequency - 指定 FM 調頻的頻率 * PowerMode - 打開或關閉收音機(Microsoft.Devices.Radio.RadioPowerMode 枚舉) * On - 打開收音機 * Off - 關閉收音機 * SignalStrength - 當前頻率的信號強度(RSSI - Received Signal Strength Indication) */ using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using Microsoft.Phone.Controls; using Microsoft.Devices.Radio; using System.Windows.Threading; using System.Threading; namespace Demo.Device { public partial class FMRadioDemo : PhoneApplicationPage { private FMRadio _radio; private DispatcherTimer _timer; public FMRadioDemo() { InitializeComponent(); // 實例化 FMRadio,收聽 90.5 頻率 _radio = FMRadio.Instance; _radio.CurrentRegion = RadioRegion.Europe; _radio.Frequency = 90.5; _timer = new DispatcherTimer(); _timer.Interval = TimeSpan.FromMilliseconds(100); _timer.Tick += new EventHandler(_timer_Tick); _timer.Start(); if (_radio.PowerMode == RadioPowerMode.On) lblStatus.Text = "收音機已打開"; else lblStatus.Text = "收音機已關閉"; } void _timer_Tick(object sender, EventArgs e) { // 實時顯示當前頻率及信號強度 lblMsg.Text = "調頻:" + _radio.Frequency; lblMsg.Text += Environment.NewLine; lblMsg.Text += "RSSI:" + _radio.SignalStrength.ToString("0.00"); } // 打開收音機 private void btnStart_Click(object sender, RoutedEventArgs e) { lblStatus.Text = "收音機打開中。。。"; // 首次啟動收音機可能需要多達 3 秒的時間,以后再啟動收音機則會在 100 毫秒以內,所以建議在后台線程打開收音機 new Thread((x) => { _radio.PowerMode = RadioPowerMode.On; Dispatcher.BeginInvoke(delegate { lblStatus.Text = "收音機已打開"; }); }).Start(); } // 關閉收音機 private void btnClose_Click(object sender, RoutedEventArgs e) { _radio.PowerMode = RadioPowerMode.Off; lblStatus.Text = "收音機已關閉"; } } }
3、演示如何使用麥克風
MicrophoneDemo.xaml
<phone:PhoneApplicationPage x:Class="Demo.Device.MicrophoneDemo" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone" xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" FontFamily="{StaticResource PhoneFontFamilyNormal}" FontSize="{StaticResource PhoneFontSizeNormal}" Foreground="{StaticResource PhoneForegroundBrush}" SupportedOrientations="Portrait" Orientation="Portrait" mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480" shell:SystemTray.IsVisible="True"> <Grid x:Name="LayoutRoot" Background="Transparent"> <StackPanel Orientation="Vertical"> <TextBlock Name="lblMsg" /> <Button Name="btnRecord" Content="錄音" Click="btnRecord_Click" /> <Button Name="btnPlay" Content="播放" Click="btnPlay_Click" /> <Button Name="btnStop" Content="停止" Click="btnStop_Click" /> </StackPanel> </Grid> </phone:PhoneApplicationPage>
MicrophoneDemo.xaml.cs
/* * 演示如何使用麥克風進行錄音 * * Microphone - 用於捕獲麥克風音頻的類 * Default - 返回默認的 Microphone 實例 * All - 返回設備的全部 Microphone 實例集合 * SampleRate - 獲取音頻的采樣率 * State - Microphone 的狀態(Microsoft.Xna.Framework.Audio.MicrophoneState 枚舉) * Started - 正在捕獲音頻 * Stopped - 已經停止工作 * BufferDuration - 麥克風捕獲音頻時的緩沖時長 * * BufferReady - 當麥克風捕獲的音頻時長達到 BufferDuration 設置的值后所觸發的事件 * * GetData(byte[] buffer) - 將麥克風最近捕獲到的音頻數據寫入到指定的緩沖區 * GetSampleSizeInBytes(TimeSpan duration) - 麥克風捕獲音頻,根據音頻時長返回音頻字節數 * GetSampleDuration(int sizeInBytes) - 麥克風捕獲音頻,根據音頻字節數返回音頻時長 * Start() - 開始捕獲 * Stop() - 停止捕獲 */ using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using Microsoft.Phone.Controls; using Microsoft.Xna.Framework.Audio; using System.IO; using System.Threading; using Microsoft.Xna.Framework; namespace Demo.Device { public partial class MicrophoneDemo : PhoneApplicationPage { // silverlight 和 xna 混合編程時,所需要用到的計時器 private GameTimer _timer; private Microphone _microphone = Microphone.Default; private SoundEffectInstance _soundInstance; // 用於播放音頻數據 private byte[] _buffer; // 每一片錄音數據的緩沖區 private MemoryStream _stream = new MemoryStream(); // 整個錄音數據的內存流 public MicrophoneDemo() { InitializeComponent(); _timer = new GameTimer(); // 指定計時器每 1/30 秒執行一次,即幀率為 30 fps _timer.UpdateInterval = TimeSpan.FromTicks(333333); // 每次幀更新時所觸發的事件 _timer.FrameAction += FrameworkDispatcherFrameAction; _timer.Start(); _microphone.BufferReady += new EventHandler<EventArgs>(_microphone_BufferReady); } private void FrameworkDispatcherFrameAction(object sender, EventArgs e) { // 當使用 silverlight 和 xna 混合編程時,每次幀更新時都需要調用 FrameworkDispatcher.Update() FrameworkDispatcher.Update(); } void _microphone_BufferReady(object sender, EventArgs e) { // 當錄音的緩沖被填滿后,將數據寫入緩沖區 _microphone.GetData(_buffer); // 將緩沖區中的數據寫入內存流 _stream.Write(_buffer, 0, _buffer.Length); } private void btnRecord_Click(object sender, RoutedEventArgs e) { if (lblMsg.Text != "錄音中") { // 設置錄音的緩沖時長為 0.5 秒 _microphone.BufferDuration = TimeSpan.FromMilliseconds(500); // 設置錄音用的緩沖區的大小 _buffer = new byte[_microphone.GetSampleSizeInBytes(_microphone.BufferDuration)]; // 初始化內存流 _stream.SetLength(0); _microphone.Start(); lblMsg.Text = "錄音中"; } } private void btnPlay_Click(object sender, RoutedEventArgs e) { if (_stream.Length > 0) { // 播放錄音 Thread soundThread = new Thread(new ThreadStart(playSound)); soundThread.Start(); lblMsg.Text = "播放錄音"; } } private void btnStop_Click(object sender, RoutedEventArgs e) { if (_microphone.State == MicrophoneState.Started) { // 停止錄音 _microphone.Stop(); lblMsg.Text = "停止錄音"; } else if (_soundInstance.State == SoundState.Playing) { // 停止播放錄音 _soundInstance.Stop(); lblMsg.Text = "停止播放錄音"; } } private void playSound() { // 播放內存流中的音頻 SoundEffect sound = new SoundEffect(_stream.ToArray(), _microphone.SampleRate, AudioChannels.Mono); _soundInstance = sound.CreateInstance(); _soundInstance.Play(); } } }
4、演示如何使用震動器
VibrationDemo.xaml
<phone:PhoneApplicationPage x:Class="Demo.Device.VibrationDemo" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone" xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" FontFamily="{StaticResource PhoneFontFamilyNormal}" FontSize="{StaticResource PhoneFontSizeNormal}" Foreground="{StaticResource PhoneForegroundBrush}" SupportedOrientations="Portrait" Orientation="Portrait" mc:Ignorable="d" d:DesignHeight="768" d:DesignWidth="480" shell:SystemTray.IsVisible="True"> <Grid x:Name="LayoutRoot" Background="Transparent"> <StackPanel Orientation="Vertical"> <Button Name="btnStart" Content="開始震動" Click="btnStart_Click" /> <Button Name="btnStop" Content="停止震動" Click="btnStop_Click" /> </StackPanel> </Grid> </phone:PhoneApplicationPage>
VibrationDemo.xaml.cs
/* * 演示如何使用震動器 * * VibrateController - 用於控制震動器 * Default - 獲取 VibrateController 實例 * Start(TimeSpan duration) - 指定震動時長,並使設備震動。有效時長在 0 - 5 秒之間,否則會拋出異常 * Stop() - 停止設備的震動 */ using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using Microsoft.Phone.Controls; using Microsoft.Devices; namespace Demo.Device { public partial class VibrationDemo : PhoneApplicationPage { public VibrationDemo() { InitializeComponent(); } private void btnStart_Click(object sender, RoutedEventArgs e) { // 震動 5 秒 VibrateController.Default.Start(TimeSpan.FromMilliseconds(5 * 1000)); } private void btnStop_Click(object sender, RoutedEventArgs e) { // 停止震動 VibrateController.Default.Stop(); } } }
OK
[源碼下載]