與眾不同 windows phone (20) - Device(設備)之位置服務(GPS 定位), FM 收音機, 麥克風, 震動器


[索引頁]
[源碼下載]


與眾不同 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
[源碼下載]


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM