Condividi tramite


Risparmio energia con l'API ciclo di vita dell'app

L'API ciclo di vita dell'app in Windows App SDK offre un set di API di gestione dell'alimentazione nello spazio dei nomi Microsoft.Windows.System.Power. Queste API offrono visibilità sul modo in cui un'app influisce sullo stato di alimentazione del dispositivo e consentono all'app di prendere decisioni intelligenti sull'utilizzo delle risorse. Ad esempio, un'app potrebbe usare questa API per posticipare le attività in background a uso intensivo delle risorse quando il dispositivo è alimentato a batteria.

Le API di risparmio energia usano un modello basato su callback simile alla funzione PowerSettingRegisterNotification esistente. L'uso di un modello di callback estende la copertura dell'API a tutte le app, incluse quelle in background, quelle headless e le altre.

Prerequisiti

Per usare l'API ciclo di vita dell'app nella SDK per app di Windows:

  1. Scaricare e installare la versione più recente di SDK per app di Windows. Per altre informazioni, vedere Introduzione a WinUI.
  2. Seguire le istruzioni per Creare il primo progetto WinUI 3 o per Usare Windows App SDK in un progetto esistente.

Registrazione e risposta agli eventi

L'esempio seguente mostra come registrarsi e rispondere agli eventi PowerManager. Questo codice sottoscrive l'evento BatteryStatusChanged all'avvio. L'app risponde alle modifiche controllando il livello di alimentazione corrente e regolando di conseguenza l'utilizzo delle risorse. Ad esempio, se la batteria entra in modalità basso consumo, l'app potrebbe posticipare le operazioni in background non critiche.

Nota

Le app possono registrarsi e annullare la registrazione a questi eventi in qualsiasi momento, ma probabilmente la maggior parte delle app imposterà i callback in condizione WinMain finché l'app continua a essere eseguita.

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
}

Configurazione della logica dell'app in base a più valori di stato

Gli eventi PowerManager sono di livello relativamente basso e in alcuni scenari un singolo gestore eventi chiamato potrebbe non fornire informazioni sufficienti affinché l'app decida come comportarsi. In questo esempio, l'evento PowerSupplyStatusChanged può essere chiamato quando il dispositivo è scollegato dall'alimentazione. In questo caso, l'app deve controllare lo stato corrente della batteria prima di decidere come procedere.

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

Controllo dello stato dello schermo

La classe PowerManager offre informazioni sugli altri stati del dispositivo in relazione al consumo di energia di un'app. Ad esempio, le app possono disabilitare l'elaborazione grafica quando lo schermo del dispositivo è disattivato.

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

Annullare la sottoscrizione agli eventi

Le app possono registrare e annullare la registrazione per le notifiche durante il loro ciclo di vita. Utilizzare il sistema di gestione preferito della registrazione agli eventi nella propria lingua se l'app non deve ricevere notifiche sullo stato di alimentazione durante il suo intero ciclo di vita.

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