Iniciar um app para obter resultados

APIs importantes

Saiba como iniciar um app a partir de outro app e trocar dados entre os dois. Isso é chamado de iniciar um aplicativo para obter resultados. O exemplo mostra como usar LaunchUriForResultsAsync para iniciar um aplicativo para obter resultados.

As novas APIs de comunicação entre aplicativos no Windows 10 permitem que os aplicativos do Windows (e aplicativos Web do Windows) iniciem um aplicativo e troquem dados e arquivos. Isso permite que você crie soluções diversas de vários aplicativos. Usando essas novas APIs, tarefas complexas que exigiriam que o usuário usasse vários aplicativos podem agora ser executadas perfeitamente. Por exemplo, seu aplicativo pode iniciar um aplicativo de rede social para selecionar um contato ou iniciar um aplicativo de check-out para concluir um processo de pagamento.

O aplicativo que você iniciará para obter resultados será chamado de aplicativo iniciado. O aplicativo que inicia o aplicativo será referenciado como aplicativo de chamada. Para este exemplo, você escreverá o aplicativo de chamada e o aplicativo iniciado.

Etapa 1: Registrar o protocolo que será manipulado no aplicativo que você iniciará para obter resultados

No arquivo Package.appxmanifest do aplicativo iniciado, adicione uma extensão de protocolo à <seção Aplicativo> . O exemplo aqui usa um protocolo fictício chamado test-app2app.

O atributo ReturnResults na extensão do protocolo aceita um destes valores:

Neste exemplo de extensão de protocolo, o aplicativo pode ser iniciado somente para obter resultados. Isso simplifica a lógica do método OnActivated, discutido a seguir, porque só será necessário lidar com o caso "iniciado para obter resultados" e não com as outras maneiras de ativação do aplicativo.

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

Etapa 2: substituir Application.OnActivated no aplicativo que será iniciado para obter resultados

Se esse método ainda não existir no aplicativo iniciado, crie-o dentro da classe App definida em App.xaml.cs.

Em um aplicativo que permite selecionar seus amigos em uma rede social, essa função pode estar onde você abre a página do seletor de pessoas. No próximo exemplo, uma página denominada LaunchedForResultsPage é exibida quando o aplicativo é ativado para obter resultados. Verifique se a instrução using está incluída na parte superior do arquivo.

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

Como a extensão de protocolo no arquivo Package.appxmanifest especifica ReturnResults como always, o código que acabamos de mostrar pode converter args diretamente no ProtocolForResultsActivatedEventArgs com confiança de que somente ProtocolForResultsActivatedEventArgs será enviada a OnActivated para esse aplicativo. Caso seu aplicativo possa ser ativado de outras formas além de iniciar para obter resultados, você pode verificar se a propriedade IActivatedEventArgs.Kind retorna ActivationKind.ProtocolForResults para determinar se o aplicativo foi iniciado para obter resultados.

Etapa 3: Adicionar um campo ProtocolForResultsOperation ao aplicativo iniciado para obter resultados

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

Você usará o campo ProtocolForResultsOperation para sinalizar quando o aplicativo iniciado estiver pronto para retornar o resultado para o aplicativo de chamada. Neste exemplo, o campo é adicionado à classe LaunchedForResultsPage porque a operação de início para obter resultados será concluída nessa página e precisaremos acessá-la.

Etapa 4: Substituir OnNavigatedTo() no aplicativo iniciado para obter resultados

Substitua o método OnNavigatedTo na página que será exibida quando o aplicativo for iniciado para obter resultados. Se esse método ainda não existir, crie-o dentro da classe para a página definida em <pagename>.xaml.cs. Verifique se a seguinte instrução using está incluída na parte superior do arquivo:

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

O objeto NavigationEventArgs no método OnNavigatedTo contém os dados passados do aplicativo de chamada. Os dados não podem exceder 100 KB e são armazenados em um objeto ValueSet.

Neste código de exemplo, o aplicativo iniciado espera que os dados enviados do aplicativo de chamada estejam em um ValueSet sob uma chave denominada TestData, porque o aplicativo de chamada do exemplo está codificado para enviar isso.

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;

Etapa 5: Escrever o código para retornar dados para o aplicativo chamador

No aplicativo iniciado, use ProtocolForResultsOperation para retornar dados para o aplicativo de chamada. Neste código de exemplo, um objeto ValueSet é criado com o valor a ser retornado ao aplicativo de chamada. O campo ProtocolForResultsOperation é usado para enviar o valor para o aplicativo de chamada.

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

Etapa 6: Escrever o código para iniciar o aplicativo para obter resultados e os dados retornados

Inicie o aplicativo a partir de um método assíncrono no aplicativo de chamada, conforme mostrado no código de exemplo. Observe as instruções using que são necessárias para a compilação do código:

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

Neste exemplo, um ValueSet que contém a chave TestData é passado para o aplicativo iniciado. O aplicativo iniciado cria um ValueSet com uma chave denominada ReturnedData que contém o resultado retornado para o chamador.

Você deve criar e implantar o aplicativo que será iniciado para obter resultados antes de executar o aplicativo de chamada. Caso contrário, LaunchUriResult.Status reportará LaunchUriStatus.AppUnavailable.

O nome da família do aplicativo iniciado será necessário ao definir TargetApplicationPackageFamilyName. Para obter o nome da família, faça a seguinte chamada a partir do aplicativo iniciado:

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

Comentários

O exemplo nestas instruções fornece uma introdução "hello world" para iniciar um aplicativo para obter resultados. Os principais aspectos a serem observados são que a nova API LaunchUriForResultsAsync permite iniciar um aplicativo de maneira assíncrona e se comunicar por meio da classe ValueSet. A transmissão de dados por meio de ValueSet é limitada a 100 KB. Se você precisar passar maiores quantidades de dados, poderá compartilhar arquivos usando a classe SharedStorageAccessManager para criar tokens de arquivos que poderão ser passados entre aplicativos. Por exemplo, dado um ValueSet denominado inputData, você pode armazenar o token em um arquivo que você quer compartilhar com o aplicativo iniciado:

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

Em seguida, passá-lo para o aplicativo iniciado por meio de LaunchUriForResultsAsync.