La gestion de l’alimentation avec l’API de cycle de vie

La gestion de l’alimentation avec l’API de cycle de vie de l’application (Windows App SDK) est disponible dans l’espace de noms Microsoft.Windows.System.Power. Ces API offrent une visibilité sur la façon dont une application affecte l’état d’alimentation de l’appareil, et elles permettent à l’application de prendre des décisions intelligentes concernant l’utilisation des ressources. Par exemple, une application pourrait utiliser cette API pour différer les tâches d’arrière-plan gourmandes en ressources lorsque l’appareil fonctionne sur batterie.

Les API de gestion de l’alimentation utilisent un modèle basé sur les rappels similaire à la fonction existante PowerSettingRegisterNotification. L’utilisation d’un modèle de rappel étend la portée de l’API à toutes les applications, y compris les applications en arrière-plan, les applications sans interface, et d’autres encore.

Prérequis

Pour utiliser l’API de cycle de vie des applications dans le Windows App SDK :

  1. Téléchargez et installez la dernière version du SDK d'application Windows. Pour plus d’informations, consultez Installer des outils pour le SDK d’application Windows.
  2. Suivez les instructions relatives à la création de votre premier projet WinUI 3 ou à l’utilisation du SDK d’application Windows dans un projet existant.

Inscription et réponse aux événements

L’exemple suivant montre comment s’abonner et répondre aux événements de PowerManager. Ce code s’abonne à l’événement BatteryStatusChanged au démarrage. L’application répond ensuite aux changements en vérifiant le niveau de batterie actuel et en ajustant son utilisation des ressources de manière appropriée. Par exemple, si la batterie se décharge à un niveau de puissance faible, l’application pourrait différer tout travail d’arrière-plan non critique.

Remarque

Les applications peuvent s’inscrire et se désinscrire de ces événements à tout moment, mais la plupart des applications voudront définir des rappels dans WinMain qui persistent tant que l’application continue de s’exécuter.

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
}

Configuration de la logique de l’application en fonction de plusieurs valeurs d’état

Les événements PowerManager sont relativement de bas niveau, et dans certains scénarios, un seul gestionnaire d’événements appelé pourrait ne pas fournir suffisamment d’informations à l’application pour décider de son comportement. Dans cet exemple, l’événement PowerSupplyStatusChanged pourrait être appelé lorsque l’appareil est déconnecté de l’alimentation. Dans ce cas, l’application doit vérifier le statut de la batterie actuel avant de décider comment procéder.

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

Vérifier l’état de l’écran

La classe PowerManager offre des informations sur d’autres états de l’appareil pertinents pour l’utilisation de l’alimentation par une application. Par exemple, les applications peuvent désactiver le traitement graphique lorsque l’écran de l’appareil est éteint.

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

Désinscription des événements

Les applications peuvent s’inscrire et se désinscrire des notifications pendant leur cycle de vie. Utilisez le système de gestion des inscriptions d’événements préféré de votre langage si votre application n’a pas besoin de recevoir des notifications d’état de l’alimentation pendant tout son cycle de vie.

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