かずきのBlog@hatena

すきな言語は C# + XAML の組み合わせ。Azure Functions も好き。最近は Go 言語勉強中。日本マイクロソフトで働いていますが、ここに書いていることは個人的なメモなので会社の公式見解ではありません。

Windows 10 TPのUniversal application platformで別アプリを起動する

Windows 10 TP時点の情報です

今までもURIでアプリを起動とかってできたんだっけ? Windows 10 TPでは、相手アプリを指定して起動するとかいろいろ強化されています。起動のしかたは簡単。起動対象のアプリのFamilyNameと起動するためのプロトコルがわかってればそれをAPIに渡すだけ。

起動される側のアプリケーションの作成

起動される側は、Package.appxmanifestに以下のようにどんなプロトコルで起動するのか書いておきます。ここではsampleappで起動するように書いています。

<?xml version="1.0" encoding="utf-8"?>

<Package
  xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
  xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
  xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
  IgnorableNamespaces="uap mp">

  <!-- 省略 -->

  <Applications>
    <Application Id="App"
      Executable="$targetnametoken$.exe"
      EntryPoint="InvokeTargetApp.App">
      <uap:VisualElements
        DisplayName="InvokeTargetApp"
        Square150x150Logo="Assets\Logo.png"
        Square44x44Logo="Assets\SmallLogo.png"
        Description="InvokeTargetApp"
        ForegroundText="light"
        BackgroundColor="#464646">
        <uap:SplashScreen Image="Assets\SplashScreen.png" />
      </uap:VisualElements>
      <!-- ここから -->
      <Extensions>
        <uap:Extension Category="windows.protocol">
          <uap:Protocol Name="sampleapp">
            <uap:Logo>Assets\Logo.png</uap:Logo>
          </uap:Protocol>
        </uap:Extension>
      </Extensions>
      <!-- ここまで -->
    </Application>
  </Applications>

  <Capabilities>
    <Capability Name="internetClient" />
  </Capabilities>
</Package>

そして、AppクラスのOnActivatedをオーバーライドしてプロトコルから起動された場合の起動シーケンスを書きます。ここでは単純にMainPageへ遷移するだけにしました。ちなみにプロトコルで起動された場合はイベント引数にProtocolActivatedEventArgsがわたってきます。

protected override void OnActivated(IActivatedEventArgs args)
{
    var e = args as ProtocolActivatedEventArgs;
    if (e == null) { return; }

    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), null);
    }
    // Ensure the current window is active
    Window.Current.Activate();
}

ついでにMainPageのコンストラクタに以下のコードを記述して、FamilyNameを取得しておきます。

Debug.WriteLine(Package.Current.Id.FamilyName);

起動する側のアプリケーション

起動する側は、簡単です。LauncherOptions型を作って、それにFamilyNameを指定して、Launcher.LaunchUriAsyncに渡してやります。URIは、Package.appxmanifestで設定したのと同じのを指定します。

ボタンのクリックイベントあたりに以下のようなコードを書いておくと、先ほど作成したアプリが起動するようになります。

private async void Button_Click(object sender, RoutedEventArgs e)
{
    var options = new LauncherOptions();
    options.TargetApplicationPackageFamilyName = "c190bbea-586b-461b-a523-9fcd05e6233c_a892ers4d9s3w";
    await Launcher.LaunchUriAsync(new Uri("sampleapp:"), options);
}