読者です 読者をやめる 読者になる 読者になる

かずきのBlog@hatena

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

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