Porting Xbox Live Code from Xbox One XDK to Windows 10 UWP

Updated March 1, 2016

In this topic:

Introduction

This white paper is intended to help developers who have used the Xbox One XDK to get started migrating their Xbox Live code to the Windows 10 Universal Windows Platform (UWP). These are tips and tricks that we in ATG have learned along the way.

Part of this migration includes switching from XSAPI 1.0 (Xbox Live Services API, included in the Xbox One XDK through August 2015) to XSAPI 2.0 (included in the Xbox One XDK starting in December 2015, and also available in the Xbox Live SDK). The functionality of these APIs are virtually identical, but there are some important implementation differences.

Other topics to be covered in this white paper include preparing your Windows development computer and installing other APIs typically needed when using Xbox Live services, such as the Secure Sockets API as well as the Connected Storage API for managing cloud-backed game saves.

Setting up and configuring your project in Dev Center and XDP

A UWP title that uses Xbox Live services needs to be configured in the Windows Dev Center and the Xbox Developer Portal (XDP). For the latest information, see “How to add Xbox Live support to a new or existing Visual Studio UWP project” in the Xbox Live Programming Guide included with the Xbox Live SDK.

Topics on that page include these steps for using Xbox Live services in your title:

If your titles support multiplayer play, some additional settings may be required in your multiplayer session templates. All Windows 10 titles that use Xbox Live multiplayer and write to an MPSD (multiplayer session document) require this new field in the list of “capabilities” found in your session templates: userAuthorizationStyle: true.

Enabling cross-play

If you will support “cross-play” (a shared Xbox Live configuration between Xbox One and PC games, allowing cross-device multiplayer gaming), you will also need to add this capability to your session templates: crossPlay: true.

For additional information about supporting cross-play and its configuration requirements in XDP, see “Ingesting ERA and UWP Cross-Play Titles in XDP” in the Xbox Live Programming Guide.

Also, for some programmatic considerations, see the section later in this white paper entitled Supporting multiplayer cross-play between Xbox One and PC.

Setting up your Windows development environment

  1. Download the latestXbox Live SDK and extract locally.
  2. Install theXbox Live Platform Extensions SDK if you need the Secure Sockets API and/or the Game Save API (aka Connected Storage) for UWP.
  3. Add Xbox Live support to your Universal Windows app project in Visual Studio. You can add either the full source or reference the binaries by installing the NuGet package into your Visual Studio 2015 project. Packages are available for both C++ and WinRT. Full instructions are included with the Xbox Live SDK documentation. See the Xbox Live Programming Guide section “How to add Xbox Live support to a new or existing Visual Studio UWP project” and read the page entitled “Installing Xbox Live SDK NuGet packages for UWP projects.”
  4. Configure your development computer to use your sandbox. There’s a command-line script in the Tools directory of the Xbox Live SDK that you can use from an administrator command prompt (for example: SwitchSandbox.cmd XDKS.1).

    Note To switch back to the retail sandbox, you can either delete the registry key that the script modifies, or you can switch to the sandbox called RETAIL.

  5. Add a developer account to your development computer. A developer account created in XDP is required to interact with Xbox Live services at runtime when you are developing in your assigned sandbox or running samples. To add one or more accounts to Windows:
    1. Open Settings (shortcut: Windows key + I).
    2. Open Accounts.
    3. On the Your Account tab, click Add a Microsoft account.
    4. Enter the developer account email and password.

AppxManifest changes

The most common changes between the Xbox and UWP versions of the appxmanifest.xml file are:

  1. Package Identity matters in UWP, even during development. Both the Identity Name and Publisher must match what was defined in Dev Center for your UWP app.
  2. A Package Dependency section is required. For example:
              <Dependencies>
                <TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.10240.0" MaxVersionTested="10.0.10240.0" />
              </Dependencies>  
    
  3. Refer to an example UWP application manifest (for example, one of the UWP samples included with the Xbox Live SDK or a default Universal Windows app project created in Visual Studio) for other sections of the application manifest that have specific requirements for UWP, such as <VisualElements>.
  4. Title and SCID are defined in the xboxservices.config file (see the next section) instead of in the “xbox.live” extension category.
  5. The “xbox.system.resources” extension category is not needed.
  6. Secure Sockets are defined in the networkmanifest.xml file (see Secure sockets) instead of in the “windows.xbox.networking” category.
  7. A “windows.protocol” extension category must be defined in order to receive Xbox Live invites in your UWP title (see Sending and receiving invites).
  8. If you use the GameChat API, you’ll want to add the microphone device capability inside the <Capabilities> element. For example:
              <DeviceCapability Name="microphone" />  
    

Define your title and SCID for the Xbox Live SDK in a config file

The Xbox Live SDK needs to know your title ID and SCID, which are no longer included in the appxmanifest.xml for UWP titles. Instead, you create a text file named xboxservices.config in your project root directory and add the following fields, replacing the values with the info for your title:

      {
        "TitleId": 174925616,
        "PrimaryServiceConfigId": "5deb0100-042c-41d9-9ec5-55580a6d2730"
      }  

Include this config file as content in your project so that it is available in the build output.

Note These values will be available programmatically within your title by using the following API:

      Microsoft::Xbox::Services::XboxLiveAppConfiguration^ xblConfig = xblContext->AppConfig;
      unsigned int titleId = xblConfig->TitleId;
      Platform::String^ scid = xblConfig->ServiceConfigurationId;  

API namespace mapping

Table 1. Namespace mapping from XDK to UWP.

  Xbox One XDK UWP API is available with…
Xbox Services API (XSAPI) Microsoft::Xbox::Services Microsoft::Xbox::Services (no change) Xbox Live SDK (use NuGet binary or source)
Game Chat 2 xbox::services::game_chat_2 xbox::services::game_chat_2 (no change) Xbox Live SDK (use NuGet binary)
Secure Sockets Windows::Xbox::Networking Windows::Networking::XboxLive Xbox Live Platform Extensions SDK
Connected Storage Windows::Xbox::Storage Windows::Gaming::XboxLive::Storage Xbox Live Platform Extensions SDK

Migrating from XSAPI 1.0 to XSAPI 2.0

XSAPI 2.0 is part of the Xbox Live SDK, available as a NuGet package binary, or for compiling from source. It is also the version used in the Xbox One XDK beginning with the December 2015 release. Both WinRT and straight ISO C++/11 interfaces are available.

For the latest information about the changes in XSAPI 2.0, see “Migrating to Xbox Live Services API 2.0” in the Xbox Live Programming Guide included with the Xbox Live SDK.

Multiplayer subscriptions and event handling

One of the breaking changes from XSAPI 1.0 to XSAPI 2.0 that most multiplayer titles will encounter is the move of several methods and events from the RealTimeActivityService to the MultiplayerService.

For example:

Note Even though you might not be explicitly using anything else in the RealTimeActivityService after moving these events and methods over to the MultiplayerService, you must still call xblContext->RealTimeActivityService->Activate() before calling EnableMultiplayerSubscriptions() because the multiplayer subscriptions require the RTA service.

For a complete list of breaking changes to the XSAPI 1.0 WinRT interface, as well as new features in XSAPI 2.0, see the table with “WinRT changes from XSAPI 1.0” in the “Migrating to Xbox Live Services API 2.0” topic in the Xbox Live Programming Guide.

What’s handled differently in UWP

Following is a very high level list of sections of code that will likely have differences between the XDK and UWP, as encountered in the new NetRumble sample (which includes both XDK and UWP versions):

The following sections go into further detail on many of these differences.

Accessing title ID and SCID info

In UWP, your title ID and service configuration ID are accessed through the AppConfig property on an instance of an XboxLiveContext.

      Microsoft::Xbox::Services::XboxLiveAppConfiguration^ xblConfig = xblContext->AppConfig;
      unsigned int titleId = xblConfig->TitleId;
      Platform::String^ scid = xblConfig->ServiceConfigurationId;  

Note In the XDK, you can get these IDs by using either these new properties or the old static properties in Windows::Xbox::Services::XboxLiveConfiguration.

Prelaunch activation

Frequently-used titles in Windows 10 may be prelaunched when the user signs in. To handle this, your title should have code that checks the launch arguments for PreLaunchActivated. For example, you probably don’t want to load all your resources during this kind of activation. For more information, see the MSDN article Handle app prelaunch.

Suspend/resume PLM handling

Suspend and resume, and PLM in general, work similarly in a Universal Windows app to the way they work on Xbox One; however, there are a few important differences to keep in mind:

Another important consideration if you use connected storage is the new ContainersChangedSinceLastSync property in the UWP version of this API. When handling a resume event, you can check this property to see if any containers changed in the cloud while your title was suspended. This can happen if the player suspended the game on one PC, played elsewhere, and then returned to the first PC. If you had read data from these containers into memory before you had suspended, you probably want to read them again to see what changed and handle the changes accordingly.

For more information about handling PLM in a UWP app on Windows 10, see the MSDN article Launching, resuming, and background tasks.

You may also find the Process Lifetime Management (PLM) for Xbox One white paper on XGD useful because it was written with games in mind, and most of the concepts for handling the app lifecycle still apply on a PC.

Extended execution

Minimizing a UWP app on a PC typically results in it immediately starting to suspend. By using extended execution, you have the opportunity to delay this process. Example implementation:

      using namespace Windows::ApplicationModel::ExtendedExecution;
      //If this goes out of scope the request is nullified
      ExtendedExecutionSession^ session;
      void App::RequestExtension()
      {
          if (!session)
          {
            session = ref new ExtendedExecutionSession();
          }
          session->Reason = ExtendedExecutionReason::Unspecified;
          session->Description = "foo";
          session->Revoked += ref new TypedEventHandler<Platform::Object^, ExtendedExecutionRevokedEventArgs^>(this, &App::ExtensionRevokedHandler);
          IAsyncOperation<ExtendedExecutionResult>^ request = session->RequestExtensionAsync();
          //At this point the request has been made. When the IAsyncOperation request completes, verify that the ExtendedExecutionResult == Allowed and you will not suspend for 
          up to 10 minutes while minimized.
      }

      void App::ExtensionRevokedHandler(Platform::Object^ obj, ExtendedExecutionRevokedEventArgs^ args)
      {
        if (args->Reason == Windows::ApplicationModel::ExtendedExecutionRevokedReason::Resumed)
        {
        //Request the extension again in preparation for the next suspend.
      RequestExtension();
        }
        //The app will either complete suspending if the extension was revoked by system policy or resume running if the user has switched back to the app.
      }  

After the ExtensionRevokedHandler has been called, a new extension needs to be requested for future potential suspensions. The ExtensionRevokedHandler is called when there is memory pressure in the system, 10 minutes have elapsed, or the user switches back to the game while the game is minimized. So RequestExtension() should likely be called at these times:

Handling users and controllers

On Windows, you work with one signed-in user at a time. In the Xbox Live SDK, you first create an XboxLiveUser object, sign them in to Xbox Live, and then create XboxLiveContext objects from this user.

Before, on the Xbox One XDK:

  1. Acquire a user (from gamepad interaction, for example).
  2. Create an XboxLiveContext from that user:
            ref new Microsoft::Xbox::Services::XboxLiveContext( Windows::Xbox::System::User^ user )  
    
  3. Handle a SignOut event:
            Windows::Xbox::System::User::SignOutStarted  
    
  4. Handle gamepad/controller pairing using:
            Windows::Xbox::Input::Controller::ControllerRemoved
            Windows::Xbox::Input::Controller::ControllerPairingChange  
    

Now, for the UWP/Xbox Live SDK:

  1. Create an XboxLiveUser:
            auto xblUser = ref new Microsoft::Xbox::Services::System::XboxLiveUser();  
    
  2. Try to sign them in by using the last Microsoft account they used, without bothering them with UI:
            xblUser->SignInSilentlyAsync();  
    
  3. If you get SignInResult::Success in the result from this async operation, create the XboxLiveContext, and then you’re finished:
            auto xblContext = ref new Microsoft::Xbox::Services::XboxLiveContext( xblUser );  
    
  4. If instead you get SignInResult::UserInteractionRequired, you need to call the interactive sign-in method that brings up system UI:
            xblUser->SignInAsync();  
    
  5. From here you may get SignInResult::UserCancel, in which case you don’t have a signed-in user and you should consider providing a menu option for them to try signing in again.

    Note When providing menu options, it’s a good idea to give them the option to switch to a different Microsoft account:

              xblUser->SwitchAccountAsync( nullptr );  
    
  6. After you have a signed-in user, you may want to hook up the XboxLiveUser::SignOutCompleted event so that you can react to the user signing out:
            xblUser->SignOutCompleted += ref new Windows::Foundation::EventHandler<Microsoft::Xbox::Services::System::SignOutCompletedEventArgs^>( &OnSignOutCompleted );  
    
  7. There is no controller pairing to handle in Windows 10.

This is a simplified example for C++ / WinRT. For a more detailed example, see “Xbox Live Authentication in Windows 10” in the Xbox Live Programming Guide. You may also find the broader example at “Adding Xbox Live to a new UWP project” helpful.

Checking multiplayer privileges

The equivalent to CheckPrivilegeAsync() is not yet available in the Xbox Live SDK. For now, you will need to search for the privilege you need in the string list returned by the Privileges property for an XboxLiveUser. For example, to check for multiplayer privileges, look for privilege “254.” Using the XDK documentation, you can find a list of all the Xbox Live privileges in the Windows::Xbox::ApplicationModel::Store::KnownPrivileges enumeration.

For a discussion on this topic, see the forum post xsapi & user privileges.

Supporting multiplayer cross-play between Xbox One and PC UWP

In addition to new session template requirements in XDP (see Setting up and configuring your project in Dev Center and XDP), cross-play comes with new restrictions on session join ability. You can no longer use “None” as a session join restriction. You must use either “Followed” or “Local” (the default restriction is “Local”).

Also, the join and read restrictions default to “Local” because of the required userAuthorizationStyle capability for Windows 10 multiplayer.

This forum article, Is it possible to create a public multiplayer session, contains additional insight.

Further information and examples can be found in the updated multiplayer developer flowcharts, the cross-play-enabled multiplayer sample NetRumble, or from your Developer Account Manager (DAM).

Sending and receiving invites

The API to bring up the UI for sending invites is now Microsoft::Xbox::Services::System::TitleCallableUI::ShowGameInviteUIAsync(). You pass in a session->SessionReference object from your activity session (typically your lobby). You can optionally pass in a second parameter that references a custom invite string ID that’s been defined in your service configuration in XDP. The string you define there will appear in the toast notification sent to the invited players. Note that what you are passing in as a parameter to this method is the ID number, and it must be formatted properly for the service. For example, string ID “1” must be passed in as “///1”.

If you want to send invites directly by using the multiplayer service (that is, without showing any UI), you can still use the other invite method, Microsoft::Xbox::Services::Multiplayer::MultiplayerService::SendInvitesAsync() from the user’s XboxLiveContext.

To allow for invites coming into Windows to protocol-activate your title, you need to add this extension to the <Application> element in the appxmanifest:

      <Extensions>
        <uap:Extension Category="windows.protocol">
          <uap:Protocol Name="ms-xbl-multiplayer" />
        </uap:Extension> 
      </Extensions>  

You can then handle the invite as you did before on Xbox One when yourCoreApplication gets an Activated event and the activation Kind is an ActivationKind::Protocol.

Showing the gamer profile card

To pop up the gamer profile card on UWP, use Microsoft::Xbox::Services::System::TitleCallableUI::ShowProfileCardUIAsync(), passing in the XUID for the target user.

Secure sockets

The Secure Socket API is included in the separate Xbox Live Platform Extensions SDK.

See this forum post for API usage: Setting up SecureDeviceAssociation for cross platform.

Note For UWP, the SocketDescriptions section has moved out of the appxmanifest and into its own networkmanifest.xml. The format inside the <SocketDescriptions> element is virtually identical, just without the mx: prefix.

For cross-play between Xbox and Windows 10, be sure that everything is defined identically between the two different kinds of manifests (Package.appxmanifest for Xbox One and networkmanifest.xml for Windows 10). The socket name, protocol, etc. must match exactly.

Also for cross-play, you will need to define the following four SDA usages inside the <AllowedUsages> element in both the Xbox One Package.appxmanifest and the Windows 10 networkmanifest.xml:

      <SecureDeviceAssociationUsage Type="InitiateFromMicrosoftConsole" />
      <SecureDeviceAssociationUsage Type="AcceptOnMicrosoftConsole" />
      <SecureDeviceAssociationUsage Type="InitiateFromWindowsDesktop" /> 
      <SecureDeviceAssociationUsage Type="AcceptOnWindowsDesktop" />  

Multiplayer QoS measurements

In addition to the namespace change in the Secure Sockets API, some of the object names and values have changed, too. The mapping for the typically-used measurement status is found in the following table.

Table 2. Typically used measurement status mapping.

XDK (Windows::Xbox::Networking::QualityOfServiceMeasurementStatus) UWP (Windows::Networking::XboxLive::XboxLiveQualityOfServiceMeasurementStatus)
HostUnreachable NoCompatibleNetworkPaths
MeasurementTimedOut TimedOut
PartialResults InProgressWithProvisionalResults
Success Succeeded

The steps involved in measuring QoS (quality of service) and processing the results are in principle the same when you compare the XDK and UWP versions of the API. However, due to the name changes and a few design changes, the resulting code looks different in some places.

To measure the QoS for the XDK, you created a collection of secure device addresses and a collection of metrics and passed these into the MeasureQualityOfServiceAsync() method.

To measure the QoS for UWP, you create a new XboxLiveQualityOfServiceMeasurement() object, call Append() to its Metrics and DeviceAddresses properties, and then call the object’s MeasureAsync() method.

For example:

      auto qosMeasurement = ref new Windows::Networking::XboxLive::XboxLiveQualityOfServiceMeasurement();
      qosMeasurement->Metrics->Append(Windows::Networking::XboxLive::XboxLiveQualityOfServiceMetric::AverageInboundBitsPerSecond);
      qosMeasurement->Metrics->Append(Windows::Networking::XboxLive::XboxLiveQualityOfServiceMetric::AverageOutboundBitsPerSecond);
      qosMeasurement->Metrics->Append(Windows::Networking::XboxLive::XboxLiveQualityOfServiceMetric::AverageLatencyInMilliseconds);
      qosMeasurement->NumberOfProbesToAttempt = myDefaultQosProbeCount;
      qosMeasurement->TimeoutInMilliseconds = myDefaultQosMeasurementTimeout;

      // Add secure addresses for each session member
      for (const auto& member : session->GetMembers())
      {
        if (!member->IsCurrentUser)
        {
          auto sda = member->SecureDeviceAddressBase64;
          if (!sda->IsEmpty())
          {
      qosMeasurement->DeviceAddresses->Append(Windows::Networking::XboxLive::XboxLiveDeviceAddress::CreateFromSnapshotBase64(sda));
          }
        }
      }
      if (qosMeasurement->DeviceAddresses->Size > 0)
      {
        qosMeasurement->MeasureAsync();
      }  

For more examples, see the MatchmakingSession::MeasureQualityOfService() and MatchmakingSession::ProcessQosMeasurements() functions in the NetRumble sample.

Writing game events

Sending game events that are configured in your title’s Service Configuration has a different API in UWP. The Xbox Live SDK uses the EventsService and a property bag model.

For example:

      auto properties = ref new Windows::Foundation::Collections::PropertySet();
      properties->Insert("RoundId", m_roundId);
      properties->Insert("SectionId", safe_cast<Platform::Object^>(0));
      properties->Insert("MultiplayerCorrelationId", m_multiplayerCorrelationId);
      properties->Insert("GameplayModeId", safe_cast<Platform::Object^>(0));
      properties->Insert("MatchTypeId", safe_cast<Platform::Object^>(0));
      properties->Insert("DifficultyLevelId", safe_cast<Platform::Object^>(0));
      auto measurements = ref new Windows::Foundation::Collections::PropertySet();
      xblContext->EventsService->WriteInGameEvent("MultiplayerRoundStart", properties, measurements);  

For more information, see the Xbox Live SDK documentation.

Note You can use the xcetool.exe provided with the Xbox Live SDK (located in the Tools directory) to convert the events.man file that you downloaded from XDP into a .h header file. Use the ‘-x’ option to generate this C++ header by using the new v2 property bag schema. This header contains C++ functions that you can call for all of your configured events; for example, EventWriteMultiplayerRoundStart(). If you prefer to use a WinRT interface, you can still refer to this header file to see how the properties and measurements are constructed for each of your events.

Connected storage

The Connected Storage API is provided in the separate Xbox Live Platform Extensions SDK. Documentation is included in the Xbox Live SDK docs.

The overall flow is the same as on Xbox One, with the addition of the ContainersChangedSinceLastSync property in the UWP version. This property should be checked when your title handles a resume event, after calling GetForUserAsync() again, to see what containers changed in the cloud while your title was suspended. If you have data loaded in memory from one of the containers that changed, you probably want to read in the data again to see what changed and handle the changes accordingly.

Other notable differences in the UWP version include:

  1. Namespace change from Windows::Xbox::Storage to Windows::Gaming::XboxLive::Storage.
  2. ConnectedStorageSpace is renamed GameSaveProvider.
  3. Windows::System::User is used in GetForUserAsync() instead of an XboxUser, and the SCID is now required.
  4. No local “machine” storage (that is, GetForMachineAsync() has been removed). Consider using Windows::Storage::ApplicationData instead for your non-roaming, local save data.
  5. Async results are returned in an exception-free *Result-type object (for example, GameSaveProviderGetResult); from this you can check the Status property, and if there is no error, read the returned object from the Value property.
  6. ConnectedStorageErrorStatus enum is renamed GameSaveErrorStatus and is returned in the Status property of a Result. All the old values exist, and a few new ones have been added:
    • Abort
    • ObjectExpired
    • Ok
    • UserHasNoXboxLiveInfo

Refer to the GameSave sample or the NetRumble sample for example usage.

Note Gamesaveutil.exe is the equivalent to xbstorage.exe (the command-line developer utility included with the XDK). After installing the Xbox Live Platform Extensions SDK, this utility can be found here: C:\Program Files (x86)\Windows Kits\10\Extension SDKs\XboxLive\1.0\Bin\x64

Summary

The API changes and new requirements outlined in this white paper are ones that you are likely to encounter when porting existing game code from the Xbox One XDK to the new UWP. Particular emphasis has been given to application and environment setup, as well as feature areas related to Xbox Live services, such as multiplayer and connected storage. For more information, follow the links provided throughout this article and in the following references, and be sure to visit the “Windows 10” section of the developer forums for more help, answers, and news.

References