かずきのBlog@hatena

日本マイクロソフトに勤めています。XAML + C#の組み合わせをメインに、たまにASP.NETやJavaなどの.NET系以外のことも書いています。掲載内容は個人の見解であり、所属する企業を代表するものではありません。

Windows 10 TPのUniversal application platformで別アプリを起動して結果を受取りたい

Windows 10 TP時点の情報です

以下の記事の続きです。

okazuki.hatenablog.com

別アプリを起動するだけでは一方通行のコミュニケーションになってしまいます。それだと、片手落ち。ということで、UAPでは、戻り値を受け取ることもできるようになっています。Launcher.LaunchUriForResultsAsyncメソッドを使うことで呼び出したアプリから結果を受取ることが出来るようになります。

戻り値のResultプロパティにValueSetで結果が入っています。以下の例はMessageというキーに結果が入ってる前提のコード例です。

private async void Button_Click(object sender, RoutedEventArgs e)
{
    var options = new LauncherOptions();
    options.TargetApplicationPackageFamilyName = "c190bbea-586b-461b-a523-9fcd05e6233c_a892ers4d9s3w";
    var data = new ValueSet();
    data["Name"] = "okazuki";
    var result = await Launcher.LaunchUriForResultsAsync(new Uri("sampleapp:"), options, data);
    if (result.Status == LaunchUriStatus.Success && result.Result != null)
    {
        var dialog = new MessageDialog(result.Result["Message"] as string);
        await dialog.ShowAsync();
    }
}

起動される側のプログラムでは、ProtocolForResultActivatedEventArgs型がわたってくるので、それをどこかに保持しておきます。

protected override void OnActivated(IActivatedEventArgs args)
{
    var e = args as ProtocolForResultsActivatedEventArgs;
    if (e == null) { return; }
    // イベント引数をどこかの保持しておく
    ActivatedArgs = e;
    Frame rootFrame = Window.Current.Content as Frame;

    // Do not repeat app initialization when the Window already has content,
    // just ensure that the window is active
    if (rootFrame == null)
    {
        // Create a Frame to act as the navigation context and navigate to the first page
        rootFrame = new Frame();
        // Set the default language
        rootFrame.Language = Windows.Globalization.ApplicationLanguages.Languages[0];

        rootFrame.NavigationFailed += OnNavigationFailed;

        if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
        {
            //TODO: Load state from previously suspended application
        }

        // Place the frame in the current Window
        Window.Current.Content = rootFrame;
    }

    if (rootFrame.Content == null)
    {
        // When the navigation stack isn't restored navigate to the first page,
        // configuring the new page by passing required information as a navigation
        // parameter
        rootFrame.Navigate(typeof(MainPage), e.Data["Name"]);
    }
    // Ensure the current window is active
    Window.Current.Activate();
}

結果を返す処理で、ProtocolForResultsActivatedEventArgsのProtocolForResultsOperationプロパティに対してReportCompletedを呼び出すことで、結果を返せます。引数にはおなじみのValueSetを渡します。

private void Button_Click(object sender, RoutedEventArgs e)
{
    var op = App.ActivatedArgs.ProtocolForResultsOperation;
    var message = new ValueSet();
    message["Message"] = "Hello world";
    op.ReportCompleted(message);
}

結構お手軽に双方向でのデータのやり取りができるようになっています。