Управление питанием с помощью API жизненного цикла приложения

api жизненного цикла приложений в пакете SDK для приложений Windows предоставляет набор api-интерфейсов управления питанием в Microsoft. Windows. Пространство имен System. Power . Эти API предоставляют сведения о том, как приложение влияет на состояние электропитания устройства, и позволяет приложению принимать разумные решения об использовании ресурсов. Например, приложение может использовать этот API для отсрочки ресурсоемких фоновых задач, когда устройство работает от аккумулятора.

API-интерфейсы управления питанием используют модель на основе обратного вызова, аналогичную существующей функции поверсеттингрегистернотификатион . Использование модели обратного вызова расширяет возможности API для всех приложений, включая фоновые приложения, приложения без монитора и т. д.

Предварительные требования

чтобы использовать API жизненного цикла приложений в пакете SDK для приложений Windows:

  1. скачайте и установите последнюю версию пакета SDK для приложений Windows. Дополнительные сведения см. в статье Установка инструментов для Windows App SDK.
  2. следуйте инструкциям, чтобы создать первый проект винуи 3 или использовать Windows пакет SDK для приложений в существующем проекте.

Подписка и реагирование на события

В следующем примере показано, как подписываться на события поверманажер и реагировать на них. Этот код подписывается на событие баттеристатусчанжед во время запуска. Затем приложение реагирует на изменения, проверяя текущий уровень питания и настраивая его использование ресурсов соответствующим образом. Например, если батарея оплачивается с низким энергопотреблением, приложение может отложить любую некритическую фоновую работу.

Примечание

Приложения могут регистрироваться и отменять регистрацию этих событий в любое время, но большинство приложений захочет установить обратные вызовы в WinMain этом случае, пока приложение продолжает работать.

BOOL bWorkInProgress;
winrt::event_token batteryToken;
winrt::event_token powerToken;
winrt::event_token powerSourceToken;
winrt::event_token chargeToken;
winrt::event_token dischargeToken;

void RegisterPowerManagerCallbacks()
{
    batteryToken = PowerManager::BatteryStatusChanged([&](
        const auto&, winrt::Windows::Foundation::IInspectable obj) { OnBatteryStatusChanged(); });
    powerToken = PowerManager::PowerSupplyStatusChanged([&](
        const auto&, winrt::Windows::Foundation::IInspectable obj) { OnPowerSupplyStatusChanged(); });
    powerSourceToken = PowerManager::PowerSourceKindChanged([&](
        const auto&, winrt::Windows::Foundation::IInspectable obj) { OnPowerSourceKindChanged(); });
    chargeToken = PowerManager::RemainingChargePercentChanged([&](
        const auto&, winrt::Windows::Foundation::IInspectable obj) { OnRemainingChargePercentChanged(); });
    dischargeToken = PowerManager::RemainingDischargeTimeChanged([&](
        const auto&, winrt::Windows::Foundation::IInspectable obj) { OnRemainingDischargeTimeChanged(); });

    if (batteryToken && powerToken && powerSourceToken && chargeToken && dischargeToken)
    {
        OutputMessage(L"Successfully registered for state notifications");
    }
    else
    {
        OutputMessage(L"Failed to register for state notifications");
    }
}

void OnBatteryStatusChanged()
{
    const size_t statusSize = 16;
    WCHAR szStatus[statusSize];
    wmemset(&(szStatus[0]), 0, statusSize);

    BatteryStatus batteryStatus = PowerManager::BatteryStatus();
    int remainingCharge = PowerManager::RemainingChargePercent();
    switch (batteryStatus)
    {
    case BatteryStatus::Charging:
        wcscpy_s(szStatus, L"Charging");
        break;
    case BatteryStatus::Discharging:
        wcscpy_s(szStatus, L"Discharging");
        break;
    case BatteryStatus::Idle:
        wcscpy_s(szStatus, L"Idle");
        break;
    case BatteryStatus::NotPresent:
        wcscpy_s(szStatus, L"NotPresent");
        break;
    }

    OutputFormattedMessage(
        L"Battery status changed: %s, %d%% remaining", 
        szStatus, remainingCharge);
    DetermineWorkloads();
}

void OnPowerSupplyStatusChanged()
{
//...etc
}

Настройка логики приложения на основе нескольких значений состояния

События поверманажер относительно низкого уровня, и в некоторых сценариях один из вызываемых обработчиков событий может не предоставить достаточно информации, чтобы приложение могло решить, как они ведут себя. В этом примере событие поверсупплистатусчанжед может вызываться, когда устройство отключается от питания. В этом случае приложение должно проверить текущее состояние аккумулятора, прежде чем принимать решение о дальнейших действиях.

void DetermineWorkloads()
{
    BatteryStatus batteryStatus = PowerManager::BatteryStatus();
    int remainingCharge = PowerManager::RemainingChargePercent();
    PowerSupplyStatus powerStatus = PowerManager::PowerSupplyStatus();
    PowerSourceKind powerSource = PowerManager::PowerSourceKind();

    if ((powerSource == PowerSourceKind::DC 
        && batteryStatus == BatteryStatus::Discharging 
        && remainingCharge < 25)
        || (powerSource == PowerSourceKind::AC
        && powerStatus == PowerSupplyStatus::Inadequate))
    {
        // The device is not in a good battery/power state, 
        // so we should pause any non-critical work.
        PauseNonCriticalWork();
    }
    else if ((batteryStatus != BatteryStatus::Discharging && remainingCharge > 75)
        && powerStatus != PowerSupplyStatus::Inadequate)
    {
        // The device is in good battery/power state,
        // so let's kick of some high-power work.
        StartPowerIntensiveWork();
    }
}

Проверить состояние экрана

Класс поверманажер предлагает сведения о других состояниях устройств, относящихся к энергопотреблению приложения. Например, приложения могут отключить обработку графики при выключенном дисплее устройства.

void OnDisplayStatusChanged()
{
    const size_t statusSize = 16;
    WCHAR szStatus[statusSize];
    wmemset(&(szStatus[0]), 0, statusSize);

    DisplayStatus displayStatus = PowerManager::DisplayStatus();
    switch (displayStatus)
    {
    case DisplayStatus::Dimmed:
        wcscpy_s(szStatus, L"Dimmed");
        break;
    case DisplayStatus::Off:
        wcscpy_s(szStatus, L"Off");
        break;
    case DisplayStatus::On:
        wcscpy_s(szStatus, L"On");
        break;
    }

    OutputFormattedMessage(
        L"Display status changed: %s", szStatus);
    if (displayStatus == DisplayStatus::Off)
    {
        // The screen is off, let's stop rendering foreground graphics,
        // and instead kick off some background work now.
        StopUpdatingGraphics();
        StartDoingBackgroundWork();
    }
}

Отмена подписки на события

Приложения могут регистрироваться и отменять регистрацию для получения уведомлений в течение жизненного цикла. Используйте предпочтительную систему управления регистрацией событий языка, если приложению не требуется получать уведомления о состоянии питания в течение всего жизненного цикла.

void UnregisterPowerManagerCallbacks()
{
    OutputMessage(L"Unregistering state notifications");
    PowerManager::BatteryStatusChanged(batteryToken);
    PowerManager::PowerSupplyStatusChanged(powerToken);
    PowerManager::PowerSourceKindChanged(powerSourceToken);
    PowerManager::RemainingChargePercentChanged(chargeToken);
    PowerManager::RemainingDischargeTimeChanged(dischargeToken);
}