Freigeben über


Fügen Sie RDX-Features (Retail Demo) zu Ihrer App hinzu

Fügen Sie einen Einzelhandels-Demomodus in Ihre Windows-App ein, damit Kunden, die PCs und Geräte auf der Verkaufsfläche ausprobieren, sofort loslegen können.

Wenn sich Kunden in einem Ladengeschäft befinden, erwarten sie, dass sie Demos von PCs und Geräten auszuprobieren können. Sie verbringen oft einen erheblichen Teil ihrer Zeit damit, mit Apps im Rahmen der Einzelhandels-Demo-Erlebnis (RDX)zu experimentieren.

Sie können Ihre App so einrichten, dass sie im normalen oder im Einzelhandelsmodus unterschiedliche Erfahrungen bereitstellt. Wenn Ihre App z. B. mit einem Setupprozess beginnt, können Sie den Setupprozess im Einzelhandelsmodus überspringen und die App mit Beispieldaten und Standardeinstellungen vorab ausstatten, damit Benutzer direkt loslegen können.

Aus Sicht unserer Kunden gibt es nur eine App. Um Kunden dabei zu helfen, zwischen den beiden Modi zu unterscheiden, empfiehlt es sich, während sich Ihre App im Einzelhandelsmodus befindet, das Wort "Einzelhandel" in der Titelleiste oder an einem geeigneten Ort anzuzeigen.

Zusätzlich zu den Microsoft Store-Anforderungen für Apps müssen RDX-fähige Apps auch mit den RDX-Setup-, Bereinigungs- und Updateprozessen kompatibel sein, um sicherzustellen, dass Kunden eine konsistente positive Erfahrung im Einzelhandelsgeschäft haben.

Designprinzipien

  • Zeigen Sie Ihr Bestes. Verwenden Sie die Demo-Erfahrung für den Einzelhandel, um zu zeigen, warum Ihre App rockt. Dies ist wahrscheinlich das erste Mal, wenn Ihr Kunde Ihre App sehen wird, also zeigen Sie ihnen das beste Stück!

  • Zeigen Sie es schnell. Kunden können ungeduldig sein – Je schneller ein Benutzer den tatsächlichen Wert Ihrer App erleben kann, desto besser.

  • Halt die Geschichte einfach. Das Demo-Erlebnis im Verkauf ist eine Kurzpräsentation für den Nutzen Ihrer App.

  • Konzentrieren Sie sich auf die Erfahrung. Geben Sie dem Benutzer Zeit, Ihre Inhalte zu digestieren. Es ist wichtig, dass sie schnell zum besten Teil gelangen, aber ebenso wichtig ist es, geeignete Pausen einzuplanen, die ihnen helfen, die Erfahrung vollständig zu genießen.

Technische Anforderungen

Da RDX-fähige Apps das Beste Ihrer App für Einzelhandelskunden präsentieren sollen, müssen sie technische Anforderungen erfüllen und Datenschutzbestimmungen einhalten, die der Microsoft Store für alle Demo-Apps für den Einzelhandel hat.

Dies kann als Prüfliste verwendet werden, um Sie bei der Vorbereitung auf den Validierungsprozess zu unterstützen und Klarheit im Testprozess zu bieten. Beachten Sie, dass diese Anforderungen nicht nur für den Validierungsprozess, sondern für die gesamte Lebensdauer der Demo-App für den Einzelhandel beibehalten werden müssen; solange Ihre App auf den Demogeräten für den Einzelhandel ausgeführt wird.

Kritische Anforderungen

RDX-fähige Apps, die diese kritischen Anforderungen nicht erfüllen, werden so bald wie möglich von allen Demogeräten für den Einzelhandel entfernt.

  • Bitten Sie nicht um personenbezogene Informationen (PII). Dazu gehören Anmeldeinformationen, Microsoft-Kontoinformationen oder Kontaktdetails.

  • Fehlerfreie Erfahrung. Ihre App muss ohne Fehler ausgeführt werden. Darüber hinaus sollten keine Fehler-Popups oder Benachrichtigungen für Kunden angezeigt werden, die die Demogeräte für den Einzelhandel verwenden. Fehler wirken sich negativ auf die App selbst aus, Ihre Marke, die Marke des Geräts, die Marke des Geräteherstellers und die Marke von Microsoft aus.

  • Kostenpflichtige Apps müssen über einen Testmodusverfügen. Ihre App muss entweder kostenlos sein oder einen Testmoduseinschließen. Kunden sind nicht bereit, für ein Erlebnis in einem Einzelhandelsgeschäft zu zahlen.

Anforderungen mit hoher Priorität

RDX-fähige Apps, die diese wichtigen Anforderungen nicht erfüllen, müssen sofort auf eine Lösung hin geprüft werden. Wenn keine sofortige Lösung gefunden wird, wird diese App möglicherweise von allen Demogeräten für den Einzelhandel entfernt.

  • unvergessliche Offline-Erfahrung. Ihre App muss eine großartige Offlineerfahrung demonstrieren, da etwa 50% der Geräte an Einzelhandelsstandorten offline sind. Dadurch wird sichergestellt, dass Kunden, die offline mit Ihrer App interagieren, weiterhin eine sinnvolle und positive Erfahrung haben können.

  • Aktualisierte Inhaltserfahrung. Ihre App sollte niemals aufgefordert werden, ein Update durchzuführen, wenn sie online ist. Wenn Updates erforderlich sind, sollten sie unauffällig ausgeführt werden.

  • Keine anonyme Kommunikation. Da ein Kunde, der ein Demogerät für den Einzelhandel verwendet, ein anonymer Benutzer ist, sollte er nicht in der Lage sein, Inhalte vom Gerät zu senden oder zu teilen.

  • Konsistente Erfahrungen bereitstellen, indem der Bereinigungsprozessverwendet wird. Jeder Kunde sollte die gleiche Erfahrung machen, wenn er zu einem Demogerät im Einzelhandel geht. Ihre App sollte den Bereinigungsprozess verwenden, um nach der Nutzung in den Standardzustand zurückzukehren. Wir möchten nicht, dass der nächste Kunde sieht, was der letzte Kunde hinter sich gelassen hat. Dazu gehören Scoreboards, Erfolge und Freischaltungen.

  • altersgerechter Inhalt. Allen App-Inhalten muss eine Teen- oder niedrigere Bewertungskategorie zugewiesen werden. Weitere Informationen finden Sie unter So wird Ihre App von der IARC bewertet und ESRB-Bewertungen.

Anforderungen mit mittlerer Priorität

Das Windows Retail Store-Team kann entwickler direkt kontaktieren, um eine Diskussion zur Behebung dieser Probleme einzurichten.

  • Fähigkeit, erfolgreich auf einer Vielzahl von Gerätenzu laufen. Apps müssen auf allen Geräten gut ausgeführt werden, einschließlich Geräten mit Low-End-Spezifikationen. Wenn die App auf Geräten installiert ist, die die Mindestspezifikationen nicht erfüllten, muss die App den Benutzer eindeutig darüber informieren. Die Mindestgeräteanforderungen müssen bekannt gemacht werden, damit die App immer mit hoher Leistung ausgeführt werden kann.

  • Erfüllen der Größenanforderungen der Einzelhandels-Store-App. Die App muss kleiner als 800 MB sein. Wenden Sie sich direkt an das Windows Retail Store-Team, wenn Ihre RDX-fähige App die Größenanforderungen nicht erfüllt, um weitere Gespräche zu führen.

RetailInfo-API: Vorbereiten des Codes für den Demomodus

IstDemoModusAktiviert

Die Eigenschaft IsDemoModeEnabled in der RetailInfo Hilfsklasse, die Teil des Windows.System.Profile Namensraums im Windows 10- und Windows 11 SDK ist, wird als boolescher Indikator verwendet, um anzugeben, auf welchem Codepfad Ihre App ausgeführt wird – den normalen Modus oder den Einzelhandelsmodus.

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

Wenn IsDemoModeEnabled "wahr" zurückgibt, können Sie mithilfe von RetailInfo.Properties eine Reihe von Eigenschaften über das Gerät abfragen, um eine angepasste Demoumgebung für den Einzelhandel zu erstellen. Diese Eigenschaften umfassen ManufacturerName, Screensize, Memory usw.

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

Bereinigungsprozess

Die Bereinigung beginnt zwei Minuten, nachdem ein Käufer nicht mehr mit dem Gerät interagiert. Die Demo für den Einzelhandel wird wiedergegeben, und Windows beginnt, alle Beispieldaten in Kontakten, Fotos und anderen Apps zurückzusetzen. Je nach Gerät kann dies zwischen 1 und 5 Minuten dauern, bis alles wieder normal zurückgesetzt wird. Dadurch wird sichergestellt, dass jeder Kunde im Einzelhandelsgeschäft zu einem Gerät gelangen kann und bei der Interaktion mit dem Gerät die gleiche Erfahrung hat.

Schritt 1: Bereinigen

  • Alle Win32- und Store-Apps sind geschlossen.
  • Alle Dateien in bekannten Ordnern wie Bilder, Videos, Musik, Dokumente, SavedPictures, CameraRoll, Desktop- und Downloads Ordner werden gelöscht.
  • Unstrukturierte und strukturierte Roamingzustände werden gelöscht.
  • Strukturierte lokale Zustände werden gelöscht.

Schritt 2: Einrichten

  • Für Offlinegeräte: Ordner bleiben leer
  • Für Onlinegeräte: Demoressourcen für den Einzelhandel können über den Microsoft Store an das Gerät übertragen werden.

Speicherung von Daten über Benutzersitzungen hinweg

Um Daten über Benutzersitzungen hinweg zu speichern, können Sie Informationen im ApplicationData.Current.TemporaryFolder- ablegen, da der Standardbereinigungsprozess die Daten in diesem Ordner nicht automatisch löscht. Beachten Sie, dass Informationen, die mithilfe von LocalState gespeichert wurden, während des Bereinigungsprozesses gelöscht werden.

Den Bereinigungsprozess anpassen

Um den Bereinigungsprozess anzupassen, implementieren Sie den Microsoft-RetailDemo-Cleanup App-Dienst in Ihre App.

Szenarien, in denen eine benutzerdefinierte Bereinigungslogik erforderlich ist, umfasst das Ausführen eines umfangreichen Setups, Das Herunterladen und Zwischenspeichern von Daten oder das Nicht-Löschen LocalState- Daten.

Schritt 1: Deklarieren sie den Microsoft-RetailDemo-Cleanup- Dienst im App-Manifest.

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

Schritt 2: Implementieren Sie Ihre benutzerdefinierte Bereinigungslogik unter der AppdataCleanup Case-Funktion mithilfe der folgenden Beispielvorlage.

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