Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Cet article fournit des instructions complètes pour les développeurs internes et tiers sur la façon d’intégrer des fonctionnalités à l’aide du Kit de développement logiciel (SDK) De continuité dans vos applications. Le Kit de développement logiciel (SDK) De continuité permet d’effectuer des expériences inter-appareils transparentes, ce qui permet aux utilisateurs de reprendre des activités sur différentes plateformes, notamment Android et Windows.
En suivant ces conseils, vous pouvez créer une expérience utilisateur fluide et intégrée sur plusieurs appareils en tirant parti du XDR à l’aide du Kit de développement logiciel (SDK) de continuité.
Important
L'intégration reprend dans Windows
La reprise est une fonctionnalité d'accès limité (LAF). Pour obtenir access à cette API, vous devez obtenir l'approbation de Microsoft pour interagir avec le package « Lien vers Windows » sur les appareils mobiles Android.
Pour demander access, envoyez un e-mail wincrossdeviceapi@microsoft.com avec les informations répertoriées ci-dessous :
- Description de votre expérience utilisateur
- Capture d’écran de votre application où un utilisateur accède en mode natif au web ou aux documents
- PackageId de votre application
- URL du Google Play Store pour votre application
Si la demande est approuvée, vous recevrez des instructions sur la façon de déverrouiller la fonctionnalité. Les approbations seront basées sur votre communication, à condition que votre scénario réponde aux exigences du scénario décrites.
Prerequisites
Pour les applications Android, vérifiez que les exigences suivantes sont remplies avant d’intégrer le Kit de développement logiciel (SDK) de continuité :
- Version minimale du Kit de développement logiciel (SDK) : 24
- Version de Kotlin : 1.9.x
- Lien vers Windows (LTW) : 1.241101.XX
Pour les applications Windows, vérifiez que les exigences suivantes sont remplies :
- Version minimale de Windows : Windows 11
- Environnement de développement : Visual Studio 2019 ou version ultérieure
Note
Les applications iOS ne sont pas prises en charge pour l’intégration avec le Kit de développement logiciel (SDK) de continuité pour l’instant.
Configurer votre environnement de développement
Les sections suivantes fournissent des instructions pas à pas pour configurer l’environnement de développement pour les applications Android et Windows.
Configuration d'Android
Pour configurer l’environnement de développement pour Android, procédez comme suit :
Pour configurer l’offre groupée, téléchargez et utilisez le fichier .aar via les bibliothèques fournies dans les versions suivantes : Versions du Kit de développement logiciel (SDK) inter-appareils windows.
Ajoutez les balises meta dans le fichier AndroidManifest.xml de votre application Android. L’extrait de code suivant montre comment ajouter les balises meta requises :
<meta-data android:name="com.microsoft.crossdevice.resumeActivityProvider" android:value="true" /> <meta-data android:name="com.microsoft.crossdevice.trigger.PartnerApp" android:value="4" />
Étapes d’intégration d’API
Après les déclarations de manifeste, les développeurs d’applications peuvent facilement envoyer leur contexte d’application en suivant un exemple de code simple.
L’application doit :
- Initialize/DeInitialize the Continuity SDK :
- L’application doit déterminer le moment approprié pour appeler les fonctions Initialize et DeInitialize.
- Après avoir appelé la fonction Initialize, un rappel qui implémente IAppContextEventHandler doit être déclenché.
- Envoyer/supprimer AppContext :
- Après avoir initialisé le SDK, si onContextRequestReceived est appelé, il indique que la connexion est établie. L’application peut ensuite envoyer (y compris créer et mettre à jour) AppContext à LTW ou supprimer AppContext à partir de LTW.
- S’il n’existe aucune connexion entre le téléphone et le PC et que l’application envoie AppContext à LTW, l’application reçoit onContextResponseError avec le message « PC n’est pas connecté ».
- Lorsque la connexion est rétablie, onContextRequestReceived est appelé à nouveau. L’application peut ensuite envoyer l’appContext actuel à LTW.
- Après onSyncServiceDisconnected ou désinitialisation du Kit de développement logiciel (SDK), l’application ne doit pas envoyer un AppContext.
Voici un exemple de code. Pour tous les champs obligatoires et facultatifs dans AppContext, reportez-vous à la description AppContext.
L’extrait de code Android suivant montre comment effectuer des demandes d’API à l’aide du Kit de développement logiciel (SDK) de continuité :
import android.os.Bundle
import android.util.Log
import android.widget.Button
import android.widget.TextView
import android.widget.Toast
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.Observer
import com.microsoft.crossdevicesdk.continuity.AppContext
import com.microsoft.crossdevicesdk.continuity.AppContextManager
import com.microsoft.crossdevicesdk.continuity.ContextRequestInfo
import com.microsoft.crossdevicesdk.continuity.IAppContextEventHandler
import com.microsoft.crossdevicesdk.continuity.IAppContextResponse
import com.microsoft.crossdevicesdk.continuity.LogUtils
import com.microsoft.crossdevicesdk.continuity.ProtocolConstants
import java.util.UUID
class MainActivity : AppCompatActivity() {
//Make buttons member variables ---
private lateinit var buttonSend: Button
private lateinit var buttonDelete: Button
private lateinit var buttonUpdate: Button
private val appContextResponse = object : IAppContextResponse {
override fun onContextResponseSuccess(response: AppContext) {
Log.d("MainActivity", "onContextResponseSuccess")
runOnUiThread {
Toast.makeText(
this@MainActivity,
"Context response success: ${response.contextId}",
Toast.LENGTH_SHORT
).show()
}
}
override fun onContextResponseError(response: AppContext, throwable: Throwable) {
Log.d("MainActivity", "onContextResponseError: ${throwable.message}")
runOnUiThread {
Toast.makeText(
this@MainActivity,
"Context response error: ${throwable.message}",
Toast.LENGTH_SHORT
).show()
// Check if the error message contains the specific string
if (throwable.message?.contains("PC is not connected") == true) {
//App should stop sending intent once this callback is received
}
}
}
}
private lateinit var appContextEventHandler: IAppContextEventHandler
private val _currentAppContext = MutableLiveData<AppContext?>()
private val currentAppContext: LiveData<AppContext?> get() = _currentAppContext
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContentView(R.layout.activity_main)
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}
LogUtils.setDebugMode(true)
var ready = false
buttonSend = findViewById(R.id.buttonSend)
buttonDelete = findViewById(R.id.buttonDelete)
buttonUpdate = findViewById(R.id.buttonUpdate)
setButtonDisabled(buttonSend)
setButtonDisabled(buttonDelete)
setButtonDisabled(buttonUpdate)
buttonSend.setOnClickListener {
if (ready) {
sendResumeActivity()
}
}
buttonDelete.setOnClickListener {
if (ready) {
deleteResumeActivity()
}
}
buttonUpdate.setOnClickListener {
if (ready) {
updateResumeActivity()
}
}
appContextEventHandler = object : IAppContextEventHandler {
override fun onContextRequestReceived(contextRequestInfo: ContextRequestInfo) {
LogUtils.d("MainActivity", "onContextRequestReceived")
ready = true
setButtonEnabled(buttonSend)
setButtonEnabled(buttonDelete)
setButtonEnabled(buttonUpdate)
}
override fun onInvalidContextRequestReceived(throwable: Throwable) {
Log.d("MainActivity", "onInvalidContextRequestReceived")
}
override fun onSyncServiceDisconnected() {
Log.d("MainActivity", "onSyncServiceDisconnected")
ready = false
setButtonDisabled(buttonSend)
setButtonDisabled(buttonDelete)
}
}
// Initialize the AppContextManager
AppContextManager.initialize(this.applicationContext, appContextEventHandler)
// Update currentAppContext text view.
val textView = findViewById<TextView>(R.id.appContext)
currentAppContext.observe(this, Observer { appContext ->
appContext?.let {
textView.text =
"Current app context: ${it.contextId}\n App ID: ${it.appId}\n Created: ${it.createTime}\n Updated: ${it.lastUpdatedTime}\n Type: ${it.type}"
Log.d("MainActivity", "Current app context: ${it.contextId}")
} ?: run {
textView.text = "No current app context available"
Log.d("MainActivity", "No current app context available")
}
})
}
// Send resume activity to LTW
private fun sendResumeActivity() {
val appContext = AppContext().apply {
this.contextId = generateContextId()
this.appId = applicationContext.packageName
this.createTime = System.currentTimeMillis()
this.lastUpdatedTime = System.currentTimeMillis()
this.type = ProtocolConstants.TYPE_RESUME_ACTIVITY
}
_currentAppContext.value = appContext
AppContextManager.sendAppContext(this.applicationContext, appContext, appContextResponse)
}
// Delete resume activity from LTW
private fun deleteResumeActivity() {
currentAppContext.value?.let {
AppContextManager.deleteAppContext(
this.applicationContext,
it.contextId,
appContextResponse
)
_currentAppContext.value = null
} ?: run {
Toast.makeText(this, "No resume activity to delete", Toast.LENGTH_SHORT).show()
Log.d("MainActivity", "No resume activity to delete")
}
}
private fun updateResumeActivity() {
currentAppContext.value?.let {
it.lastUpdatedTime = System.currentTimeMillis()
AppContextManager.sendAppContext(this.applicationContext, it, appContextResponse)
_currentAppContext.postValue(it)
} ?: run {
Toast.makeText(this, "No resume activity to update", Toast.LENGTH_SHORT).show()
Log.d("MainActivity", "No resume activity to update")
}
}
private fun setButtonDisabled(button: Button) {
button.isEnabled = false
button.alpha = 0.5f
}
private fun setButtonEnabled(button: Button) {
button.isEnabled = true
button.alpha = 1.0f
}
override fun onDestroy() {
super.onDestroy()
// Deinitialize the AppContextManager
AppContextManager.deInitialize(this.applicationContext)
}
override fun onStart() {
super.onStart()
// AppContextManager.initialize(this.applicationContext, appContextEventHandler)
}
override fun onStop() {
super.onStop()
// AppContextManager.deInitialize(this.applicationContext)
}
private fun generateContextId(): String {
return "${packageName}.${UUID.randomUUID()}"
}
}
Étapes de validation d’intégration
Pour valider l’intégration du Kit de développement logiciel (SDK) de continuité dans votre application, procédez comme suit :
Préparation
Les étapes suivantes sont requises pour préparer la validation d’intégration :
Assurez-vous que le LTW privé est installé.
Connectez LTW à votre PC :
Pour obtenir des instructions, consultez Comment gérer votre appareil mobile sur votre PC .
Note
Si après avoir analysé le code QR, vous n’êtes pas redirigé vers LTW, ouvrez D’abord LTW et scannez le code QR dans l’application.
Vérifiez que l’application partenaire a intégré le Kit de développement logiciel (SDK) de continuité.
Validation
Ensuite, procédez comme suit pour valider l’intégration :
- Lancez l’application et initialisez le Kit de développement logiciel (SDK). Vérifiez que onContextRequestReceived est appelé.
- Après l'appel de onContextRequestReceived, l'application peut envoyer AppContext à LTW. Si onContextResponseSuccess est appelé après l’envoi d’AppContext, l’intégration du SDK réussit.
- Si l’application envoie AppContext pendant que le PC est verrouillé ou déconnecté, vérifiez que onContextResponseError est appelé avec « PC n’est pas connecté ».
- Lorsque la connexion est restaurée, vérifiez que onContextRequestReceived est appelé à nouveau et que l’application peut ensuite envoyer l’appContext actuel à LTW.
La capture d’écran ci-dessous montre l’entrée de journal lorsque le PC est déconnecté avec le message d’erreur « PC n’est pas connecté » et l’entrée de journal après la reconnexion lorsque onContextRequestReceived est appelé à nouveau.
AppContext
XDR définit AppContext comme métadonnées par le biais de laquelle XDR peut comprendre l’application à reprendre, ainsi que le contexte avec lequel l’application doit être reprise. Les applications peuvent utiliser des activités pour permettre aux utilisateurs de revenir à ce qu’ils faisaient dans leur application, sur plusieurs appareils. Les activités créées par n’importe quelle application mobile s’affichent sur les appareils Windows des utilisateurs tant que ces appareils ont été approvisionnés par l’hôte d’expérience inter-appareils (CDEH).
Chaque application est différente, et c'est à Windows de comprendre l'application cible pour la reprise, tandis que certaines applications spécifiques sur Windows doivent comprendre le contexte. XDR propose un schéma générique qui peut répondre aux exigences pour tous les scénarios de reprise d’application tiers ainsi que pour tous les scénarios de reprise d’application tiers.
contextId
- Obligatoire : Oui
- Description : il s’agit d’un identificateur unique utilisé pour distinguer un AppContext d’un autre. Il garantit que chaque AppContext est identifiable de façon unique.
- Utilisation : veillez à générer un contextId unique pour chaque AppContext afin d’éviter les conflits.
type
- Obligatoire : Oui
- Description : il s’agit d’un indicateur binaire qui indique le type d’AppContext envoyé à Link to Windows (LTW). La valeur doit être cohérente avec le TypeContextType demandé.
- Utilisation : définissez cet indicateur en fonction du type de contexte que vous envoyez. Par exemple :
ProtocolConstants.TYPE_RESUME_ACTIVITY.
createTime
- Obligatoire : Oui
- Description : cet horodatage représente l’heure de création de l’AppContext.
- Utilisation : enregistrez l’heure exacte à laquelle AppContext est créé.
intentUri
- Obligatoire : Non, si weblink est fourni
- Description : cet URI indique l’application qui peut continuer le AppContext transmis par l’appareil d’origine.
- Utilisation : indiquez cette option si vous souhaitez spécifier une application particulière pour gérer le contexte.
weblink
- Obligatoire : Non, si intentUri est fourni
- Description : cet URI est utilisé pour lancer le point de terminaison web de l’application s’ils choisissent de ne pas utiliser d’applications du Store. Ce paramètre est utilisé uniquement lorsque intentUri n’est pas fourni. Si les deux sont fournis, intentUri sera utilisé pour reprendre l’application sur Windows.
- Utilisation : à utiliser uniquement si l’application souhaite reprendre sur les points de terminaison web et non les applications de magasin.
appId
- Obligatoire : Oui
- Description : il s’agit du nom du package de l’application pour laquelle le contexte est destiné.
- Utilisation : définissez ce paramètre sur le nom du package de votre application.
title
- Obligatoire : Oui
- Description : il s’agit du titre d’AppContext, tel qu’un nom de document ou un titre de page web.
- Utilisation : fournissez un titre explicite qui représente AppContext.
Aperçu
- Obligatoire : Non
- Description : Il s’agit d’octets de l’image d’aperçu qui peuvent représenter AppContext.
- Utilisation : fournissez une image d’aperçu si elle est disponible pour donner aux utilisateurs une représentation visuelle de l’AppContext.
Durée de vie
- Obligatoire : Non
- Description : il s'agit de la durée de vie du
AppContexten millisecondes. Il est utilisé uniquement pour les scénarios en cours. Si elle n’est pas définie, la valeur par défaut est de 5 minutes. - Utilisation : définissez cette valeur pour définir la durée pendant laquelle la
AppContextvaleur doit être valide. Vous pouvez définir une valeur jusqu’à un maximum de 5 minutes. Toute valeur supérieure sera automatiquement raccourcie à 5 minutes.
URI d’intention
Les URI vous permettent de lancer une autre application pour effectuer une tâche spécifique, ce qui permet des scénarios d’application à application utiles. Pour plus d’informations sur le lancement d’applications à l’aide d’URI, consultez Lancer l’application Windows par défaut pour un URI et Créer des liens profonds vers le contenu de l'application | Développeurs Android.
Gestion des réponses d’API dans Windows
Cette section explique comment gérer les réponses d’API dans les applications Windows. Le Kit de développement logiciel (SDK) de continuité fournit un moyen de gérer les réponses d’API pour les applications Win32, UWP et Windows App SDK.
Exemple d’application Win32
Pour que les applications Win32 gèrent le lancement de l’URI du protocole, les étapes suivantes sont requises :
Tout d’abord, une entrée doit être effectuée dans le Registre comme suit :
[HKEY_CLASSES_ROOT\partnerapp] @="URL:PartnerApp Protocol" "URL Protocol"="" [HKEY_CLASSES_ROOT\partnerapp\shell\open\command] @="\"C:\\path\\to\\PartnerAppExecutable.exe\" \"%1\""Le lancement doit être géré dans la fonction principale de l’application Win32 :
#include <windows.h> #include <shellapi.h> #include <string> #include <iostream> int CALLBACK wWinMain(HINSTANCE, HINSTANCE, PWSTR lpCmdLine, int) { // Check if there's an argument passed via lpCmdLine std::wstring cmdLine(lpCmdLine); std::wstring arguments; if (!cmdLine.empty()) { // Check if the command-line argument starts with "partnerapp://", indicating a URI launch if (cmdLine.find(L"partnerapp://") == 0) { // This is a URI protocol launch // Process the URI as needed // Example: Extract action and parameters from the URI arguments = cmdLine; // or further parse as required } else { // Launched by command line or activation APIs } } else { // Handle cases where no arguments were passed } return 0; }
Applications UWP
Pour les applications UWP, l'URI de protocole peut être inscrit dans le manifeste de l'application de project. Les étapes suivantes montrent comment gérer l’activation du protocole dans une application UWP.
Tout d’abord, l’URI du protocole est inscrit dans le
Package.appxmanifestfichier comme suit :<Applications> <Application Id= ... > <Extensions> <uap:Extension Category="windows.protocol"> <uap:Protocol Name="alsdk"> <uap:Logo>images\icon.png</uap:Logo> <uap:DisplayName>SDK Sample URI Scheme</uap:DisplayName> </uap:Protocol> </uap:Extension> </Extensions> ... </Application> <Applications>Ensuite, dans le
App.xaml.csfichier, remplacez laOnActivatedméthode comme suit :public partial class App { protected override void OnActivated(IActivatedEventArgs args) { if (args.Kind == ActivationKind.Protocol) { ProtocolActivatedEventArgs eventArgs = args as ProtocolActivatedEventArgs; // TODO: Handle URI activation // The received URI is eventArgs.Uri.AbsoluteUri } } }
Pour plus d’informations sur la gestion du lancement d’URI dans les applications UWP, consultez l’étape 3 dans Gérer l’activation d’URI.
Exemple WinUI 3
L’extrait de code suivant montre comment gérer l’activation du protocole dans une application WinUI C++ avec Windows App SDK :
void App::OnActivated(winrt::Windows::ApplicationModel::Activation::IActivatedEventArgs const& args)
{
if (args.Kind() == winrt::Windows::ApplicationModel::Activation::ActivationKind::Protocol)
{
auto protocolArgs = args.as<winrt::Windows::ApplicationModel::Activation::ProtocolActivatedEventArgs>();
auto uri = protocolArgs.Uri();
std::wstring uriString = uri.AbsoluteUri().c_str();
//Process the URI as per argument scheme
}
}
Weblink
L’utilisation d’un lien web lance le point de terminaison web de l’application. Les développeurs d’applications doivent s’assurer que le lien web fourni à partir de leur application Android est valide, car XDR utilise le navigateur par défaut du système pour rediriger vers le weblink fourni.
Gestion des arguments obtenus à partir de Cross Device Resume
Il incombe à chaque application de désérialiser et de déchiffrer l’argument reçu et de traiter les informations en conséquence pour transférer le contexte continu du téléphone vers le PC. Par exemple, si un appel doit être transféré, l’application doit être en mesure de communiquer ce contexte à partir du téléphone et de l’application de bureau doit comprendre ce contexte de manière appropriée et continuer le chargement.
Contenu connexe
Windows developer