Windows phone 8 學習筆記(7) 設備


本節主要涉及到 Windows phone 8 手機支持的各類設備,包括相機、設備狀態,振動裝置等。還有各類感應器,包括磁力計、加速度器和陀螺儀。通過設備狀態可以獲取內存、硬件、電源、鍵盤等狀態;通過相機捕獲照片和視頻;各類感應器幫助我們獲取設備的運動狀態等。

快速導航:
    一、設備狀態
    二、相機
    三、羅盤傳感器
    四、加速度計
    五、陀螺儀
    六、如何振動手機

一、設備狀態

通過DeviceStatus 類我們可以確定設備的相關狀態信息,比如內存大小啊,固件版本啊,還有是否部署了物理鍵盤等信息,以及與電源的相關信息,當前是電池還是外部電源等。

我們通過下面的代碼展示如何獲取這些信息。

 [C#]
        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]
    <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>
[C#] 
    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]
    <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>
[C#]
    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#]
 if (!Compass.IsSupported)
 {
     MessageBox.Show("設備不支持羅盤");
     return;
 }

 

如果設備支持,我們還需要判斷羅盤的精度,如果精度不高,需要提醒用戶校對精度。當羅盤獲取數據時,通過CurrentValueChanged事件處理獲取的數據。

[XAML]
<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#]
compass = new Compass();
//指定數據更新時間間隔.
compass.TimeBetweenUpdates = TimeSpan.FromMilliseconds(20);
//從羅盤傳感器獲取數據時發生
compass.CurrentValueChanged += new EventHandler<SensorReadingEventArgs<CompassReading>>(compass_CurrentValueChanged);
//羅盤需要校驗時發生
compass.Calibrate += new EventHandler<CalibrationEventArgs>(compass_Calibrate);
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#]
//校驗設備是否支持
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#]
//判斷設備是否支持陀螺儀
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#]
            VibrateController testVibrateController = VibrateController.Default;
            //定義振動時間
            testVibrateController.Start(TimeSpan.FromSeconds(3));
            //在振動時間達到前停止振動
            testVibrateController.Stop();

 

作者:[ Lipan]
出處:[ http://www.cnblogs.com/lipan/]
版權聲明:本文的版權歸作者與博客園共有。轉載時須注明原文出處以及作者,並保留原文指向型鏈接,不得更改原文內容。否則作者將保留追究其法律責任。


免責聲明!

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



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