Share via


Exercise

Task 1. Obtaining and Displaying General Information

The starting point for this exercise is the solution located in the lab installation folder under the Source\Begin folder.

The solution contains a basic Model –View–ViewModel application (see https://msdn.microsoft.com/en-us/magazine/dd419663.aspx) that already exposes the user interface required to present the various capabilities of a specific Windows® Phone 7 Codenamed “Mango” device.

If you examine the solution’s single project, you will notice several project folders:

  • Model – Contains the data model, which represents information collected about the device. This folder contains the following class definitions:
    • Information – An abstract class that represents an object, the properties of which supply information about the device
    • CapabilityInformation – An abstract class that inherits Information and adds properties describing the features available for the device
    • NetworkInformation – An abstract class that inherits Information and adds properties describing the network status and capabilities of the device
    • DeviceInformation – An abstract class that inherits Information and adds properties describing the device itself (hardware version, model name, etc.)
  • Service – Contains objects that the ViewModel will use in order to obtain the device information. This folder contains the following subfolders and interface definition:
    • IInformationProvider – Defines an entity that can supply information about the device itself, its features and its network capabilities and status
    • Fake – This subfolder contains code that presents place-holder data to display at design-time. This allows for better visualization of the user interface without having to actually run the application
    • Real – This subfolder is for code that queries the device to receive its actual capabilities
  • ViewModel – Contains the application’s ViewModel, which links the data to the user interface. This folder contains a single class:
    • DeviceInformationViewModel – This class supplies device information by presenting an IInformationProvider; it provides fake (place-holder) data at design time that is replaced with actual data at runtime

The focus of this lab is on implementing the classes contained in the Real subfolder to have them perform the desired queries.

This task shows how to get the most basic information about the device using the Microsoft.Phone.Info.DeviceStatus class, which contains information about the device’s version and make, its keyboard, memory, and power source.

Note:
 Using the DeviceStatus class requires adding a reference to the Microsoft.Phone assembly. This reference is present in Windows® Phone 7 Codenamed “Mango” application projects by default.
  1. Open the RealDeviceInformation.cs file located under the Service\Real project folder.
  2. Alter the RealDeviceInformation class to match the following code snippet:

    C#

    public class RealDeviceInformation : DeviceInformation { public override 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; } }
    Note:
    The code above places the Microsoft.Phone.Info.DeviceStatus class’s property values in the information object, allowing the user interface to display it.

Task 2. Obtaining and Displaying Network Information

This task shows how to obtain information about the device’s network status and capabilities using two classes in the Microsoft.Phone.Net.NetworkInformation namespace: DeviceNetworkInformation andNetworkInterface. These classes allow us to detect whether the device is connected to the network and allows us to see the type of connection. This information can be very useful when you write applications that depend on an active network connection or that download a considerable amount of data and you would like to do it over Wi-Fi instead of over a cellular data connection.

Note:
 Downloading large amounts of data over a cellular data connection may cause the user to use a considerable portion of his data plan. Additionally, data downloaded using a cellular connection drains the device’s battery considerably faster than when using a wireless connection.
  1. Open the RealNetworkInformation.cs file located under the Service\Real project folder.
  2. Add the following using statement to the top of the file:

    C#

    using Microsoft.Phone.Net.NetworkInformation;

  3. Alter the RealNetworkInformation class to match the following code snippet:

    C#

    public class RealNetworkInformation : NetworkInformation { public override 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; } private string GetInterfaceTypeString(Microsoft.Phone.Net. NetworkInformation.NetworkInterfaceType networkInterfaceType) { switch (networkInterfaceType) { case NetworkInterfaceType.AsymmetricDsl: return "Asymmetric DSL"; case NetworkInterfaceType.Atm: return "Atm"; case NetworkInterfaceType.BasicIsdn: return "Basic ISDN"; case NetworkInterfaceType.Ethernet: return "Ethernet"; case NetworkInterfaceType.Ethernet3Megabit: return "3 Mbit Ethernet"; case NetworkInterfaceType.FastEthernetFx: return "Fast Ethernet"; case NetworkInterfaceType.FastEthernetT: return "Fast Ethernet"; case NetworkInterfaceType.Fddi: return "FDDI"; case NetworkInterfaceType.GenericModem: return "Generic Modem"; case NetworkInterfaceType.GigabitEthernet: return "Gigabit Ethernet"; case NetworkInterfaceType.HighPerformanceSerialBus: return "High Performance Serial Bus"; case NetworkInterfaceType.IPOverAtm: return "IP Over Atm"; case NetworkInterfaceType.Isdn: return "ISDN"; case NetworkInterfaceType.Loopback: return "Loopback"; case NetworkInterfaceType.MobileBroadbandCdma: return "CDMA Broadband Connection"; case NetworkInterfaceType.MobileBroadbandGsm: return "GSM Broadband Connection"; case NetworkInterfaceType.MultiRateSymmetricDsl: return "Multi-Rate Symmetrical DSL"; case NetworkInterfaceType.None: return "None"; case NetworkInterfaceType.Ppp: return "PPP"; case NetworkInterfaceType.PrimaryIsdn: return "Primary ISDN"; case NetworkInterfaceType.RateAdaptDsl: return "Rate Adapt DSL"; case NetworkInterfaceType.Slip: return "Slip"; case NetworkInterfaceType.SymmetricDsl: return "Symmetric DSL"; case NetworkInterfaceType.TokenRing: return "Token Ring"; case NetworkInterfaceType.Tunnel: return "Tunnel"; case NetworkInterfaceType.Unknown: return "Unknown"; case NetworkInterfaceType.VeryHighSpeedDsl: return "Very High Speed DSL"; case NetworkInterfaceType.Wireless80211: return "Wireless"; default: return "Unknown"; } } }
    Note:
    You may notice that the bulk of the code is a method that translates the network interface type enumeration into more friendly strings. Notice how we used NetworkInterfaceType directly in the GetInterfaceTypeString method body to increase this snippet’s readability. Using the statement added in step 2 makes this possible.

    The RefreshData method uses the Microsoft.Phone.Net.NetworkInformation .DeviceNetworkInformation class to get information regarding the device’s connection state and the Microsoft.Phone.Net.NetworkInformation.NetworkInterface class to get the type of connection available.

Task 3. Obtaining and Displaying Hardware Sensor Capabilities

This task shows how to obtain information about a device’s sensors and camera using classes under the Microsoft.Devices and Microsoft.Devices.Sensors namespaces. These classes allow us to detect the sensors a specific device contains, as well as to detect the capabilities of its camera. If you plan to write an application that relies on accelerometer input, it is important to make sure that the device contains an accelerometer.

  1. Add a reference to the Mircosoft.Devices.Sensors assembly.
  2. Open the RealCapabilityInformation.cs file located under the Service\Real project folder.
  3. Alter the RealCapabilityInformation class to match the following code snippet:

    C#

    public class RealCapabilityInformation : CapabilityInformation { public override 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; } }
    Note:
     The code above accesses several classes under the Microsoft.Devices.Sensors namespace and tests whether or not they are available on the device: The Gyroscope, a sensor that measures the device’s orientation, the Accelerometer, a sensor that measures the device’s rate of movement in 3D space, the Compass, a sensor that detects the device’s alignment using the earth’s magnetic field, and Motion, a sensor that combines all previously mentioned sensors.

  4. Open the MainPage.xaml.cs file located under MainPage.xaml at the project root.
  5. Replace the current implementation of PanoStatus_SelectionChanged in the MainPage class with the following code:

    C#

    private void PanoStatus_SelectionChanged(object sender, 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(); } }
    Note:
    The PanoStatus_SelectionChanged method is an event handler that is called whenever the panorama control on the application’s main page changes the item it displays. Displaying the “Capabilities” item initializes the device’s camera by attaching its preview as a feed to a box on the screen. This allows you to get the camera’s supported resolution. When a different item displays, it uninitializes the camera.

  6. Add a set of additional methods to the MainPage class. These methods initialize the device’s camera to allow us to query its supported resolutions and free the camera when it is no longer required.
  7. Use the following code snippet:

    C#

    protected override 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); } protected override 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(() => { CapabilityInformation info = (App.Current.Resources["DeviceInformationViewModel"] as DeviceInformationViewModel).InformationProvider.Capabilities; ObservableCollection<string> resolutions = new ObservableCollection<string>(); foreach (Size resolution in Camera.AvailableResolutions) { resolutions.Add(String.Format("{0}x{1}", resolution.Width, resolution.Height)); } info.SupportedResolutions = resolutions; }); }

    Let us review the methods we have added:

    • OnNavigatedTo and OnNavigatedFrom initialize and uninitialized the camera when the application is sent to the background or brought back up while the “Capabilities” panorama item is displayed
    • UninitializeCamera is simply a helper method that performs the steps necessary to detach the camera preview from the user interface
    • camera_Initialized is an event handler called once the camera is initialized in order to update the ViewModel with the camera’s supported resolutions, which are only available after the camera is initialized

The application is now ready. If you run it on the emulator, it should look like the following:

Figure 1

The application displaying the simulator’s brand and hardware version

Figure 2

The network state and capabilities as detected for the emulator

Figure 3

The capabilities reported by the emulator

Figure 4

Scrolling the capabilities view further reveals the camera preview. Other views are scrollable as well.

Try running the application on your Windows Phone. Depending on the type of Windows Phone device you have, you should see different results.