Compartir a través de


Adición de características de demostración comercial (RDX) a la aplicación

Incluya un modo de demostración comercial en su aplicación de Windows para que los clientes que prueben equipos y dispositivos en el área de ventas puedan comenzar de inmediato.

Cuando los clientes están en una tienda minorista, esperan poder probar demostraciones de equipos y dispositivos. A menudo pasan un fragmento considerable de su tiempo jugando con aplicaciones a través de la experiencia de demostración comercial de (RDX).

Puedes configurar la aplicación para proporcionar experiencias diferentes mientras normales o modos de minoristas. Por ejemplo, si la aplicación comienza con un proceso de configuración, puede omitirlo en modo comercial y rellenar previamente la aplicación con datos de ejemplo y la configuración predeterminada para que puedan saltar directamente.

Desde la perspectiva de nuestros clientes, solo hay una aplicación. Para ayudar a los clientes a distinguir entre los dos modos, se recomienda que mientras la aplicación esté en modo comercial, muestra la palabra "Retail" destacadamente en la barra de título o en una ubicación adecuada.

Además de los requisitos de Microsoft Store para las aplicaciones, las aplicaciones compatibles con RDX también deben ser compatibles con los procesos de configuración, limpieza y actualización de RDX para garantizar que los clientes tengan una experiencia positiva coherente en la tienda minorista.

Principios de diseño

  • Mostrar su mejor. Usa la experiencia de demostración en el punto de venta para mostrar por qué tu aplicación es excelente. Es probable que esta sea la primera vez que tu cliente vea tu aplicación, así que muéstrales la mejor parte.

  • Muéstralo rápido. Los clientes pueden ser impacientes: cuanto más rápido pueda experimentar un usuario el valor real de la aplicación, mejor.

  • Mantenga la historia sencilla. La experiencia de demostración comercial es una presentación breve del valor de tu aplicación.

  • Centrarse en la experiencia. Conceda al usuario tiempo para resúmenes del contenido. Aunque llevarlos rápidamente a la mejor parte es importante, diseñar pausas adecuadas puede ayudarles a disfrutar completamente de la experiencia.

Requisitos técnicos

Como las aplicaciones compatibles con RDX están diseñadas para mostrar lo mejor de la aplicación a los clientes minoristas, deben cumplir los requisitos técnicos y cumplir las regulaciones de privacidad que Microsoft Store tiene para todas las aplicaciones de experiencia de demostración comercial.

Esto se puede usar como una lista de comprobación para ayudarle a prepararse para el proceso de validación y para proporcionar claridad en el proceso de prueba. Tenga en cuenta que estos requisitos deben mantenerse, no solo para el proceso de validación, sino para toda la duración de la aplicación de experiencia de demostración comercial; siempre que la aplicación permanezca ejecutándose en los dispositivos de demostración comercial.

Requisitos críticos

Las aplicaciones compatibles con RDX que no cumplen estos requisitos críticos se quitarán de todos los dispositivos de demostración comercial lo antes posible.

  • No solicite información de identificación personal (PII). Esto incluye información de inicio de sesión, información de cuenta Microsoft o detalles de contacto.

  • Experiencia sin errores. La aplicación debe ejecutarse sin errores. Además, no se deben mostrar elementos emergentes o notificaciones de error a los clientes que usan los dispositivos de demostración comercial. Los errores se reflejan negativamente en la aplicación misma, la marca de su empresa, la marca del dispositivo, la marca del fabricante del dispositivo y la marca de Microsoft.

  • Las aplicaciones de pago deben tener un modo de prueba. La aplicación debe ser gratuita o incluir un modo de evaluación. Los clientes no buscan pagar una experiencia en una tienda minorista.

Requisitos de alta prioridad

Las aplicaciones compatibles con RDX que no cumplen estos requisitos de prioridad alta deben investigarse para una corrección inmediatamente. Si no se encuentra ninguna corrección inmediata, esta aplicación se puede quitar de todos los dispositivos de demostración comercial.

  • experiencia memorable sin conexión. La aplicación debe demostrar una excelente experiencia sin conexión, ya que aproximadamente 50% de los dispositivos están sin conexión en ubicaciones comerciales. Esto es para asegurarse de que los clientes que interactúan con la aplicación sin conexión todavía pueden tener una experiencia significativa y positiva.

  • Experiencia de contenido actualizada. La aplicación nunca debe solicitar actualizaciones cuando esté en línea. Si se necesitan actualizaciones, se deben realizar de forma silenciosa.

  • Ninguna comunicación anónima. Dado que un cliente que usa un dispositivo de demostración comercial es un usuario anónimo, no debe poder enviar mensajes ni compartir contenido desde el dispositivo.

  • Ofrezca experiencias coherentes mediante el proceso de limpieza. Cada cliente debe tener la misma experiencia cuando pase a un dispositivo de demostración comercial. Su aplicación debe usar proceso de limpieza para volver al mismo estado predeterminado después de cada uso. No queremos que el siguiente cliente vea lo que el último cliente ha dejado atrás. Esto incluye marcadores, logros y elementos desbloqueables.

  • Contenido apropiado para la edad. Todo el contenido de la aplicación debe asignarse a una categoría adolescente o de clasificación inferior. Para obtener más información, consulta Calificar tu aplicación por IARC y calificaciones de ESRB.

Requisitos de prioridad media

El equipo de la Tienda de Windows puede ponerse en contacto con los desarrolladores directamente para establecer una conversación sobre cómo solucionar estos problemas.

  • Capacidad de ejecutarse correctamente en una gama de dispositivos. Las aplicaciones deben ejecutarse bien en todos los dispositivos, incluidos los dispositivos con especificaciones de gama baja. Si la aplicación está instalada en dispositivos que no cumplen las especificaciones mínimas, la aplicación debe informar claramente al usuario sobre esto. Se deben conocer los requisitos mínimos del dispositivo para que la aplicación siempre se pueda ejecutar con un alto rendimiento.

  • Cumplir los requisitos de tamaño de la aplicación de la tienda minorista. La aplicación debe ser inferior a 800 MB. Póngase en contacto directamente con el equipo de la Tienda comercial de Windows para obtener más información si la aplicación compatible con RDX no cumple los requisitos de tamaño.

RETAILInfo API: Preparación del código para el modo de demostración

ModoDemoActivado

La propiedad IsDemoModeEnabled de la clase de utilidad RetailInfo, que forma parte del espacio de nombres Windows.System.Profile en el SDK de Windows 10 y Windows 11, se utiliza como un indicador booleano para especificar en qué ruta de código se ejecuta su aplicación: el modo normal o el modo minorista.

using Windows.Storage;

StorageFolder folder = ApplicationData.Current.LocalFolder;

if (Windows.System.Profile.RetailInfo.IsDemoModeEnabled) 
{
    // Use the demo specific directory
    folder = await folder.GetFolderAsync("demo");
}

StorageFile file = await folder.GetFileAsync("hello.txt");
// Now read from file
using namespace Windows::Storage;

StorageFolder^ localFolder = ApplicationData::Current->LocalFolder;

if (Windows::System::Profile::RetailInfo::IsDemoModeEnabled) 
{
    // Use the demo specific directory
    create_task(localFolder->GetFolderAsync("demo").then([this](StorageFolder^ demoFolder)
    {
        return demoFolder->GetFileAsync("hello.txt");
    }).then([this](task<StorageFile^> fileTask)
    {
        StorageFile^ file = fileTask.get();
    });
    // Do something with file
}
else
{
    create_task(localFolder->GetFileAsync("hello.txt").then([this](StorageFile^ file)
    {
        // Do something with file
    });
}
if (Windows.System.Profile.retailInfo.isDemoModeEnabled) {
    console.log("Retail mode is enabled.");
} else {
    Console.log("Retail mode is not enabled.");
}

Propiedades de RetailInfo

Cuando IsDemoModeEnabled devuelve true, puede consultar un conjunto de propiedades sobre el dispositivo mediante RetailInfo.Properties para crear una experiencia de demostración comercial más personalizada. Estas propiedades incluyen Nombre del Fabricante, Tamaño de Pantalla, Memoria, etcétera.

using Windows.UI.Xaml.Controls;
using Windows.System.Profile

TextBlock priceText = new TextBlock();
priceText.Text = RetailInfo.Properties[KnownRetailInfo.Price];
// Assume infoPanel is a StackPanel declared in XAML
this.infoPanel.Children.Add(priceText);
using namespace Windows::UI::Xaml::Controls;
using namespace Windows::System::Profile;

TextBlock ^manufacturerText = ref new TextBlock();
manufacturerText.set_Text(RetailInfo::Properties[KnownRetailInfoProperties::Price]);
// Assume infoPanel is a StackPanel declared in XAML
this->infoPanel->Children->Add(manufacturerText);
var pro = Windows.System.Profile;
console.log(pro.retailInfo.properties[pro.KnownRetailInfoProperties.price);

IDL

//  Copyright (c) Microsoft Corporation. All rights reserved.
//
//  WindowsRuntimeAPISet

import "oaidl.idl";
import "inspectable.idl";
import "Windows.Foundation.idl";
#include <sdkddkver.h>

namespace Windows.System.Profile
{
    runtimeclass RetailInfo;
    runtimeclass KnownRetailInfoProperties;

    [version(NTDDI_WINTHRESHOLD), uuid(0712C6B8-8B92-4F2A-8499-031F1798D6EF), exclusiveto(RetailInfo)]
    [version(NTDDI_WINTHRESHOLD, Platform.WindowsPhone)]
    interface IRetailInfoStatics : IInspectable
    {
        [propget] HRESULT IsDemoModeEnabled([out, retval] boolean *value);
        [propget] HRESULT Properties([out, retval, hasvariant] Windows.Foundation.Collections.IMapView<HSTRING, IInspectable *> **value);
    }

    [version(NTDDI_WINTHRESHOLD), uuid(50BA207B-33C4-4A5C-AD8A-CD39F0A9C2E9), exclusiveto(KnownRetailInfoProperties)]
    [version(NTDDI_WINTHRESHOLD, Platform.WindowsPhone)]
    interface IKnownRetailInfoPropertiesStatics : IInspectable
    {
        [propget] HRESULT RetailAccessCode([out, retval] HSTRING *value);
        [propget] HRESULT ManufacturerName([out, retval] HSTRING *value);
        [propget] HRESULT ModelName([out, retval] HSTRING *value);
        [propget] HRESULT DisplayModelName([out, retval] HSTRING *value);
        [propget] HRESULT Price([out, retval] HSTRING *value);
        [propget] HRESULT IsFeatured([out, retval] HSTRING *value);
        [propget] HRESULT FormFactor([out, retval] HSTRING *value);
        [propget] HRESULT ScreenSize([out, retval] HSTRING *value);
        [propget] HRESULT Weight([out, retval] HSTRING *value);
        [propget] HRESULT DisplayDescription([out, retval] HSTRING *value);
        [propget] HRESULT BatteryLifeDescription([out, retval] HSTRING *value);
        [propget] HRESULT ProcessorDescription([out, retval] HSTRING *value);
        [propget] HRESULT Memory([out, retval] HSTRING *value);
        [propget] HRESULT StorageDescription([out, retval] HSTRING *value);
        [propget] HRESULT GraphicsDescription([out, retval] HSTRING *value);
        [propget] HRESULT FrontCameraDescription([out, retval] HSTRING *value);
        [propget] HRESULT RearCameraDescription([out, retval] HSTRING *value);
        [propget] HRESULT HasNfc([out, retval] HSTRING *value);
        [propget] HRESULT HasSdSlot([out, retval] HSTRING *value);
        [propget] HRESULT HasOpticalDrive([out, retval] HSTRING *value);
        [propget] HRESULT IsOfficeInstalled([out, retval] HSTRING *value);
        [propget] HRESULT WindowsVersion([out, retval] HSTRING *value);
    }

    [version(NTDDI_WINTHRESHOLD), static(IRetailInfoStatics, NTDDI_WINTHRESHOLD)]
    [version(NTDDI_WINTHRESHOLD, Platform.WindowsPhone), static(IRetailInfoStatics, NTDDI_WINTHRESHOLD, Platform.WindowsPhone)]
    [threading(both)]
    [marshaling_behavior(agile)]
    runtimeclass RetailInfo
    {
    }

    [version(NTDDI_WINTHRESHOLD), static(IKnownRetailInfoPropertiesStatics, NTDDI_WINTHRESHOLD)]
    [version(NTDDI_WINTHRESHOLD, Platform.WindowsPhone), static(IKnownRetailInfoPropertiesStatics, NTDDI_WINTHRESHOLD, Platform.WindowsPhone)]
    [threading(both)]
    [marshaling_behavior(agile)]
    runtimeclass KnownRetailInfoProperties
    {
    }
}

Proceso de limpieza

La limpieza comienza dos minutos después de que un comprador deje de interactuar con el dispositivo. La demostración comercial se reproduce y Windows comienza a restablecer los datos de ejemplo en los contactos, fotos y otras aplicaciones. Dependiendo del dispositivo, esto puede tardar entre 1 y 5 minutos en restablecerse completamente todo a la normalidad. Esto garantiza que todos los clientes de la tienda minorista puedan caminar hasta un dispositivo y tener la misma experiencia al interactuar con el dispositivo.

Paso 1: Limpieza

  • Todas las aplicaciones win32 y store están cerradas
  • Se eliminan todos los archivos de carpetas conocidas como Imágenes, Vídeos, Música, Documentos, SavedPictures, CameraRoll, Escritorio y Descargas .
  • Se eliminan los estados de itinerancia no estructurados y estructurados.
  • Se eliminan los estados locales estructurados

Paso 2: Configuración

  • Para dispositivos sin conexión: las carpetas permanecen vacías
  • Para dispositivos en línea: los recursos de demostración comercial se pueden insertar en el dispositivo desde Microsoft Store.

Almacenamiento de datos entre sesiones de usuario

Para almacenar datos entre sesiones de usuario, puede almacenar información en ApplicationData.Current.TemporaryFolder , ya que el proceso de limpieza predeterminado no elimina automáticamente los datos de esta carpeta. Tenga en cuenta que la información almacenada mediante LocalState se elimina durante el proceso de limpieza.

Personalización del proceso de limpieza

Para personalizar el proceso de limpieza, implemente el servicio de aplicación Microsoft-RetailDemo-Cleanup en su aplicación.

Los escenarios en los que se necesita una lógica de limpieza personalizada incluyen ejecutar una amplia configuración, descargar y guardar en caché datos, o no deseen que se eliminen LocalState datos.

Paso 1: Declarar el servicio Microsoft-RetailDemo-Cleanup en el manifiesto de la aplicación.

  <Applications>
      <Extensions>
        <uap:Extension Category="windows.appService" EntryPoint="MyCompany.MyApp.RDXCustomCleanupTask">
          <uap:AppService Name="Microsoft-RetailDemo-Cleanup" />
        </uap:Extension>
      </Extensions>
   </Application>
  </Applications>

Paso 2: Implemente su lógica de limpieza personalizada en el caso de la función AppdataCleanup mediante la plantilla de ejemplo siguiente.

using System;
using System.IO;
using System.Runtime.Serialization.Json;
using System.Threading;
using System.Threading.Tasks;
using Windows.ApplicationModel.AppService;
using Windows.ApplicationModel.Background;
using Windows.Foundation.Collections;
using Windows.Storage;

namespace MyCompany.MyApp
{
    public sealed class RDXCustomCleanupTask : IBackgroundTask
    {
        BackgroundTaskCancellationReason _cancelReason = BackgroundTaskCancellationReason.Abort;
        BackgroundTaskDeferral _deferral = null;
        IBackgroundTaskInstance _taskInstance = null;
        AppServiceConnection _appServiceConnection = null;

        const string MessageCommand = "Command";

        public void Run(IBackgroundTaskInstance taskInstance)
        {
            // Get the deferral object from the task instance, and take a reference to the taskInstance;
            _deferral = taskInstance.GetDeferral();
            _taskInstance = taskInstance;
            _taskInstance.Canceled += new BackgroundTaskCanceledEventHandler(OnCanceled);

            AppServiceTriggerDetails appService = _taskInstance.TriggerDetails as AppServiceTriggerDetails;
            if ((appService != null) && (appService.Name == "Microsoft-RetailDemo-Cleanup"))
            {
                _appServiceConnection = appService.AppServiceConnection;
                _appServiceConnection.RequestReceived += _appServiceConnection_RequestReceived;
                _appServiceConnection.ServiceClosed += _appServiceConnection_ServiceClosed;
            }
            else
            {
                _deferral.Complete();
            }
        }

        void _appServiceConnection_ServiceClosed(AppServiceConnection sender, AppServiceClosedEventArgs args)
        {
        }

        async void _appServiceConnection_RequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
        {
            //Get a deferral because we will be calling async code
            AppServiceDeferral requestDeferral = args.GetDeferral();
            string command = null;
            var returnData = new ValueSet();

            try
            {
                ValueSet message = args.Request.Message;
                if (message.ContainsKey(MessageCommand))
                {
                    command = message[MessageCommand] as string;
                }

                if (command != null)
                {
                    switch (command)
                    {
                        case "AppdataCleanup":
                            {
                                // Do custom clean up logic here
                                break;
                            }
                    }
                }
            }
            catch (Exception e)
            {
            }
            finally
            {
                requestDeferral.Complete();
                // Also release the task deferral since we only process one request per instance.
                _deferral.Complete();
            }
        }

        private void OnCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
        {
            _cancelReason = reason;
        }
    }
}