获取电池信息Get battery information

** 重要的 API **** Important APIs **

了解如何使用 Windows. Power 命名空间中的 api 获取详细的电池信息。Learn how to get detailed battery information using APIs in the Windows.Devices.Power namespace. 电池报告 (BatteryReport) 描述了某一电池或聚合电池的充电、容量和状态。A battery report (BatteryReport) describes the charge, capacity, and status of a battery or aggregate of batteries. 本主题演示了应用如何获取电池报告和更改通知。This topic demonstrates how your app can get battery reports and be notified of changes. 代码示例可从列在本主题末尾处的基本电池应用中获取。Code examples are from the basic battery app that's listed at the end of this topic.

获取聚合电池报告Get aggregate battery report

某些设备拥有多个电池,而对于每个电池在此类设备的总能量容量中所发挥的功能,并非总是显而易见。Some devices have more than one battery and it's not always obvious how each battery contributes to the overall energy capacity of the device. 这时就要用到 AggregateBattery 类了。This is where the AggregateBattery class comes in. 聚合电池表示所有连接到设备的电池控制器并可提供一个整体 BatteryReport 对象。The aggregate battery represents all battery controllers connected to the device and can provide a single overall BatteryReport object.

注意   电池类实际上对应于电池控制器。Note  A Battery class actually corresponds to a battery controller. 控制器有时连接至物理电池,而有时又连接至设备机箱,具体视设备而定。Depending on the device, sometimes the controller is attached to the physical battery and sometimes it's attached to the device enclosure. 因此,即使没有电池也可以创建电池对象。Thus, it's possible to create a battery object even when no batteries are present. 其他时候,电池对象可能为 nullOther times, the battery object may be null.

一旦有了聚合电池对象,你便可以调用 GetReport 来获取对应的 BatteryReportOnce you have an aggregate battery object, call GetReport to get the corresponding BatteryReport.

private void RequestAggregateBatteryReport()
{
    // Create aggregate battery object
    var aggBattery = Battery.AggregateBattery;

    // Get report
    var report = aggBattery.GetReport();

    // Update UI
    AddReportUI(BatteryReportPanel, report, aggBattery.DeviceId);
}

获取单个电池报告Get individual battery reports

还可以为各个电池创建 BatteryReport 对象。You can also create a BatteryReport object for individual batteries. GetDeviceSelector 方法与 FindAllAsync 方法结合使用,以获取表示已连接至设备的任何电池控制器的 DeviceInformation 对象集合。Use GetDeviceSelector with the FindAllAsync method to obtain a collection of DeviceInformation objects that represent any battery controllers that are connected to the device. 然后,通过所需 DeviceInformation 对象的 Id 属性,使用 FromIdAsync 方法来创建相应的 BatteryThen, using the Id property of the desired DeviceInformation object, create a corresponding Battery with the FromIdAsync method. 最后,调用 GetReport 以获取单个电池报告。Finally, call GetReport to get the individual battery report.

此示例显示了如何为所有连接到设备的电池创建电池报告。This example shows how to create a battery report for all batteries connected to the device.

async private void RequestIndividualBatteryReports()
{
    // Find batteries 
    var deviceInfo = await DeviceInformation.FindAllAsync(Battery.GetDeviceSelector());
    foreach(DeviceInformation device in deviceInfo)
    {
        try
        {
        // Create battery object
        var battery = await Battery.FromIdAsync(device.Id);

        // Get report
        var report = battery.GetReport();

        // Update UI
        AddReportUI(BatteryReportPanel, report, battery.DeviceId);
        }
        catch { /* Add error handling, as applicable */ }
    }
}

访问报告详细信息Access report details

BatteryReport 对象提供了大量电池信息。The BatteryReport object provides a lot of battery information. 有关详细信息,请参阅其属性的 API 参考:StatusBatteryStatus 枚举)、ChargeRateInMilliwattsDesignCapacityInMilliwattHoursFullChargeCapacityInMilliwattHoursRemainingCapacityInMilliwattHoursFor more info, see the API reference for its properties: Status (a BatteryStatus enumeration), ChargeRateInMilliwatts, DesignCapacityInMilliwattHours, FullChargeCapacityInMilliwattHours, and RemainingCapacityInMilliwattHours. 此示例显示了一些基本电池应用所使用的电池报告属性,这将在本主题后面介绍。This example shows some of the battery report properties used by the basic battery app, that's provided later in this topic.

...
TextBlock txt3 = new TextBlock { Text = "Charge rate (mW): " + report.ChargeRateInMilliwatts.ToString() };
TextBlock txt4 = new TextBlock { Text = "Design energy capacity (mWh): " + report.DesignCapacityInMilliwattHours.ToString() };
TextBlock txt5 = new TextBlock { Text = "Fully-charged energy capacity (mWh): " + report.FullChargeCapacityInMilliwattHours.ToString() };
TextBlock txt6 = new TextBlock { Text = "Remaining energy capacity (mWh): " + report.RemainingCapacityInMilliwattHours.ToString() };
...
...

请求报告更新Request report updates

当电池的充电、容量或状态发生变化时,Battery 对象会触发 ReportUpdated 事件。The Battery object triggers the ReportUpdated event when charge, capacity, or status of the battery changes. 这通常会在发生状态变化时立即发生,在发生所有其他变化时定期发生。This typically happens immediately for status changes and periodically for all other changes. 此示例显示了如何注册电池报告更新。This example shows how to register for battery report updates.

...
Battery.AggregateBattery.ReportUpdated += AggregateBattery_ReportUpdated;
...

处理报告更新Handle report updates

发生电池更新时,ReportUpdated 事件会将相应的 Battery 对象传递到事件处理程序方法。When a battery update occurs, the ReportUpdated event passes the corresponding Battery object to the event handler method. 但是,不会从 UI 线程调用此事件处理程序。However, this event handler is not called from the UI thread. 你将需要使用 Dispatcher 对象来调用任意 UI 更改,如此示例中所示。You'll need to use the Dispatcher object to invoke any UI changes, as shown in this example.

async private void AggregateBattery_ReportUpdated(Battery sender, object args)
{
    if (reportRequested)
    {

        await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
        {
            // Clear UI
            BatteryReportPanel.Children.Clear();


            if (AggregateButton.IsChecked == true)
            {
                // Request aggregate battery report
                RequestAggregateBatteryReport();
            }
            else
            {
                // Request individual battery report
                RequestIndividualBatteryReports();
            }
        });
    }
}

示例:基本电池应用Example: basic battery app

通过在 Microsoft Visual Studio 中生成下列基本电池应用来测试这些 API。Test out these APIs by building the following basic battery app in Microsoft Visual Studio. 在 Visual Studio 开始页上,单击“新建项目”****,然后在“Visual C#”>“Windows”>“通用”**** 模板下,使用“空白应用”**** 模板创建一个新应用。From the Visual Studio start page, click New Project, and then under the Visual C# > Windows > Universal templates, create a new app using the Blank App template.

接下来,打开文件 MainPage.xaml,并将下列 XML 复制到此文件中(替换其原始内容)。Next, open the file MainPage.xaml and copy the following XML into this file (replacing its original contents).

<Page
    x:Class="App1.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App1"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" >
        <StackPanel VerticalAlignment="Center" Margin="15,30,0,0" >
            <RadioButton x:Name="AggregateButton" Content="Aggregate results" GroupName="Type" IsChecked="True" />
            <RadioButton x:Name="IndividualButton" Content="Individual results" GroupName="Type" IsChecked="False" />
        </StackPanel>
        <StackPanel Orientation="Horizontal">
        <Button x:Name="GetBatteryReportButton" 
                Content="Get battery report" 
                Margin="15,15,0,0" 
                Click="GetBatteryReport"/>
        </StackPanel>
        <StackPanel x:Name="BatteryReportPanel" Margin="15,15,0,0"/>
    </StackPanel>
</Page>

如果你的应用未命名为 App1,将需要使用应用的命名空间替换上面的代码片段中类名称的第一部分。If your app isn't named App1, you'll need to replace the first part of the class name in the previous snippet with the namespace of your app. 例如,如果创建了一个名为BasicBatteryApp的项目,请将 x:Class="App1.MainPage" 替换为 x:Class="BasicBatteryApp.MainPage"For example, if you created a project named BasicBatteryApp, you'd replace x:Class="App1.MainPage" with x:Class="BasicBatteryApp.MainPage". 还应当将 xmlns:local="using:App1" 替换为 xmlns:local="using:BasicBatteryApp"You should also replace xmlns:local="using:App1" with xmlns:local="using:BasicBatteryApp".

下一步,打开你项目的 MainPage.xaml.cs 文件,用下列内容替换现有的代码。Next, open your project's MainPage.xaml.cs file and replace the existing code with the following.

using System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
using Windows.Devices.Enumeration;
using Windows.Devices.Power;
using Windows.UI.Core;

namespace App1
{
    public sealed partial class MainPage : Page
    {
        bool reportRequested = false;
        public MainPage()
        {
            this.InitializeComponent();
            Battery.AggregateBattery.ReportUpdated += AggregateBattery_ReportUpdated;
        }


        private void GetBatteryReport(object sender, RoutedEventArgs e)
        {
            // Clear UI
            BatteryReportPanel.Children.Clear();


            if (AggregateButton.IsChecked == true)
            {
                // Request aggregate battery report
                RequestAggregateBatteryReport();
            }
            else
            {
                // Request individual battery report
                RequestIndividualBatteryReports();
            }

            // Note request
            reportRequested = true;
        }

        private void RequestAggregateBatteryReport()
        {
            // Create aggregate battery object
            var aggBattery = Battery.AggregateBattery;

            // Get report
            var report = aggBattery.GetReport();

            // Update UI
            AddReportUI(BatteryReportPanel, report, aggBattery.DeviceId);
        }

        async private void RequestIndividualBatteryReports()
        {
            // Find batteries 
            var deviceInfo = await DeviceInformation.FindAllAsync(Battery.GetDeviceSelector());
            foreach(DeviceInformation device in deviceInfo)
            {
                try
                {
                // Create battery object
                var battery = await Battery.FromIdAsync(device.Id);

                // Get report
                var report = battery.GetReport();

                // Update UI
                AddReportUI(BatteryReportPanel, report, battery.DeviceId);
                }
                catch { /* Add error handling, as applicable */ }
            }
        }


        private void AddReportUI(StackPanel sp, BatteryReport report, string DeviceID)
        {
            // Create battery report UI
            TextBlock txt1 = new TextBlock { Text = "Device ID: " + DeviceID };
            txt1.FontSize = 15;
            txt1.Margin = new Thickness(0, 15, 0, 0);
            txt1.TextWrapping = TextWrapping.WrapWholeWords;

            TextBlock txt2 = new TextBlock { Text = "Battery status: " + report.Status.ToString() };
            txt2.FontStyle = Windows.UI.Text.FontStyle.Italic;
            txt2.Margin = new Thickness(0, 0, 0, 15);

            TextBlock txt3 = new TextBlock { Text = "Charge rate (mW): " + report.ChargeRateInMilliwatts.ToString() };
            TextBlock txt4 = new TextBlock { Text = "Design energy capacity (mWh): " + report.DesignCapacityInMilliwattHours.ToString() };
            TextBlock txt5 = new TextBlock { Text = "Fully-charged energy capacity (mWh): " + report.FullChargeCapacityInMilliwattHours.ToString() };
            TextBlock txt6 = new TextBlock { Text = "Remaining energy capacity (mWh): " + report.RemainingCapacityInMilliwattHours.ToString() };

            // Create energy capacity progress bar & labels
            TextBlock pbLabel = new TextBlock { Text = "Percent remaining energy capacity" };
            pbLabel.Margin = new Thickness(0,10, 0, 5);
            pbLabel.FontFamily = new FontFamily("Segoe UI");
            pbLabel.FontSize = 11;

            ProgressBar pb = new ProgressBar();
            pb.Margin = new Thickness(0, 5, 0, 0);
            pb.Width = 200;
            pb.Height = 10;
            pb.IsIndeterminate = false;
            pb.HorizontalAlignment = HorizontalAlignment.Left;

            TextBlock pbPercent = new TextBlock();
            pbPercent.Margin = new Thickness(0, 5, 0, 10);
            pbPercent.FontFamily = new FontFamily("Segoe UI");
            pbLabel.FontSize = 11;

            // Disable progress bar if values are null
            if ((report.FullChargeCapacityInMilliwattHours == null)||
                (report.RemainingCapacityInMilliwattHours == null))
            {
                pb.IsEnabled = false;
                pbPercent.Text = "N/A";
            }
            else
            {
                pb.IsEnabled = true;
                pb.Maximum = Convert.ToDouble(report.FullChargeCapacityInMilliwattHours);
                pb.Value = Convert.ToDouble(report.RemainingCapacityInMilliwattHours);
                pbPercent.Text = ((pb.Value / pb.Maximum) * 100).ToString("F2") + "%";
            }

            // Add controls to stackpanel
            sp.Children.Add(txt1);
            sp.Children.Add(txt2);
            sp.Children.Add(txt3);
            sp.Children.Add(txt4);
            sp.Children.Add(txt5);
            sp.Children.Add(txt6);
            sp.Children.Add(pbLabel);
            sp.Children.Add(pb);
            sp.Children.Add(pbPercent);
        }

        async private void AggregateBattery_ReportUpdated(Battery sender, object args)
        {
            if (reportRequested)
            {

                await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
                {
                    // Clear UI
                    BatteryReportPanel.Children.Clear();


                    if (AggregateButton.IsChecked == true)
                    {
                        // Request aggregate battery report
                        RequestAggregateBatteryReport();
                    }
                    else
                    {
                        // Request individual battery report
                        RequestIndividualBatteryReports();
                    }
                });
            }
        }
    }
}

如果你的应用未命名为 App1,将需要用你命名项目的名称为以上示例中的命名空间重命名。If your app isn't named App1, you'll need to rename the namespace in the previous example with the name you gave your project. 例如,如果你创建了一个名为BasicBatteryApp的项目,请将命名空间 App1 替换为命名空间 BasicBatteryAppFor example, if you created a project named BasicBatteryApp, you'd replace namespace App1 with namespace BasicBatteryApp.

最后,若要运行此基本电池应用:在“调试”**** 菜单上,单击“开始调试”**** 以测试该解决方案。Finally, to run this basic battery app: on the Debug menu, click Start Debugging to test the solution.

提示   若要从BatteryReport对象接收数值,请在本地计算机或外部设备上调试应用 (例如 Windows Phone) 。Tip  To receive numeric values from the BatteryReport object, debug your app on the Local Machine or an external Device (such as a Windows Phone). 在设备仿真器上调试时,BatteryReport 对象会将 null 返回到容量和比率属性。When debugging on a device emulator, the BatteryReport object returns null to the capacity and rate properties.