Updated March 1, 2016
In this topic:
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.
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.
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.
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.
The most common changes between the Xbox and UWP versions of the appxmanifest.xml file are:
<Dependencies>
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.10240.0" MaxVersionTested="10.0.10240.0" />
</Dependencies>
<DeviceCapability Name="microphone" />
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;
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 |
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.
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.
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.
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.
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 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.
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:
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:
ref new Microsoft::Xbox::Services::XboxLiveContext( Windows::Xbox::System::User^ user )
Windows::Xbox::System::User::SignOutStarted
Windows::Xbox::Input::Controller::ControllerRemoved
Windows::Xbox::Input::Controller::ControllerPairingChange
Now, for the UWP/Xbox Live SDK:
auto xblUser = ref new Microsoft::Xbox::Services::System::XboxLiveUser();
xblUser->SignInSilentlyAsync();
auto xblContext = ref new Microsoft::Xbox::Services::XboxLiveContext( xblUser );
xblUser->SignInAsync();
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 );
xblUser->SignOutCompleted += ref new Windows::Foundation::EventHandler<Microsoft::Xbox::Services::System::SignOutCompletedEventArgs^>( &OnSignOutCompleted );
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.
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.
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).
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.
To pop up the gamer profile card on UWP, use Microsoft::Xbox::Services::System::TitleCallableUI::ShowProfileCardUIAsync(), passing in the XUID for the target user.
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" />
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.
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.
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:
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
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.