Skip to content

Commit e933993

Browse files
[DO NOT MERGE until release] Add Cross Device Resume (XDR) topic (#5336)
* Add initial draft of cross device resume doc * resume updates * Remove internal note * Update XDR topic from updated document * Remove todo section * Change appId to required * Add onboarding info for android apps * Add scenario requirements link * Update usage max time --------- Co-authored-by: Matt Wojciakowski <[email protected]>
1 parent debe4e7 commit e933993

File tree

3 files changed

+381
-4
lines changed

3 files changed

+381
-4
lines changed
Lines changed: 366 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,366 @@
1+
---
2+
title: Cross Device Resume (XDR) Using Continuity SDK
3+
description: Guidelines for first & third party developers to integrate with Windows XDR experiences using the Continuity SDK.
4+
ms.date: 08/12/2025
5+
ms.topic: how-to
6+
# customer intent: As a Windows developer, I want to learn how to integrate my app with Windows XDR experiences so that I can provide a seamless experience for my users.
7+
---
8+
9+
# Cross Device Resume (XDR) using Continuity SDK (Android and Windows Applications)
10+
11+
This article provides comprehensive guidelines for first-party and third-party developers on how to integrate features using the Continuity SDK in your applications. The Continuity SDK enables seamless cross-device experiences, allowing users to resume activities across different platforms, including Android and Windows.
12+
13+
By following this guidance, you can create a smooth and integrated user experience across multiple devices by leveraging the XDR using Continuity SDK.
14+
15+
> [!IMPORTANT]
16+
> **Onboarding to Resume in Windows**
17+
>
18+
> Resume is a Limited Access Feature (LAF). To gain access to this API, you'll need to get approval from Microsoft to interoperate with the "Link to Windows" package on Android mobile devices.
19+
>
20+
> To request access, email [[email protected]](mailto:[email protected]) with the information listed below:
21+
>
22+
> - A description of your user experience
23+
> - A screenshot of your application where a user natively accesses web or documents
24+
> - The **PackageId** of your application
25+
> - The Google Play store URL for your application
26+
>
27+
> If the request is approved, you will receive instructions on how to unlock the feature. Approvals will be based on your communication, provided that your scenario meets the outlined [Scenario Requirements](/windows/cross-device/phonelink/#scenario-requirements).
28+
29+
## Prerequisites
30+
31+
For Android applications, ensure the following requirements are met before integrating the Continuity SDK:
32+
33+
- Minimum SDK Version: 24
34+
- Kotlin Version: 1.9.x
35+
- Link to Windows (LTW): 1.241101.XX
36+
37+
For Windows applications, ensure the following requirements are met:
38+
39+
- Minimum Windows Version: Windows 11
40+
- Development Environment: Visual Studio 2019 or later
41+
42+
> [!NOTE]
43+
> iOS applications are not supported for integration with the Continuity SDK at this time.
44+
45+
## Configure your development environment
46+
47+
The following sections provide step-by-step instructions for setting up the development environment for both Android and Windows applications.
48+
49+
### Android setup
50+
51+
To set up the development environment for Android, follow these steps:
52+
53+
1. To set up the bundle, download and use the .aar file via libraries provided in the following releases: [Windows Cross-Device SDK releases](https://github.com/microsoft/Windows-Cross-Device/releases).
54+
55+
1. Add the meta tags in the AndroidManifest.xml file of your Android application. The following snippet demonstrates how to add the required meta tags:
56+
57+
```xml
58+
<meta-data
59+
android:name="com.microsoft.crossdevice.resumeActivityProvider"
60+
android:value="true" />
61+
62+
<meta-data
63+
android:name="com.microsoft.crossdevice.trigger.PartnerApp"
64+
android:value="4" />
65+
```
66+
67+
## API integration steps
68+
69+
After the manifest declarations, app developers can easily send their app context by following a simple code example.
70+
71+
The App must:
72+
73+
1. Initialize/DeInitialize the Continuity SDK:
74+
1. The app should determine the appropriate time to call the Initialize and DeInitialize functions.
75+
1. After calling the Initialize function, a callback that implements IAppContextEventHandler should be triggered.
76+
1. Send/Delete **AppContext**:
77+
1. After initializing the SDK, if **onContextRequestReceived** is called, it indicates the connection is established. The app can then send (including create and update) **AppContext** to LTW or delete **AppContext** from LTW.
78+
1. After **onSyncServiceDisconnected** or deinitializing the SDK, the app should not send an **AppContext**.
79+
80+
Below is a code example. For all the required and optional fields in **AppContext**, please refer to the [AppContext description](#appcontext).
81+
82+
The following Android code snippet demonstrates how to make API requests using the Continuity SDK:
83+
84+
```kotlin MainActivity.kt
85+
class MainActivity : ComponentActivity() {
86+
87+
// Required code for Continuity SDK integration
88+
private val appContextResponse = object : IAppContextResponse {
89+
override fun onContextResponseSuccess(response: AppContext) {
90+
Log.d("MainActivity", "onContextResponseSuccess")
91+
}
92+
93+
override fun onContextResponseError(response: AppContext, throwable: Throwable) {
94+
Log.d("MainActivity", "onContextResponseError")
95+
}
96+
}
97+
98+
private lateinit var appContextEventHandler: IAppContextEventHandler
99+
100+
private val appContext: AppContext = AppContext()
101+
102+
override fun onCreate(savedInstanceState: Bundle?) {
103+
super.onCreate(savedInstanceState)
104+
var ready = false
105+
// Existing code...
106+
107+
// Required code for Continuity SDK integration
108+
appContextEventHandler = object : IAppContextEventHandler {
109+
override fun onContextRequestReceived(contextRequestInfo: ContextRequestInfo) {
110+
Log.d("MainActivity", "onContextRequestReceived")
111+
ready = true
112+
113+
sendResume()
114+
}
115+
116+
override fun onSyncServiceDisconnected() {
117+
Log.d("MainActivity", "onSyncServiceDisconnected")
118+
}
119+
120+
override fun onInvalidContextRequestReceived(throwable: Throwable) {
121+
Log.d("MainActivity", "onInvalidContextRequestReceived")
122+
ready = false
123+
deleteResume()
124+
}
125+
}
126+
127+
// Required code for Continuity SDK integration
128+
AppContextManager.initialize(this.applicationContext, appContextEventHandler)
129+
}
130+
131+
// Required code for Continuity SDK integration
132+
private fun sendResume() {
133+
appContext.setContextId("13f53be4-d0d1-448a-8c78-af28820af119")
134+
appContext.setAppId(this.packageName)
135+
appContext.type = ProtocolConstants.TYPE_RESUME_ACTIVITY
136+
137+
// Set context fields. Refer to the AppContext section for detailed field descriptions.
138+
AppContextManager.sendAppContext(this.applicationContext, appContext, appContextResponse)
139+
}
140+
141+
// Required code for Continuity SDK integration
142+
private fun deleteResume() {
143+
AppContextManager.deleteAppContext(this.applicationContext, "13f53be4-d0d1-448a-8c78-af28820af119", appContextResponse)
144+
}
145+
146+
// Existing code
147+
}
148+
```
149+
150+
## Integration validation steps
151+
152+
To validate the integration of the Continuity SDK in your application, follow these steps:
153+
154+
### Preparation
155+
156+
The following steps are required to prepare for the integration validation:
157+
158+
1. Ensure private LTW is installed.
159+
1. Connect LTW to your PC:
160+
161+
Refer to [How to manage your mobile device on your PC](https://support.microsoft.com/topic/phone-link-requirements-and-setup-cd2a1ee7-75a7-66a6-9d4e-bf22e735f9e3#bkmk_cdeh_learn_more) for instructions.
162+
163+
> [!NOTE]
164+
> If after scanning the QR code you aren't redirected to LTW, please open LTW first and scan the QR code within the app.
165+
166+
1. Verify that the partner app has integrated the Continuity SDK.
167+
168+
### Validation
169+
170+
Next, follow these steps to validate the integration:
171+
172+
1. Launch the app and initialize the SDK. Confirm that **onContextRequestReceived** is called.
173+
1. After **onContextRequestReceived** has been called, the app can send the **AppContext** to LTW. If **onContextResponseSuccess** is called after sending **AppContext**, the SDK integration is successful.
174+
175+
## AppContext
176+
177+
XDR defines **AppContext** as metadata through which XDR can understand which app to resume, along with the context with which the application must be resumed. Apps can use activities to enable users to get back to what they were doing in their app, across multiple devices. Activities created by any mobile app appear on users' Windows device(s) so long as those devices have been Cross Device Experience Host (CDEH) provisioned.  
178+
179+
Every application is different, and it's up to Windows to understand the target application for resume and up to specific applications on Windows to understand the context. XDR is proposing a generic schema which can cater to requirements for all first party as well as third party app resume scenarios.
180+
181+
### contextId
182+
183+
- Required: Yes
184+
- Description: This is a unique identifier used to distinguish one **AppContext** from another. It ensures that each **AppContext** is uniquely identifiable.
185+
- Usage: Make sure to generate a unique contextId for each **AppContext** to avoid conflicts.
186+
187+
### type
188+
189+
- Required: Yes
190+
- Description: This is a binary flag that indicates the type of **AppContext** being sent to Link to Windows (LTW). The value should be consistent with the requestedContextType.
191+
- Usage: Set this flag according to the type of context you are sending. For example, `ProtocolConstants.TYPE_RESUME_ACTIVITY`.
192+
193+
### createTime
194+
195+
- Required: Yes
196+
- Description: This timestamp represents the creation time of the **AppContext**.
197+
- Usage: Record the exact time when the **AppContext** is created.
198+
199+
### intentUri
200+
201+
- Required: No, if **weblink** is provided
202+
- Description: This URI indicates which app can continue the **AppContext** handed over from the originating device.
203+
- Usage: Provide this if you want to specify a particular app to handle the context.
204+
205+
### weblink
206+
207+
- Required: No, if **intentUri** is provided
208+
- Description: This URI is used to launch the web endpoint of the application if they choose not to use store apps. This parameter is used only when **intentUri** is not provided. If both are provided, **intentUri** will be used to resume the application on Windows.
209+
- Usage: Only to be use if application wants to resume on web endpoints and not the store applications.
210+
211+
### appId
212+
213+
- Required: Yes
214+
- Description: This is the package name of the application the context is for.
215+
- Usage: Set this to the package name of your application.
216+
217+
### title
218+
219+
- Required: Yes
220+
- Description: This is the title of the **AppContext**, such as a document name or web page title.
221+
- Usage: Provide a meaningful title that represents the **AppContext**.
222+
223+
### preview
224+
225+
- Required: No
226+
- Description: These are bytes of the preview image that can represent the **AppContext**.
227+
- Usage: Provide a preview image if available to give users a visual representation of the **AppContext**.
228+
229+
### LifeTime
230+
231+
- Required: No
232+
- Description: This is the lifetime of the `AppContext` in milliseconds. It is only used for ongoing scenarios. If not set, the default value is 5 minutes.
233+
- Usage: Set this to define how long the `AppContext` should be valid. You can set a value up to a maximum of 5 minutes. Any greater value will automatically be shortened to 5 minutes.
234+
235+
## Intent URIs
236+
237+
URIs allow you to launch another app to perform a specific task, enabling helpful app-to-app scenarios. For more infomation about launching apps using URIs, see [Launch the default Windows app for a URI](/windows/apps/develop/launch/launch-default-app) and [Create Deep Links to App Content | Android Developers](https://developer.android.com/training/app-links/deep-linking).
238+
239+
## Handling API responses in Windows
240+
241+
This section describes how to handle the API responses in Windows applications. The Continuity SDK provides a way to handle the API responses for Win32, UWP, and Windows App SDK apps.
242+
243+
### Win32 app example
244+
245+
For Win32 apps to handle protocol URI launch, the following steps are required:
246+
247+
1. First, an entry needs to be made to the registry as follows:
248+
249+
```
250+
[HKEY_CLASSES_ROOT\partnerapp]
251+
@="URL:PartnerApp Protocol"
252+
"URL Protocol"=""
253+
254+
[HKEY_CLASSES_ROOT\partnerapp\shell\open\command]
255+
@="\"C:\\path\\to\\PartnerAppExecutable.exe\" \"%1\""
256+
```
257+
258+
1. The launch must be handled in the main function of the Win32 app:
259+
260+
```cpp
261+
#include <windows.h>
262+
#include <shellapi.h>
263+
#include <string>
264+
#include <iostream>
265+
266+
int CALLBACK wWinMain(HINSTANCE, HINSTANCE, PWSTR lpCmdLine, int)
267+
{
268+
// Check if there's an argument passed via lpCmdLine
269+
std::wstring cmdLine(lpCmdLine);
270+
std::wstring arguments;
271+
272+
if (!cmdLine.empty())
273+
{
274+
// Check if the command-line argument starts with "partnerapp://", indicating a URI launch
275+
if (cmdLine.find(L"partnerapp://") == 0)
276+
{
277+
// This is a URI protocol launch
278+
// Process the URI as needed
279+
// Example: Extract action and parameters from the URI
280+
arguments = cmdLine; // or further parse as required
281+
}
282+
else
283+
{
284+
// Launched by command line or activation APIs
285+
}
286+
}
287+
else
288+
{
289+
// Handle cases where no arguments were passed
290+
}
291+
292+
return 0;
293+
}
294+
```
295+
296+
### UWP Apps
297+
298+
For UWP apps, the protocol URI can be registered in the project's app manifest. The following steps demonstrate how to handle protocol activation in a UWP app.
299+
300+
1. First, the protocol URI is registered in the `Package.appxmanifest` file as follows:
301+
302+
```xml
303+
<Applications>
304+
<Application Id= ... >
305+
<Extensions>
306+
<uap:Extension Category="windows.protocol">
307+
<uap:Protocol Name="alsdk">
308+
<uap:Logo>images\icon.png</uap:Logo>
309+
<uap:DisplayName>SDK Sample URI Scheme</uap:DisplayName>
310+
</uap:Protocol>
311+
</uap:Extension>
312+
</Extensions>
313+
...
314+
</Application>
315+
<Applications>
316+
```
317+
318+
1. Next, in the `App.xaml.cs` file, override the `OnActivated` method as follows:
319+
320+
```csharp
321+
public partial class App
322+
{
323+
protected override void OnActivated(IActivatedEventArgs args)
324+
{
325+
if (args.Kind == ActivationKind.Protocol)
326+
{
327+
ProtocolActivatedEventArgs eventArgs = args as ProtocolActivatedEventArgs;
328+
// TODO: Handle URI activation
329+
// The received URI is eventArgs.Uri.AbsoluteUri
330+
}
331+
}
332+
}
333+
```
334+
335+
For more information on handling URI launch in UWP apps, see step 3 in [Handle URI activation](/windows/apps/develop/launch/handle-uri-activation#step-3-handle-the-activated-event).
336+
337+
### WinUI 3 example
338+
339+
The following code snippet demonstrates how to handle protocol activation in a C++ WinUI app with Windows App SDK:
340+
341+
```cpp
342+
void App::OnActivated(winrt::Windows::ApplicationModel::Activation::IActivatedEventArgs const& args)
343+
{
344+
if (args.Kind() == winrt::Windows::ApplicationModel::Activation::ActivationKind::Protocol)
345+
{
346+
auto protocolArgs = args.as<winrt::Windows::ApplicationModel::Activation::ProtocolActivatedEventArgs>();
347+
auto uri = protocolArgs.Uri();
348+
std::wstring uriString = uri.AbsoluteUri().c_str();
349+
//Process the URI as per argument scheme
350+
}
351+
}
352+
```
353+
354+
## Weblink
355+
356+
Using a weblink will launch the web endpoint of the application. App developers need to ensure that the weblink provided from their Android application is valid because XDR will use default browser of the system to redirect to the weblink provided.
357+
358+
## Handling arguments obtained from Cross Device Resume
359+
360+
It is the responsibility of each app to deserialize and decrypt the argument received and process the information accordingly to transfer the ongoing context from phone to PC. For example, if a call needs to be transferred, the app must be able to communicate that context from phone and the desktop app must understand that context appropriately and continue loading.
361+
362+
## Related content
363+
364+
- [Handle URI activation](/windows/apps/develop/launch/handle-uri-activation)
365+
- [Integrate with Windows](index.md)
366+
- [Cross Device People API](cross-device-people-api.md)

0 commit comments

Comments
 (0)