Adicionar recursos de demonstração (RDX) do varejo ao seu aplicativo

Inclua um modo de demonstração de varejo em seu aplicativo do Windows para que os clientes que experimentarem PCs e dispositivos na área de vendas possam começar imediatamente.

Quando os clientes estão em uma loja de varejo, eles esperam poder experimentar demonstrações de computadores e dispositivos. Muitas vezes, eles passam uma parte considerável do tempo brincando com aplicativos por meio da RDX (experiência de demonstração de varejo).

Você pode configurar seu aplicativo para fornecer experiências diferentes enquanto estiver em modos normais ou de varejo . Por exemplo, se seu aplicativo começar com um processo de instalação, você poderá passar por ele no modo de varejo e preencher previamente o aplicativo com dados de exemplo e configurações padrão para que eles possam entrar diretamente.

Da perspectiva de nossos clientes, há apenas um aplicativo. Para ajudar os clientes a distinguir entre os dois modos, recomendamos que, enquanto seu aplicativo estiver no modo de varejo, ele mostre a palavra "Varejo" em destaque na barra de título ou em um local adequado.

Além dos requisitos da Microsoft Store para aplicativos, os aplicativos com reconhecimento de RDX também devem ser compatíveis com os processos de instalação, limpeza e atualização do RDX para garantir que os clientes tenham uma experiência consistentemente positiva na loja de varejo.

Princípios de design

  • Mostre o seu melhor. Use a experiência de demonstração de varejo para mostrar por que seu aplicativo é arrasada. É provável que essa seja a primeira vez que seu cliente verá seu aplicativo, então mostre a melhor parte!

  • Mostre-o rápido. Os clientes podem ser impacientes - Quanto mais rápido um usuário puder experimentar o valor real do aplicativo, melhor.

  • Mantenha a história simples. A experiência de demonstração de varejo é uma apresentação de elevador para o valor do seu aplicativo.

  • Concentre-se na experiência. Dê ao usuário tempo para interpretar o conteúdo. Embora mostrar a eles a melhor parte seja importante, projetar pausas indicadas pode ajudá-los no aproveitamento máximo da experiência.

Requisitos técnicos

Como os aplicativos com reconhecimento de RDX destinam-se a mostrar o melhor do seu aplicativo para clientes de varejo, eles devem atender aos requisitos técnicos e aderir aos regulamentos de privacidade que a Microsoft Store tem para todos os aplicativos de experiência de demonstração de varejo.

Isso pode ser usado como uma lista de verificação para ajudá-lo a se preparar para o processo de validação e para fornecer clareza no processo de teste. Esses requisitos precisam ser mantidos, não apenas para o processo de validação, mas para todo o tempo de vida do aplicativo de experiência de demonstração de revenda; desde que o aplicativo continue em execução nos dispositivos de demonstração de revenda.

Requisitos críticos

Os aplicativos com reconhecimento de RDX que não atendem a esses requisitos críticos serão removidos de todos os dispositivos de demonstração de varejo o mais rápido possível.

  • Não solicite PII (informações de identificação pessoal). Isso inclui informações de logon, informações de conta da Microsoft ou detalhes de contato.

  • Experiência sem erros. O aplicativo deve ser executado sem erros. Além disso, nenhum pop-up de erro ou notificação deve ser mostrado para clientes que usem os dispositivos de demonstração de revenda. Os erros refletem negativamente sobre o próprio aplicativo, sua marca, a marca do dispositivo, a marca do fabricante do dispositivo e a marca da Microsoft.

  • Os aplicativos pagos devem ter um modo de avaliação. Seu aplicativo precisa ser gratuito ou incluir um modo de avaliação. Os clientes não esperam pagar por uma experiência em uma loja de revenda.

Requisitos de alta prioridade

Os aplicativos com reconhecimento de RDX que não atendem a esses requisitos de alta prioridade precisam ser investigados para uma correção imediatamente. Se nenhuma correção imediata for encontrada, esse aplicativo poderá ser removido de todos os dispositivos de demonstração de revenda.

  • Experiência offline memorável. Seu aplicativo precisa demonstrar uma ótima experiência offline, pois cerca de 50% dos dispositivos estão offline em locais de varejo. Isso é para garantir que os clientes que interajam com o aplicativo offline ainda sejam capazes de ter uma experiência significativa e positiva.

  • Experiência de conteúdo atualizada. Seu aplicativo nunca deve receber solicitações de atualizações quando estiver online. Se forem necessárias atualizações, elas deverão ser executadas silenciosamente.

  • Sem comunicação anônima. Como um cliente que usa um dispositivo de demonstração de varejo é um usuário anônimo, ele não deve ser capaz de enviar mensagens ou compartilhar conteúdo do dispositivo.

  • Fornecer experiências consistentes usando o processo de limpeza. Todos os clientes devem ter a mesma experiência quando usarem um dispositivo de demonstração de revenda. Seu aplicativo deve usar limpo processo para retornar ao mesmo estado padrão após cada uso. Não queremos que o próximo cliente veja o que o último cliente deixou para trás. Isso inclui placares, conquistas e desbloqueios.

  • Conteúdo apropriado para a idade. Todo o conteúdo do aplicativo precisa ser atribuído a uma categoria de classificação Adolescente ou inferior. Para saber mais, confira Obter seu aplicativo classificado por classificações IARC e ESRB.

Requisitos de prioridade média

A equipe da Loja de revenda do Windows pode entrar em contato com desenvolvedores diretamente para marcar uma reunião sobre como corrigir esses problemas.

  • Capacidade de executar com êxito em uma variedade de dispositivos. Os aplicativos devem ser executados bem em todos os dispositivos, incluindo dispositivos com especificações de baixo nível. Se o aplicativo estiver instalado em dispositivos que não atenderam às especificações mínimas, o aplicativo precisará informar claramente o usuário sobre isso. Os requisitos de dispositivo mínimos devem ser conhecidos de maneira que o aplicativo possa ser sempre executado com alto desempenho.

  • Atender aos requisitos de tamanho do aplicativo da loja de varejo. O aplicativo deve ser menor do que 800 MB. Entre em contato diretamente com a equipe da Windows Retail Store para mais discussões se o aplicativo com reconhecimento de RDX não atender aos requisitos de tamanho.

API RetailInfo: preparando seu código para o modo de demonstração

IsDemoModeEnabled

A propriedade IsDemoModeEnabled na classe de utilitário RetailInfo, que faz parte do namespace Windows.System.Profile no SDK do Windows 10 e Windows 11, é usada como um indicador booliano para especificar em qual caminho de código seu aplicativo é executado – o modo normal ou o modo de varejo.

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.");
}

RetailInfo.Properties

Quando IsDemoModeEnabled retorna verdadeiro, é possível consultar um conjunto de propriedades sobre o dispositivo usando RetailInfo.Properties para criar uma experiência de demonstração de varejo mais personalizada. Entre essas propriedades estão ManufacturerName, Screensize, Memory etc.

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
    {
    }
}

Processo de limpeza

A limpeza começa dois minutos depois que um comprador para de interagir com o dispositivo. A demonstração de varejo é reproduzida e o Windows começa a redefinir os dados de exemplo nos contatos, fotos e outros aplicativos. Dependendo do dispositivo, isso pode levar entre 1 e 5 minutos para redefinir totalmente tudo de volta ao normal. Isso garante que todos os clientes na loja de varejo possam acessar um dispositivo e ter a mesma experiência ao interagir com o dispositivo.

Etapa 1: Limpeza

  • Todos os aplicativos Win32 e da Loja são fechados
  • Todos os arquivos em pastas conhecidas como Imagens, Vídeos, Música, Documentos, SavedPictures, CameraRoll, Área de Trabalho e Downloads são excluídos
  • Estados de roaming não estruturados e estruturados são excluídos
  • Estados locais estruturados são excluídos

Etapa 2: Instalação

  • Para dispositivos offline: as pastas permanecem vazias
  • Para dispositivos online: os ativos de demonstração de varejo podem ser enviados para o dispositivo pela Microsoft Store

Armazenar dados entre sessões de usuário

Para armazenar dados entre sessões de usuário, você pode armazenar informações em ApplicationData.Current.TemporaryFolder , pois o processo de limpeza padrão não exclui automaticamente os dados nessa pasta. Observe que as informações armazenadas usando LocalState são excluídas durante o processo de limpeza.

Personalizar o processo de limpeza

Para personalizar o processo de limpeza, implemente o Microsoft-RetailDemo-Cleanup serviço de aplicativo em seu aplicativo.

Os cenários em que uma lógica de limpeza personalizada é necessária incluem a execução de uma configuração abrangente, o download e o cache de dados ou a falta de exclusão de dados LocalState .

Etapa 1: declare o serviço Microsoft-RetailDemo-Cleanup no manifesto do aplicativo.

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

Etapa 2: implemente sua lógica de limpeza personalizada na função de caso AppdataCleanup usando o modelo de exemplo abaixo.

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