Iniciar una aplicación para obtener resultados

API importantes

Aprende a iniciar una aplicación desde otra aplicación y a intercambiar datos entre las dos. Esto se denomina inicio de una aplicación para obtener resultados. En el ejemplo siguiente se muestra cómo usar LaunchUriForResultsAsync para iniciar una aplicación para obtener resultados.

Las nuevas API de comunicación de aplicaciones a aplicaciones en Windows 10 permiten que las aplicaciones de Windows (y las aplicaciones web de Windows) inicien una aplicación y intercambien datos y archivos. Esto le permite crear soluciones de mash-up a partir de varias aplicaciones. Con estas nuevas API, las tareas complejas que habrían requerido al usuario usar varias aplicaciones ahora se pueden controlar sin problemas. Por ejemplo, la aplicación podría iniciar una aplicación de redes sociales para elegir un contacto o iniciar una aplicación de desprotección para completar un proceso de pago.

La aplicación que se iniciará para los resultados se denominará aplicación iniciada. La aplicación que inicia la aplicación se denominará aplicación que llama. En este ejemplo, escribirá tanto la aplicación que llama como la aplicación iniciada.

Paso 1: Registrar el protocolo que se va a controlar en la aplicación que se iniciará para obtener resultados

En el archivo Package.appxmanifest de la aplicación iniciada, agregue una extensión de protocolo a la sección Aplicación>.< En el ejemplo siguiente se usa un protocolo ficticio denominado test-app2app.

El atributo ReturnResults de la extensión de protocolo acepta uno de estos valores:

En este ejemplo de extensión de protocolo, la aplicación solo se puede iniciar para los resultados. Esto simplifica la lógica dentro del método OnActivated , que se describe a continuación, porque solo tenemos que controlar el caso "iniciado para los resultados" y no las otras formas de activar la aplicación.

<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>

Paso 2: Invalidar Application.OnActivated en la aplicación que se iniciará para obtener resultados

Si este método aún no existe en la aplicación iniciada, créelo dentro de la App clase definida en App.xaml.cs.

En una aplicación que te permite elegir a tus amigos en una red social, esta función podría ser donde abres la página del selector de personas. En este ejemplo siguiente, se muestra una página denominada LaunchedForResultsPage cuando se activa la aplicación para obtener resultados. Asegúrese de que la instrucción using se incluye en la parte superior del archivo.

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();
}

Dado que la extensión de protocolo del archivo Package.appxmanifest especifica ReturnResults como siempre, el código que acaba de mostrar se puede convertir args directamente a ProtocolForResultsActivatedEventArgs con confianza en que solo ProtocolForResultsActivatedEventArgs se enviará a OnActivated para esta aplicación. Si la aplicación se puede activar de maneras distintas del inicio de los resultados, puedes comprobar si la propiedad IActivatedEventArgs.Kind devuelve ActivationKind.ProtocolForResults para indicar si la aplicación se inició para obtener resultados.

Paso 3: Agregar un campo ProtocolForResultsOperation a la aplicación que inicia para obtener resultados

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

Usará el campo ProtocolForResultsOperation para indicar cuándo la aplicación iniciada está lista para devolver el resultado a la aplicación que realiza la llamada. En este ejemplo, el campo se agrega a la clase LaunchForResultsPage porque completará la operación launch-for-results desde esa página y tendrá acceso a ella.

Paso 4: Invalidar OnNavigatedTo() en la aplicación que inicia para obtener resultados

Invalide el método OnNavigatedTo en la página que se mostrará cuando se inicie la aplicación para obtener resultados. Si este método aún no existe, créelo dentro de la clase para la página definida en <pagename>.xaml.cs. Asegúrese de que la siguiente instrucción using se incluye en la parte superior del archivo:

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

El objeto NavigationEventArgs del método OnNavigatedTo contiene los datos pasados desde la aplicación que realiza la llamada. Los datos no pueden superar los 100 KB y se almacenan en un objeto ValueSet.

En este código de ejemplo, la aplicación iniciada espera que los datos enviados desde la aplicación que realiza la llamada estén en un ValueSet en una clave denominada TestData, ya que eso es lo que la aplicación que llama al ejemplo está codificada para enviar.

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;

Paso 5: Escribir código para devolver datos a la aplicación que llama

En la aplicación iniciada, use ProtocolForResultsOperation para devolver datos a la aplicación que llama. En este código de ejemplo, se crea un objeto ValueSet que contiene el valor que se va a devolver a la aplicación que realiza la llamada. A continuación, se usa el campo ProtocolForResultsOperation para enviar el valor a la aplicación que realiza la llamada.

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

Paso 6: Escribir código para iniciar la aplicación para obtener resultados y obtener los datos devueltos

Inicie la aplicación desde un método asincrónico en la aplicación que realiza la llamada, como se muestra en este código de ejemplo. Tenga en cuenta las instrucciones using , que son necesarias para que el código se compile:

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;
}

En este ejemplo, se pasa un valueSet que contiene la clave TestData a la aplicación iniciada. La aplicación iniciada crea un ValueSet con una clave denominada ReturnedData que contiene el resultado devuelto al autor de la llamada.

Debe compilar e implementar la aplicación que iniciará para obtener resultados antes de ejecutar la aplicación que realiza la llamada. De lo contrario, LaunchUriResult.Status notificará LaunchUriStatus.AppUnavailable.

Necesitará el nombre de familia de la aplicación iniciada al establecer TargetApplicationPackageFamilyName. Una manera de obtener el nombre de familia es realizar la siguiente llamada desde dentro de la aplicación iniciada:

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

Comentarios

En el ejemplo de este procedimiento se proporciona una introducción "hola mundo" para iniciar una aplicación para obtener resultados. Las principales cosas que hay que tener en cuenta son que la nueva API LaunchUriForResultsAsync le permite iniciar de forma asincrónica una aplicación y comunicarse a través de la clase ValueSet. Pasar datos a través de valueSet está limitado a 100 KB. Si necesita pasar grandes cantidades de datos, puede compartir archivos mediante la clase SharedStorageAccessManager para crear tokens de archivo que puede pasar entre aplicaciones. Por ejemplo, dada una clase ValueSet denominada inputData, puede almacenar el token en un archivo que quiera compartir con la aplicación iniciada:

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

A continuación, páselo a la aplicación iniciada a través de LaunchUriForResultsAsync.