Partager via


Lien ciblé à partir d’une application en arrière-plan dans Cortana vers une application au premier plan

Avertissement

Cette fonctionnalité n’est plus prise en charge à partir de la mise à jour Windows 10 Update de mai 2020 (version 2004, nom de code « 20H1 »).

Fournissez des liens profonds à partir d’une application en arrière-plan dans Cortana qui lance l’application au premier plan dans un état ou un contexte spécifique.

Remarque

Cortana et le service de l’application d’arrière-plan sont tous deux interrompus lorsque l’application de premier plan est lancée.

Un lien profond est affiché par défaut sur l’écran de complétion de Cortana, comme illustré ici (« Aller à AdventureWorks »), mais vous pouvez afficher des liens profonds sur d’autres écrans.

Capture d’écran de l’achèvement de l’application en arrière-plan Cortana pour un prochain voyage

Vue d’ensemble

Les utilisateurs peuvent accéder à votre application à partir de Cortana en :

Nous abordons ici un lien profond.

Les liens profonds sont utiles lorsque Cortana et votre service d’application servent de passerelle vers votre application complète (au lieu de demander à l’utilisateur de lancer l’application via le menu Démarrer), ou pour donner accès à des détails et des fonctionnalités plus riches dans votre application qui ne sont pas possibles à partir de Cortana. Les liens profonds sont un autre moyen d’améliorer la convivialité et de promouvoir votre application.

Il existe trois façons de fournir des liens profonds :

  • Un lien « Aller à <application> » sur les différents écrans de Cortana.
  • Lien intégré dans une vignette de contenu sur différents écrans Cortana.
  • Lancement programmé de l’application de premier plan à partir du service d’application d’arrière-plan.

Sur la plupart des écrans, Cortana affiche un lien profond « Aller à <application> » sous la carte de contenu.

Capture d’écran du lien profond Cortana « Accéder à l’application » sur un écran de saisie semi-automatique de l’application en arrière-plan.

Vous pouvez fournir un argument de lancement pour ce lien qui ouvre votre application dans un contexte similaire à celui du service d’application. Si vous ne fournissez pas d’argument de lancement, l’application est lancée sur l’écran principal.

Dans cet exemple tiré du fichier AdventureWorksVoiceCommandService.cs de l’échantillon AdventureWorks, nous transmettons la chaîne de destination (destination) spécifiée à la méthode SendCompletionMessageForDestination, qui récupère tous les trajets correspondants et fournit un lien profond vers l’application.

Tout d’abord, nous créons un VoiceCommandUserMessage (userMessage) qui est prononcé par Cortana et affiché sur le canevas de Cortana. Un objet liste VoiceCommandContentTile est ensuite créé pour afficher la collection de cartes de résultats sur l’espace.

Ces deux objets sont ensuite transmis à la méthode CreateResponse de l’objet VoiceCommandResponse (response). Nous définissons ensuite la valeur de la propriété AppLaunchArgument de l’objet réponse en fonction de la valeur destination transmise à cette fonction. Lorsqu’un utilisateur touche une vignette de contenu sur le canevas Cortana, les valeurs des paramètres sont transmises à l’application par l’intermédiaire de l’objet de réponse.

Enfin, nous appelons la méthode ReportSuccessAsync de la connexion VoiceCommandServiceConnection.

/// <summary>
/// Show details for a single trip, if the trip can be found. 
/// This demonstrates a simple response flow in Cortana.
/// </summary>
/// <param name="destination">The destination specified in the voice command.</param>
private async Task SendCompletionMessageForDestination(string destination)
{
...
    IEnumerable<Model.Trip> trips = store.Trips.Where(p => p.Destination == destination);

    var userMessage = new VoiceCommandUserMessage();
    var destinationsContentTiles = new List<VoiceCommandContentTile>();
...
    var response = VoiceCommandResponse.CreateResponse(userMessage, destinationsContentTiles);

    if (trips.Count() > 0)
    {
        response.AppLaunchArgument = destination;
    }

    await voiceServiceConnection.ReportSuccessAsync(response);
}

Vous pouvez ajouter des liens profonds aux cartes de contenu sur les différents écrans de Cortana.

Capture d’écran du canevas Cortana pour le flux d’application en arrière-plan Cortana de bout en bout à l’aide d’AdventureWorks à venir avec transfertAdventureWorks « Voyage à venir » avec écran de transfert

Comme pour les liens « Aller à <application> », vous pouvez fournir un argument de lancement pour ouvrir votre application dans un contexte similaire à celui du service d’application. Si vous ne fournissez pas d’argument de lancement, la vignette de contenu ne renvoie pas à votre application.

Dans cet exemple tiré du fichier AdventureWorksVoiceCommandService.cs de l’échantillon AdventureWorks, nous transmettons la destination spécifiée à la méthode SendCompletionMessageForDestination, qui récupère tous les trajets correspondants et fournit des cartes de contenu avec des liens profonds vers l’application.

Tout d’abord, nous créons un VoiceCommandUserMessage (userMessage) qui est prononcé par Cortana et affiché sur le canevas de Cortana. Un objet liste VoiceCommandContentTile est ensuite créé pour afficher la collection de cartes de résultats sur l’espace.

Ces deux objets sont ensuite transmis à la méthode CreateResponse de l’objet VoiceCommandResponse (response). Nous définissons ensuite la valeur de propriété AppLaunchArgument sur la valeur de la destination dans la commande vocale.

Enfin, nous appelons la méthode ReportSuccessAsync de la connexion VoiceCommandServiceConnection. Ici, nous ajoutons deux vignettes de contenus avec des valeurs de paramètres AppLaunchArgument différentes à une liste VoiceCommandContentTile utilisée dans l’appel ReportSuccessAsync de l’objet VoiceCommandServiceConnection.

/// <summary>
/// Show details for a single trip, if the trip can be found. 
/// This demonstrates a simple response flow in Cortana.
/// </summary>
/// <param name="destination">The destination specified in the voice command.</param>
private async Task SendCompletionMessageForDestination(string destination)
{
    // If this operation is expected to take longer than 0.5 seconds, the task must
    // supply a progress response to Cortana before starting the operation, and
    // updates must be provided at least every 5 seconds.
    string loadingTripToDestination = string.Format(
               cortanaResourceMap.GetValue("LoadingTripToDestination", cortanaContext).ValueAsString,
               destination);
    await ShowProgressScreen(loadingTripToDestination);
    Model.TripStore store = new Model.TripStore();
    await store.LoadTrips();

    // Query for the specified trip. 
    // The destination should be in the phrase list. However, there might be  
    // multiple trips to the destination. We pick the first.
    IEnumerable<Model.Trip> trips = store.Trips.Where(p => p.Destination == destination);

    var userMessage = new VoiceCommandUserMessage();
    var destinationsContentTiles = new List<VoiceCommandContentTile>();
    if (trips.Count() == 0)
    {
        string foundNoTripToDestination = string.Format(
               cortanaResourceMap.GetValue("FoundNoTripToDestination", cortanaContext).ValueAsString,
               destination);
        userMessage.DisplayMessage = foundNoTripToDestination;
        userMessage.SpokenMessage = foundNoTripToDestination;
    }
    else
    {
        // Set plural or singular title.
        string message = "";
        if (trips.Count() > 1)
        {
            message = cortanaResourceMap.GetValue("PluralUpcomingTrips", cortanaContext).ValueAsString;
        }
        else
        {
            message = cortanaResourceMap.GetValue("SingularUpcomingTrip", cortanaContext).ValueAsString;
        }
        userMessage.DisplayMessage = message;
        userMessage.SpokenMessage = message;

        // Define a tile for each destination.
        foreach (Model.Trip trip in trips)
        {
            int i = 1;
            
            var destinationTile = new VoiceCommandContentTile();

            destinationTile.ContentTileType = VoiceCommandContentTileType.TitleWith68x68IconAndText;
            destinationTile.Image = await StorageFile.GetFileFromApplicationUriAsync(new Uri("ms-appx:///AdventureWorks.VoiceCommands/Images/GreyTile.png"));

            destinationTile.AppLaunchArgument = trip.Destination;
            destinationTile.Title = trip.Destination;
            if (trip.StartDate != null)
            {
                destinationTile.TextLine1 = trip.StartDate.Value.ToString(dateFormatInfo.LongDatePattern);
            }
            else
            {
                destinationTile.TextLine1 = trip.Destination + " " + i;
            }

            destinationsContentTiles.Add(destinationTile);
            i++;
        }
    }

    var response = VoiceCommandResponse.CreateResponse(userMessage, destinationsContentTiles);

    if (trips.Count() > 0)
    {
        response.AppLaunchArgument = destination;
    }

    await voiceServiceConnection.ReportSuccessAsync(response);
}

Vous pouvez également lancer votre application de manière programmatique avec un argument launch pour ouvrir votre application dans un contexte similaire à celui du service d’application. Si vous ne fournissez pas d’argument de lancement, l’application est lancée sur l’écran principal.

Ici, nous ajoutons un paramètre AppLaunchArgument avec la valeur « Las Vegas » à un objet VoiceCommandResponse utilisé dans l’appel RequestAppLaunchAsync de l’objet VoiceCommandServiceConnection.

var userMessage = new VoiceCommandUserMessage();
userMessage.DisplayMessage = "Here are your trips.";
userMessage.SpokenMessage = 
  "You have one trip to Vegas coming up.";

response = VoiceCommandResponse.CreateResponse(userMessage);
response.AppLaunchArgument = "Las Vegas";
await  VoiceCommandServiceConnection.RequestAppLaunchAsync(response);

Manifeste de l’application

Pour permettre la création de liens profonds dans votre application, vous devez déclarer l’extension windows.personalAssistantLaunch dans le fichier Package.appxmanifest de votre projet d’application.

Ici, nous déclarons l’extension windows.personalAssistantLaunch pour l’application Adventure Works.

<Extensions>
  <uap:Extension Category="windows.appService" 
    EntryPoint="AdventureWorks.VoiceCommands.AdventureWorksVoiceCommandService">
    <uap:AppService Name="AdventureWorksVoiceCommandService"/>
  </uap:Extension>
  <uap:Extension Category="windows.personalAssistantLaunch"/> 
</Extensions>

Contrat de protocole

Votre application est lancée au premier plan via l’activation URI (Uniform Resource Identifier) à l’aide d’un contrat de protocole. Votre application doit remplacer l’événement OnActivated de votre application et rechercher un ActivationKind de type Protocol. Pour en savoir plus, reportez-vous au Guide d’activation d’URI.

Ici, nous décodons l’URI fourni par les ProtocolActivatedEventArgs pour accéder à l’argument de lancement. Dans cet exemple, l’URI est défini comme suit : « windows.personalassistantlaunch:?LaunchContext=Las Vegas ».

if (args.Kind == ActivationKind.Protocol)
  {
    var commandArgs = args as ProtocolActivatedEventArgs;
    Windows.Foundation.WwwFormUrlDecoder decoder = 
      new Windows.Foundation.WwwFormUrlDecoder(commandArgs.Uri.Query);
    var destination = decoder.GetFirstValueByName("LaunchContext");

    navigationCommand = new ViewModel.TripVoiceCommand(
      "protocolLaunch",
      "text",
      "destination",
      destination);

    navigationToPageType = typeof(View.TripDetails);

    rootFrame.Navigate(navigationToPageType, navigationCommand);

    // Ensure the current window is active.
    Window.Current.Activate();
  }