Administración de energía con la API de ciclo de vida de la aplicación

La API de ciclo de vida de la aplicación en el SDK de aplicaciones para Windows proporciona un conjunto de API de administración de energía en el espacio de nombres Microsoft.Windows.System.Power. Estas API proporcionan visibilidad sobre cómo una aplicación afecta al estado de energía del dispositivo y permiten que la aplicación tome decisiones inteligentes sobre el uso de recursos. Por ejemplo, una aplicación podría usar esta API para posponer tareas en segundo plano que consumen muchos recursos mientras el dispositivo funciona con batería.

Las API de administración de energía usan un modelo basado en devolución de llamada similar a la función PowerSettingRegisterNotification existente. El uso de un modelo de devolución de llamada amplía el alcance de la API a todas las aplicaciones, incluidas las aplicaciones en segundo plano, las aplicaciones sin encabezado y otras.

Requisitos previos

Para usar la API de ciclo de vida de la aplicación en el SDK de aplicaciones para Windows:

  1. Descargue e instale la versión experimental más reciente del SDK de Aplicaciones para Windows. Para más información, consulte Instalación de herramientas para el SDK de Aplicaciones para Windows.
  2. Siga las instrucciones para crear su primer proyecto de WinUI 3 o para usar el SDK de aplicaciones para Windows en un proyecto existente.

Suscripción y respuesta a eventos

En el ejemplo siguiente se muestra cómo suscribirse y responder a eventos de PowerManager . Este código se suscribe al evento BatteryStatusChanged durante el inicio. A continuación, la aplicación responde a los cambios comprobando el nivel de energía actual y ajustando su uso de recursos de forma adecuada. Por ejemplo, si la batería se descarga en un estado de bajo consumo, la aplicación podría aplazar cualquier trabajo en segundo plano que no sea crítico.

Nota:

Las aplicaciones pueden registrar y anular el registro de estos eventos en cualquier momento, pero la mayoría de las aplicaciones querrán establecer devoluciones de llamada en WinMain que perduren mientras la aplicación siga ejecutándose.

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
}

Configuración de la lógica de la aplicación basada en varios valores de estado

Los eventos de PowerManager son relativamente de bajo nivel y, en algunos escenarios, es posible que un único controlador de eventos al que se llame no proporcione suficiente información para que la aplicación decida cómo comportarse. En este ejemplo, se podría llamar al evento de PowerSupplyStatusChanged cuando el dispositivo se desconecta de la alimentación. En ese caso, la aplicación debe comprobar el estado de la batería actual antes de decidir cómo continuar.

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();
    }
}

Comprobación del estado de la pantalla

La clase PowerManager ofrece información sobre otros estados de dispositivo relevantes para el uso de energía de una aplicación. Por ejemplo, las aplicaciones pueden deshabilitar el procesamiento de gráficos cuando la pantalla del dispositivo está apagada.

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();
    }
}

Cancelación de la suscripción de eventos

Las aplicaciones pueden registrarse y anular el registro de las notificaciones durante su ciclo de vida. Use el sistema de administración de registros de eventos preferido de su idioma si la aplicación no necesita recibir notificaciones de estado de energía durante todo su ciclo de vida.

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