Lancer une application pour obtenir des résultats

API importantes

Découvrez comment démarrer une application à partir d’une autre, et échanger des données entre les deux. Il s’agit du lancement d’une application pour obtenir des résultats. L’exemple suivant vous montre comment utiliser LaunchUriForResultsAsync afin de démarrer une application pour afficher les résultats.

Les nouvelles API de communication entre les applications de Windows 10 permettent aux applications Windows (et aux applications web Windows) de démarrer une application et d’échanger des données et des fichiers. Cela vous permet de créer des solutions hybrides à partir de plusieurs applications. Grâce à ces nouvelles API, les tâches complexes qui, auparavant, auraient obligé l’utilisateur à lancer plusieurs applications, peuvent désormais être gérées de manière transparente. Ainsi, votre application peut démarrer une application de réseau social pour choisir un contact, ou une application de validation d’achat pour effectuer un processus de paiement.

L’application que vous démarrez pour afficher les résultats sera désignée sous le nom d’application lancée. L’application qui lance l’application sera désignée sous le nom d’application appelante. Pour cet exemple, vous allez écrire l’application appelante et l’application lancée.

Étape 1 : Inscrire le protocole à gérer dans l’application démarrée pour afficher les résultats

Dans le fichier Package.appxmanifest de l’application lancée, ajoutez une extension de protocole à la <section Application> . L’exemple présent utilise un protocole fictif, appelé test-app2app.

L’attribut ReturnResults dans l’extension de protocole accepte l’une des valeurs suivantes :

  • optional : l’application peut être démarrée pour afficher les résultats via la méthode LaunchUriForResultsAsync, ou à d’autres fins via la méthode LaunchUriAsync. Si vous utilisez l’élément optional, l’application lancée doit déterminer si elle a été démarrée pour afficher les résultats. Pour ce faire, elle peut vérifier l’argument d’événement OnActivated. Si la propriété IActivatedEventArgs.Kind de l’argument renvoie ActivationKind.ProtocolForResults ou si le type de l’argument d’événement est ProtocolActivatedEventArgs, l’application a été lancée via LaunchUriForResultsAsync.
  • always : l’application peut être démarrée uniquement pour afficher les résultats ; autrement dit, elle ne peut répondre qu’à LaunchUriForResultsAsync.
  • none : l’application ne peut pas être démarrée pour afficher les résultats ; elle ne peut répondre qu’à LaunchUriAsync.

Dans cet exemple d’extension de protocole, l’application peut être démarrée uniquement pour afficher les résultats. Cela permet de simplifier la logique figurant dans la méthode OnActivated (abordée ci-dessous), car nous avons uniquement besoin de gérer les cas de « démarrage pour afficher les résultats », et non les autres modes d’activation possibles de l’application.

<Applications>
   <Application ...>

     <Extensions>
       <uap:Extension Category="windows.protocol">
         <uap:Protocol Name="test-app2app" ReturnResults="always">
           <uap:DisplayName>Test app-2-app</uap:DisplayName>
         </uap:Protocol>
       </uap:Extension>
     </Extensions>

   </Application>
</Applications>

Étape 2 : Remplacer l’élément Application.OnActivated dans l’application à démarrer pour afficher les résultats

Si cette méthode n’existe pas déjà dans l’application lancée, créez-la dans la classe App définie dans le fichier App.xaml.cs.

Dans une application permettant de sélectionner vos amis dans un réseau social, cette fonction peut être utilisée pour ouvrir la page du sélecteur de contacts. Dans l’exemple suivant, une page appelée LaunchedForResultsPage s’affiche lorsque l’application est activée pour afficher les résultats. Assurez-vous que l’instruction using est incluse en haut du fichier.

using Windows.ApplicationModel.Activation;
...
protected override void OnActivated(IActivatedEventArgs args)
{
    // Window management
    Frame rootFrame = Window.Current.Content as Frame;
    if (rootFrame == null)
    {
        rootFrame = new Frame();
        Window.Current.Content = rootFrame;
    }

    // Code specific to launch for results
    var protocolForResultsArgs = (ProtocolForResultsActivatedEventArgs)args;
    // Open the page that we created to handle activation for results.
    rootFrame.Navigate(typeof(LaunchedForResultsPage), protocolForResultsArgs);

    // Ensure the current window is active.
    Window.Current.Activate();
}
using namespace winrt::Windows::ApplicationModel::Activation;
...
protected override void OnActivated(IActivatedEventArgs args)
{
    // Window management
    Frame rootFrame{ nullptr };
    auto content = Window::Current().Content();
    if (content)
    {
        rootFrame = content.try_as<Frame>();
    }
    
    if (rootFrame == null)
    {
        rootFrame = Frame();
        Window::Current().Content(rootFrame);
    }

    // Code specific to launch for results
    auto protocolForResultsEventArgs{ args.as<ProtocolForResultsActivatedEventArgs>() };
    // Open the page that we created to handle activation for results.
    rootFrame.Navigate(xaml_typename<LaunchedForResultsPage>(), protocolForResultsArgs);

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

Étant donné que l’extension de protocole dans le fichier Package.appxmanifest spécifie l’élément ReturnResults en tant que always, le code que nous venons d’illustrer peut effectuer un transtypage de l’élément args directement à ProtocolForResultsActivatedEventArgs. Cela permet de s’assurer que seul ProtocolForResultsActivatedEventArgs sera transmis à OnActivated pour cette application. Si votre application peut être activée d’une manière autre que le lancement pour les résultats, vous pouvez case activée si la propriété IActivatedEventArgs.Kind renvoie ActivationKind.ProtocolForResults pour indiquer si l’application a été lancée pour les résultats.

Étape 3 : Ajouter un champ ProtocolForResultsOperation à l’application que vous démarrez pour afficher les résultats

private Windows.System.ProtocolForResultsOperation _operation = null;
Windows::System::ProtocolForResultsOperation _operation = nullptr;

Vous utiliserez le champ ProtocolForResultsOperation pour signaler que l’application lancée est prête à renvoyer le résultat à l’application à l’origine de l’appel. Dans cet exemple, le champ est ajouté à la classe LaunchedForResultsPage, car vous effectuez le démarrage pour afficher les résultats à partir de cette page et devez être à même d’y accéder.

Étape 4 : Remplacer OnNavigatedTo() dans l’application que vous démarrez pour afficher les résultats

Remplacez la méthode OnNavigatedTo dans la page que vous allez afficher lorsque votre application est démarrée pour afficher les résultats. Si cette méthode n’existe pas encore, créez-la dans la classe de la page définie dans le fichier <pagename>.xaml.cs. Assurez-vous que l’instruction using suivante est incluse en haut du fichier :

using Windows.ApplicationModel.Activation
using namespace winrt::Windows::ApplicationModel::Activation;

L’objet NavigationEventArgs de la méthode OnNavigatedTo contient les données transmises par l’application à l’origine de l’appel. Ces données, d’une taille de 100 Ko au maximum, sont stockées dans un objet ValueSet.

Dans cet exemple de code, l’application lancée s’attend à ce que les données envoyées par l’application à l’origine de l’appel soient incluses dans un élément ValueSet, sous une clé appelée TestData, car il s’agit de l’élément dont l’envoi a été prévu par le code de l’exemple d’application à l’origine de l’appel.

using Windows.ApplicationModel.Activation;
...
protected override void OnNavigatedTo(NavigationEventArgs e)
{
    var protocolForResultsArgs = e.Parameter as ProtocolForResultsActivatedEventArgs;
    // Set the ProtocolForResultsOperation field.
    _operation = protocolForResultsArgs.ProtocolForResultsOperation;

    if (protocolForResultsArgs.Data.ContainsKey("TestData"))
    {
        string dataFromCaller = protocolForResultsArgs.Data["TestData"] as string;
    }
}
...
private Windows.System.ProtocolForResultsOperation _operation = null;
using namespace winrt::Windows::ApplicationModel::Activation;
...
protected override void OnNavigatedTo(NavigationEventArgs e)
{
    auto protocolForResultsArgs = e.Parameter().try_as<ProtocolForResultsActivatedEventArgs>();
    // Set the ProtocolForResultsOperation field.
    _operation = protocolForResultsArgs.ProtocolForResultsOperation();

    if (protocolForResultsArgs.Data().HasKey("TestData"))
    {
        string dataFromCaller{ unbox_value<hstring>(protocolForResultsArgs.Data().Lookup("TestData")) };
    }
}
...
Windows::System::ProtocolForResultsOperation _operation = nullptr;

Étape 5 : Écrire du code pour renvoyer des données à l’application à l’origine de l’appel

Dans l’application lancée, utilisez ProtocolForResultsOperation pour retourner des données à l’application appelante. Dans cet exemple de code, un objet ValueSet est créé. Il contient la valeur à renvoyer à l’application à l’origine de l’appel. Le champ ProtocolForResultsOperation est ensuite utilisé pour envoyer la valeur à l’application à l’origine de l’appel.

    ValueSet result = new ValueSet();
    result["ReturnedData"] = "The returned result";
    _operation.ReportCompleted(result);
    ValueSet result;
    result.Insert("ReturnedData", "The returned result");
    _operation.ReportCompleted(result);

Étape 6 : Écrire du code pour démarrer l’application pour afficher les résultats et obtenir les données renvoyées

Démarrez l’application à partir d’une méthode asynchrone dans l’application à l’origine de l’appel, comme illustré dans cet exemple de code. Notez les instructions using, qui sont nécessaires pour que le code soit compilé :

using System.Threading.Tasks;
using Windows.System;
...

async Task<string> LaunchAppForResults()
{
    var testAppUri = new Uri("test-app2app:"); // The protocol handled by the launched app
    var options = new LauncherOptions();
    options.TargetApplicationPackageFamilyName = "67d987e1-e842-4229-9f7c-98cf13b5da45_yd7nk54bq29ra";

    var inputData = new ValueSet();
    inputData["TestData"] = "Test data";

    string theResult = "";
    LaunchUriResult result = await Windows.System.Launcher.LaunchUriForResultsAsync(testAppUri, options, inputData);
    if (result.Status == LaunchUriStatus.Success &&
        result.Result != null &&
        result.Result.ContainsKey("ReturnedData"))
    {
        ValueSet theValues = result.Result;
        theResult = theValues["ReturnedData"] as string;
    }
    return theResult;
}

Dans cet exemple, un élément ValueSet contenant la clé TestData est transmis à l’application lancée. L’application lancée crée un élément ValueSet avec une clé appelée ReturnedData, qui contient le résultat renvoyé à l’application à l’origine de l’appel.

Vous devez générer et déployer l’application à démarrer pour afficher les résultats avant d’exécuter l’application à l’origine de l’appel. Sinon, LaunchUriResult.Status indiquera LaunchUriStatus.AppUnavailable.

Vous aurez besoin du nom de famille de l’application lancée lorsque vous définissez targetApplicationPackageFamilyName. Une façon d’obtenir le nom de famille consiste à effectuer l’appel suivant à partir de l’application lancée :

string familyName = Windows.ApplicationModel.Package.Current.Id.FamilyName;

Remarques

L’exemple de cette procédure inclut une introduction de type « hello world » pour le démarrage d’une application afin d’afficher les résultats. Les points clés à noter sont que la nouvelle API LaunchUriForResultsAsync vous permet de lancer de manière asynchrone une application et de communiquer via la classe ValueSet . Les données à transmettre via un élément ValueSet doivent présenter une taille de 100 Ko au maximum. Si vous devez transmettre de plus grandes quantités de données, vous pouvez partager des fichiers à l’aide de la classe SharedStorageAccessManager pour créer des jetons de fichier que vous pouvez transmettre entre les applications. Par exemple, pour un élément ValueSet appelé inputData, vous pouvez stocker le jeton dans un fichier que vous souhaitez partager avec l’application lancée :

inputData["ImageFileToken"] = SharedStorageAccessManager.AddFile(myFile);

transférez-le ensuite à l’application lancée via LaunchUriForResultsAsync.