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 aqui mostra como usar LaunchUriForResultsAsync para iniciar um aplicativo para obter resultados.

As novas APIs de comunicação entre aplicativos no Windows 10 possibilitam que os aplicativos do Windows (e os aplicativos Web do Windows) iniciem um aplicativo e troquem dados e arquivos. Isso permite que você crie soluções de mash-up de vários aplicativos. Usando essas novas APIs, tarefas complexas que exigiriam que o usuário usasse vários aplicativos agora podem ser tratadas sem problemas. Por exemplo, seu aplicativo pode iniciar um aplicativo de rede social para escolher um contato ou iniciar um aplicativo de checkout 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á chamado de aplicativo de chamada. Para este exemplo, você escreverá o aplicativo de chamada e o aplicativo iniciado.

Etapa 1: Registre o protocolo a ser tratado 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 de protocolo aceita um destes valores:

Neste exemplo de extensão de protocolo, o aplicativo pode ser iniciado apenas para obter resultados. Isso simplifica a lógica dentro do método OnActivated, discutido abaixo, porque temos que lidar apenas com o caso "iniciado para resultados" e não com as outras maneiras pelas quais o aplicativo pode ser ativado.

<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 você iniciará para obter resultados

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

Em um aplicativo que permite que você escolha seus amigos em uma rede social, essa função pode ser onde você abre a página do seletor de pessoas. Neste próximo exemplo, uma página chamada LaunchedForResultsPage é exibida quando o aplicativo é ativado para resultados. Certifique-se de que a instrução using esteja 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 sempre, o código mostrado pode ser convertido args diretamente em ProtocolForResultsActivatedEventArgs com a confiança de que somente ProtocolForResultsActivatedEventArgs será enviado para OnActivated para este aplicativo. Se o aplicativo puder ser ativado de maneiras diferentes da inicialização para resultados, você poderá verificar se a propriedade IActivatedEventArgs.Kind retorna ActivationKind.ProtocolForResults para saber se o aplicativo foi iniciado para resultados.

Etapa 3: adicionar um campo ProtocolForResultsOperation ao aplicativo que você inicia 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 ao aplicativo de chamada. Neste exemplo, o campo é adicionado à classe LaunchedForResultsPage porque você concluirá a operação de inicialização para resultados dessa página e precisará acessá-la.

Etapa 4: substituir OnNavigatedTo() no aplicativo que você inicia para obter resultados

Substitua o método OnNavigatedTo na página que você exibirá quando seu 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. Certifique-se de que a seguinte instrução using esteja 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 em uma chave chamada TestData, porque é isso que o aplicativo de chamada do exemplo está codificado 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;

Etapa 5: Escrever código para retornar dados ao aplicativo de chamada

No aplicativo iniciado, use ProtocolForResultsOperation para retornar dados ao aplicativo de chamada. Neste código de exemplo, é criado um objeto ValueSet que contém 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: Escreva o código para iniciar o aplicativo para obter resultados e obter os dados retornados

Inicie o aplicativo de dentro de um método assíncrono em seu aplicativo de chamada, conforme mostrado neste código de exemplo. Observe as instruções using , que são necessárias para que o código seja compilado:

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 contendo a chave TestData é passado para o aplicativo iniciado. O aplicativo iniciado cria um ValueSet com uma chave chamada ReturnedData que contém o resultado retornado ao chamador.

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

Você precisará do nome da família do aplicativo iniciado ao definir o TargetApplicationPackageFamilyName. Uma maneira de obter o sobrenome é fazer a seguinte chamada de dentro do aplicativo iniciado:

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

Comentários

O exemplo neste tutorial fornece uma introdução "olá, mundo" para iniciar um aplicativo para obter resultados. As principais coisas a serem observadas são que a nova API LaunchUriForResultsAsync permite que você inicie um aplicativo de forma assíncrona e se comunique por meio da classe ValueSet. A passagem de dados por meio de um ValueSet é limitada a 100 KB. Se você precisar passar grandes quantidades de dados, poderá compartilhar arquivos usando a classe SharedStorageAccessManager para criar tokens de arquivo que podem ser passados entre aplicativos. Por exemplo, dado um ValueSet chamado inputData, você pode armazenar o token em um arquivo que deseja compartilhar com o aplicativo iniciado:

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

Em seguida, passe-o para o aplicativo iniciado por meio de LaunchUriForResultsAsync.