Introducción a los Servicios de notificaciones de inserción de Windows (WNS)

Con los Servicios de notificaciones de inserción de Windows (WNS), los desarrolladores de terceros pueden enviar actualizaciones de notificaciones del sistema, de icono, de distintivo y sin procesar desde su propio servicio de nube. Esto proporciona un mecanismo para enviar nuevas actualizaciones a los usuarios de una manera segura y de bajo consumo.

Cómo funciona

En el siguiente diagrama se muestra el flujo de datos completo para enviar una notificación de inserción. Implica estos pasos:

  1. La aplicación solicita un canal de notificación de inserción desde WNS.
  2. Windows pide a WNS que cree un canal de notificación. Este canal se devuelve al dispositivo que realiza la llamada en forma de un identificador uniforme de recursos (URI).
  3. WNS devuelve el URI del canal de notificación a tu aplicación.
  4. La aplicación envía el URI a su propio servicio en la nube. A continuación, almacena el URI en su propio servicio en la nube para que pueda acceder al URI al enviar notificaciones. El URI es una interfaz entre su propia aplicación y su propio servicio; es su responsabilidad implementar esta interfaz con estándares web seguros y seguros.
  5. Cuando el servicio en la nube tiene una actualización que se va a enviar, notifica a WNS mediante el URI del canal. Esto se hace mediante la emisión de una solicitud HTTP POST, incluida la carga de notificación, a través de capa de sockets seguros (SSL). Este paso requiere autenticación.
  6. WNS recibe la solicitud y enruta la notificación al dispositivo adecuado.

wns data flow diagram for push notification

Registro de la aplicación y recepción de las credenciales del servicio en la nube

Para poder enviar notificaciones mediante WNS, la aplicación debe registrarse en el panel de la tienda, como se describe aquí.

Solicitud de un canal de notificación

Cuando se ejecuta una aplicación capaz de recibir notificaciones de inserción, primero debe solicitar un canal de notificación a través de CreatePushNotificationChannelForApplicationAsync. Para obtener una explicación completa y un código de ejemplo, consulte Cómo solicitar, crear y guardar un canal de notificación. Esta API devuelve un URI de canal que está vinculado de forma única a la aplicación que realiza la llamada y su icono, y a través del cual se pueden enviar todos los tipos de notificación.

Una vez que la aplicación ha creado correctamente un URI de canal, la envía a su servicio en la nube, junto con los metadatos específicos de la aplicación que se deben asociar a este URI.

Notas importantes

  • No garantizamos que el URI del canal de notificación de una aplicación siempre siga siendo el mismo. Se recomienda que la aplicación solicite un nuevo canal cada vez que se ejecute y actualice su servicio cuando cambia el URI. El desarrollador nunca debe modificar el URI del canal y considerarlo como una cadena de caja negra. En este momento, los URI de canal expiran después de 30 días. Si su aplicación de Windows 10 renovará periódicamente su canal en segundo plano, puede descargar el ejemplo de notificaciones de inserción y periódicas para Windows 8.1 y volver a usar su código fuente o el patrón que muestra.
  • El desarrollador implementa la interfaz entre el servicio en la nube y la aplicación cliente. Se recomienda que la aplicación pase por un proceso de autenticación con su propio servicio y transmita datos a través de un protocolo seguro, como HTTPS.
  • Es importante que el servicio en la nube siempre garantice que el URI del canal use el dominio "notify.windows.com". El servicio nunca debe enviar notificaciones de inserción a un canal en cualquier otro dominio. Si la devolución de llamada de la aplicación está en peligro, un atacante malintencionado podría enviar un URI de canal para suplantar WNS. Sin inspeccionar el dominio, el servicio en la nube podría revelar información a este atacante sin saberlo. El subdominio del URI del canal está sujeto a cambios y no debe tenerse en cuenta al validar el URI del canal.
  • Si el servicio en la nube intenta entregar una notificación a un canal expirado, WNS devolverá código de respuesta 410. En respuesta a ese código, el servicio ya no debe intentar enviar notificaciones a ese URI.

Autenticación del servicio en la nube

Para enviar una notificación, el servicio en la nube debe autenticarse a través de WNS. El primer paso de este proceso se produce al registrar la aplicación en el panel de Microsoft Store. Durante el proceso de registro, la aplicación recibe un identificador de seguridad de paquete (SID) y una clave secreta. El servicio en la nube usa esta información para autenticarse con WNS.

El esquema de autenticación WNS se implementa mediante el perfil de credenciales de cliente del protocolo OAuth 2.0. El servicio en la nube se autentica con WNS proporcionando sus credenciales (SID de paquete y clave secreta). A cambio, recibe un token de acceso. Este token de acceso permite que un servicio en la nube envíe una notificación. El token es necesario con cada solicitud de notificación enviada al WNS.

En un nivel alto, la cadena de información es la siguiente:

  1. El servicio en la nube envía sus credenciales a WNS a través de HTTPS siguiendo el protocolo OAuth 2.0. Esto autentica el servicio con WNS.
  2. WNS devuelve un token de acceso si la autenticación se realizó correctamente. Este token de acceso se usa en todas las solicitudes de notificación posteriores hasta que expire.

wns diagram for cloud service authentication

En la autenticación con WNS, el servicio en la nube envía una solicitud HTTP a través de capa de sockets seguros (SSL). Los parámetros se proporcionan en el formato "application/x-www-for-urlencoded". Proporcione el SID del paquete en el campo "client_id" y la clave secreta en el campo "client_secret", como se muestra en el siguiente ejemplo. Para obtener más información sobre la sintaxis, consulte la referencia solicitud de token de acceso.

Nota:

Esto es solo un ejemplo, no es un código para copiar y pegar, y usarlo correctamente como propio. 

 POST /accesstoken.srf HTTP/1.1
 Content-Type: application/x-www-form-urlencoded
 Host: https://login.live.com
 Content-Length: 211
 
 grant_type=client_credentials&client_id=ms-app%3a%2f%2fS-1-15-2-2972962901-2322836549-3722629029-1345238579-3987825745-2155616079-650196962&client_secret=Vex8L9WOFZuj95euaLrvSH7XyoDhLJc7&scope=notify.windows.com

WNS autentica el servicio en la nube y, si se ejecuta correctamente, envía una respuesta de "200 OK". El token de acceso se devuelve en los parámetros incluidos en el cuerpo de la respuesta HTTP mediante el tipo de medio "application/json". Una vez que el servicio haya recibido el token de acceso, estará listo para enviar notificaciones.

En el siguiente ejemplo se muestra una respuesta de autenticación correcta, incluido el token de acceso. Para obtener más información sobre la sintaxis, consulte Encabezados de solicitud y respuesta del servicio de notificaciones de inserción.

 HTTP/1.1 200 OK   
 Cache-Control: no-store
 Content-Length: 422
 Content-Type: application/json
 
 {
     "access_token":"EgAcAQMAAAAALYAAY/c+Huwi3Fv4Ck10UrKNmtxRO6Njk2MgA=", 
     "token_type":"bearer"
 }

Notas importantes

  • El protocolo OAuth 2.0 admitido en este procedimiento sigue la versión 16 de borrador.
  • Las solicitudes de comentarios (RFC) de OAuth usa el término "cliente" para hacer referencia al servicio en la nube.
  • Puede haber cambios en este procedimiento cuando se finalice el borrador de OAuth.
  • El token de acceso se puede reutilizar para varias solicitudes de notificación. Esto permite que el servicio en la nube se autentique una sola vez para enviar muchas notificaciones. Sin embargo, cuando expire el token de acceso, el servicio en la nube debe autenticarse de nuevo para recibir un nuevo token de acceso.

Envío de una notificación

Con el URI del canal, el servicio en la nube puede enviar una notificación cada vez que tenga una actualización para el usuario.

El token de acceso descrito anteriormente se puede reutilizar para varias solicitudes de notificación; el servidor en la nube no es necesario para solicitar un nuevo token de acceso para cada notificación. Si el token de acceso ha expirado, la solicitud de notificación devolverá un error. Se recomienda no intentar volver a enviar la notificación más de una vez si se rechaza el token de acceso. Si se produce este error, deberá solicitar un nuevo token de acceso y volver a enviar la notificación. Para obtener el código de error exacto, consulte Códigos de respuesta de notificación de inserción.

  1. El servicio en la nube realiza una solicitud HTTP POST al URI del canal. Esta solicitud debe realizarse a través de SSL y contiene los encabezados necesarios y la carga de notificación. El encabezado de autorización debe incluir el token de acceso adquirido para la autorización.

    Aquí se muestra una solicitud de ejemplo. Para obtener más información sobre la sintaxis, consulte Códigos de respuesta de notificación de inserción.

    Para obtener más información sobre cómo redactar la carga de notificación, consulte Inicio rápido: Envío de una notificación de inserción. La carga de una notificación de inserción de icono, notificación del sistema o distintivo se proporciona como contenido XML que se adhiere a su esquema de iconos adaptables definido correspondiente o esquema de iconos heredados. La carga de una notificación sin procesar no tiene una estructura especificada. Está estrictamente definida por la aplicación.

     POST https://cloud.notify.windows.com/?token=AQE%bU%2fSjZOCvRjjpILow%3d%3d HTTP/1.1
     Content-Type: text/xml
     X-WNS-Type: wns/tile
     Authorization: Bearer EgAcAQMAAAAALYAAY/c+Huwi3Fv4Ck10UrKNmtxRO6Njk2MgA=
     Host: cloud.notify.windows.com
     Content-Length: 24
    
     <body>
     ....
    
  2. WNS responde para indicar que se ha recibido la notificación y se entregará en la próxima oportunidad disponible. Sin embargo, WNS no proporciona confirmación de un extremo a otro que el dispositivo o la aplicación han recibido la notificación.

En este diagrama se muestra el flujo de datos:

wns diagram for sending a notification

Notas importantes

  • WNS no garantiza la confiabilidad ni la latencia de una notificación.
  • Las notificaciones nunca deben incluir datos confidenciales o personales.
  • Para enviar una notificación, el servicio en la nube primero debe autenticarse con WNS y recibir un token de acceso.
  • Un token de acceso solo permite que un servicio en la nube envíe notificaciones a la aplicación única para la que se creó el token. No se puede usar un token de acceso para enviar notificaciones entre varias aplicaciones. Por lo tanto, si el servicio en la nube admite varias aplicaciones, debe proporcionar el token de acceso correcto para la aplicación al insertar una notificación en cada URI del canal.
  • Cuando el dispositivo esté sin conexión, WNS almacenará de forma predeterminada uno de cada tipo de notificación (icono, distintivo, notificación del sistema) para cada URI del canal y sin notificaciones sin procesar.
  • En escenarios en los que el contenido de la notificación se personaliza al usuario, WNS recomienda que el servicio en la nube envíe inmediatamente esas actualizaciones cuando se reciban. Algunos ejemplos de este escenario son las actualizaciones de fuentes de redes sociales, las invitaciones de comunicación instantánea, las nuevas notificaciones de mensajes o las alertas. Como alternativa, puede tener escenarios en los que la misma actualización genérica se entregue con frecuencia a un gran subconjunto de los usuarios; por ejemplo, actualizaciones meteorológicas, de acciones y noticias. Las directrices de WNS especifican que la frecuencia de estas actualizaciones debe ser como máximo una cada 30 minutos. El usuario final o WNS pueden determinar que las actualizaciones rutinarias más frecuentes son abusivas.
  • La plataforma de notificaciones de Windows mantiene una conexión de datos periódica con WNS para mantener el socket activo y correcto. Si no hay ninguna aplicación que solicite ni use canales de notificación, no se creará el socket.

Expiración de las notificaciones de icono y distintivo

De forma predeterminada, las notificaciones de icono y distintivo expiran tres días después de descargarse. Cuando una notificación expira, el contenido se quita del icono o la cola y ya no se muestra al usuario. Es un procedimiento recomendado establecer una expiración (con un tiempo que tenga sentido para la aplicación) en todas las notificaciones de icono y distintivo para que el contenido del icono no persista más tiempo de lo que es relevante. Un tiempo de expiración explícito es esencial para el contenido con una duración definida. Esto también garantiza la eliminación del contenido obsoleto si el servicio en la nube deja de enviar notificaciones, o si el usuario se desconecta de la red durante un período prolongado.

El servicio en la nube puede establecer una expiración para cada notificación estableciendo el encabezado HTTP X-WNS-TTL para especificar el tiempo (en segundos) que la notificación permanecerá válida después de enviarla. Si quiere obtener más información, consulte Encabezados de respuesta y solicitud del servicio de notificaciones de inserción.

Por ejemplo, durante el día de negociación activo de un mercado de valores, puede establecer la expiración de una actualización de precios de acciones en dos veces el intervalo de envío (por ejemplo, una hora después de la recepción si envía notificaciones cada media hora). Otro ejemplo: una aplicación de noticias podría determinar que un día es una hora de expiración adecuada para una actualización diaria del icono de noticias.

Notificaciones de inserción y ahorro de batería

El ahorro de batería extiende la duración de la batería limitando la actividad en segundo plano en el dispositivo. Windows 10 permite al usuario establecer el ahorro de batería para activarse automáticamente cuando la batería cae por debajo de un umbral especificado. Cuando el ahorro de batería está encendido, la recepción de notificaciones de inserción está deshabilitada para ahorrar energía. Esta regla tiene algunas excepciones. La siguiente configuración del ahorro de batería de Windows 10 (que se encuentra en la aplicación Configuración) permite a la aplicación recibir notificaciones de inserción incluso cuando el ahorro de batería está activado.

  • Permitir notificaciones de inserción de cualquier aplicación mientras está en ahorro de batería: esta configuración permite que todas las aplicaciones reciban notificaciones de inserción mientras el ahorro de batería está activado. Tenga en cuenta que esta configuración solo se aplica a Windows 10 para las ediciones de escritorio (Home, Pro, Enterprise y Education).
  • Siempre permitidas: esta configuración permite que las aplicaciones específicas se ejecuten en segundo plano mientras el ahorro de batería está activado, incluida la recepción de notificaciones de inserción. El usuario mantiene esta lista manualmente.

No hay ninguna manera de comprobar el estado de estas dos configuraciones, pero puede comprobar el estado del ahorro de batería. En Windows 10, usa la propiedad EnergySaverStatus para comprobar el estado del ahorro de batería. La aplicación también puede usar el evento EnergySaverStatusChanged para recibir los cambios en el ahorro de batería.

Si la aplicación depende en gran medida de las notificaciones de inserción, se recomienda notificar a los usuarios que es posible que no reciban notificaciones mientras el ahorro de batería está activado y para que sea fácil ajustar la configuración del ahorro de batería. Con el esquema de URI de configuración del ahorro de batería en Windows 10, ms-settings:batterysaver-settings, puede proporcionar un vínculo cómodo a la aplicación Configuración.

Sugerencia

Al notificar al usuario la configuración de ahorro de batería, se recomienda proporcionar una forma de suprimir el mensaje en el futuro. Por ejemplo, la casilla dontAskMeAgainBox del siguiente ejemplo conserva la preferencia del usuario en LocalSettings.

A continuación, te mostramos un ejemplo de cómo comprobar si el ahorro de batería está activado en Windows 10. En este ejemplo se notifica al usuario y se inicia la aplicación Configuración para la configuración del ahorro de batería. El dontAskAgainSetting permite al usuario suprimir el mensaje si no desea recibir una notificación de nuevo.

using System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
using Windows.System;
using Windows.System.Power;
...
...
async public void CheckForEnergySaving()
{
   //Get reminder preference from LocalSettings
   bool dontAskAgain;
   var localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;
   object dontAskSetting = localSettings.Values["dontAskAgainSetting"];
   if (dontAskSetting == null)
   {  // Setting does not exist
      dontAskAgain = false;
   }
   else
   {  // Retrieve setting value
      dontAskAgain = Convert.ToBoolean(dontAskSetting);
   }
   
   // Check if battery saver is on and that it's okay to raise dialog
   if ((PowerManager.EnergySaverStatus == EnergySaverStatus.On)
         && (dontAskAgain == false))
   {
      // Check dialog results
      ContentDialogResult dialogResult = await saveEnergyDialog.ShowAsync();
      if (dialogResult == ContentDialogResult.Primary)
      {
         // Launch battery saver settings (settings are available only when a battery is present)
         await Launcher.LaunchUriAsync(new Uri("ms-settings:batterysaver-settings"));
      }

      // Save reminder preference
      if (dontAskAgainBox.IsChecked == true)
      {  // Don't raise dialog again
         localSettings.Values["dontAskAgainSetting"] = "true";
      }
   }
}
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Storage.h>
#include <winrt/Windows.System.h>
#include <winrt/Windows.System.Power.h>
#include <winrt/Windows.UI.Xaml.h>
#include <winrt/Windows.UI.Xaml.Controls.h>
#include <winrt/Windows.UI.Xaml.Navigation.h>
using namespace winrt;
using namespace winrt::Windows::Foundation;
using namespace winrt::Windows::Storage;
using namespace winrt::Windows::System;
using namespace winrt::Windows::System::Power;
using namespace winrt::Windows::UI::Xaml;
using namespace winrt::Windows::UI::Xaml::Controls;
using namespace winrt::Windows::UI::Xaml::Navigation;
...
winrt::fire_and_forget CheckForEnergySaving()
{
    // Get reminder preference from LocalSettings.
    bool dontAskAgain{ false };
    auto localSettings = ApplicationData::Current().LocalSettings();
    IInspectable dontAskSetting = localSettings.Values().Lookup(L"dontAskAgainSetting");
    if (!dontAskSetting)
    {
        // Setting doesn't exist.
        dontAskAgain = false;
    }
    else
    {
        // Retrieve setting value
        dontAskAgain = winrt::unbox_value<bool>(dontAskSetting);
    }

    // Check whether battery saver is on, and whether it's okay to raise dialog.
    if ((PowerManager::EnergySaverStatus() == EnergySaverStatus::On) && (!dontAskAgain))
    {
        // Check dialog results.
        ContentDialogResult dialogResult = co_await saveEnergyDialog().ShowAsync();
        if (dialogResult == ContentDialogResult::Primary)
        {
            // Launch battery saver settings
            // (settings are available only when a battery is present).
            co_await Launcher::LaunchUriAsync(Uri(L"ms-settings:batterysaver-settings"));
        }

        // Save reminder preference.
        if (dontAskAgainBox().IsChecked())
        {
            // Don't raise the dialog again.
            localSettings.Values().Insert(L"dontAskAgainSetting", winrt::box_value(true));
        }
    }
}

Este es el XAML del ContentDialog destacado en este ejemplo.

<ContentDialog x:Name="saveEnergyDialog"
               PrimaryButtonText="Open battery saver settings"
               SecondaryButtonText="Ignore"
               Title="Battery saver is on."> 
   <StackPanel>
      <TextBlock TextWrapping="WrapWholeWords">
         <LineBreak/><Run>Battery saver is on and you may 
          not receive push notifications.</Run><LineBreak/>
         <LineBreak/><Run>You can choose to allow this app to work normally
         while in battery saver, including receiving push notifications.</Run>
         <LineBreak/>
      </TextBlock>
      <CheckBox x:Name="dontAskAgainBox" Content="OK, got it."/>
   </StackPanel>
</ContentDialog>