プロトコルアクティベーションへの対応
マニフェストに宣言したので、「タイムライン」からプロトコルアクティベーションでアプリを起動してもらえるようにはなりました。でも、ただ起動するだけです。「ユーザーアクティビティ」として登録した状態を復元しましょう。また、このままでは、「タイムライン」で「ユーザーアクティビティ」をクリックするたびに新しいプロセスが起動してしまいます。複数のプロセスが立ち上がらないようにもしてみましょう。
デスクトップブリッジでのプロトコルアクティベーション
純粋なUWPアプリとは違って、「UWPアプリ化」したデスクトップアプリの場合は、プロトコルアクティベーションによって必ずアプリが起動されます。起動時、Main関数の最初の引数としてアクティベーションURIが渡されます。
従って、Main関数の冒頭で引数をチェックして、第1引数がアクティベーションURIであれば、プロトコルアクティベーションで起動されたと判定すればよさそうです。今回は、引数のアクティベーションURIから状態を復元するための情報(=表示していたWebページのURL)を取り出してみて、その結果がnullでなければプロトコルアクティベーションだと判定することにします。
Main関数を追加する
WPFのプロジェクトの既定では、Main関数はビルド時に自動生成されるようになっています。Main関数に独自の処理を追加するには、自動生成を止めてから、AppクラスにMain関数を追加します。
まず、ソリューションエクスプローラーでWPFプロジェクトの「App.xaml」ファイルを選び、そのプロパティペインでビルドアクションを[ApplicationDefinition]から[Page]に変更します。これでMain関数の自動生成が止まります。
次に、「App.xaml.cs」ファイルを開いて、Main関数を追加します(次のコード)。
[STAThread] public static void Main(string[] args) { App app = new App(); app.InitializeComponent(); app.Run(); }
さらに、AppクラスからMainWindowを操作できるようにしておきましょう。自動生成されたコードではMainWindowのインスタンスを明示的に作っていないので、操作しにくいのです。「App.xaml」ファイルを開いて、先頭の「Application」タグ内から「StartupUri="MainWindow.xaml"」の部分を削除します。そうしたら、Main関数を次のコードのように変更します。
[STAThread] public static void Main(string[] args) { App app = new App(); app.Startup += OnStartup; app.InitializeComponent(); app.Run(); return; // 以下はローカル関数のみ void OnStartup(object sender, StartupEventArgs e) { // 明示的にMainWindowインスタンスを生成して表示する MainWindow mainWindow = new MainWindow(); mainWindow.Show(); } }
プロトコルアクティベーションで指定されたWebページを表示する
先に、MainWindowクラスに、外部から指定したWebページを表示する機能を追加しておきましょう(次のコード)。
internal async void Navigate(string url) { this.WebView1.Navigate(new Uri(url)); }
さて、今回の場合、プロトコルアクティベーションで渡された引数から表示すべきWebページのURL文字列を取り出すコードは、次のようになります。プロトコルアクティベーションではないときはnullを返すようにしました。
string GetProtocolActivationUrl(string args) // argsはMain関数の引数 { if (args.Length > 0 // 引数が存在し && args[0].StartsWith("uf05.bluewatersoft.jp-timelinetest:") //先頭がプロトコル名なら && Uri.TryCreate(args[0], UriKind.Absolute, out var uri)) //引数をUriクラスに変換し、 return uri.Query.Substring(1); //そのUriのクエリ部分(先頭の'?'を除く)が表示すべきURL else return null; }
このGetProtocolActivationUrlメソッドをMain関数に組み込みます。そして、プロトコルアクティベーションのURLが得られたときには、MainWindowを表示したときに前述のNavigateメソッドを呼び出すようにします(次のコード、Appクラス内)。
[STAThread] public static void Main(string[] args) { // プロトコルアクティベーションで起動されたときの、表示すべきURL string protocolActivationUrl = GetProtocolActivationUrl(); App app = new App(); app.Startup += OnStartup; app.InitializeComponent(); app.Run(); return; // 以下はローカル関数のみ string GetProtocolActivationUrl() //ローカル関数にしたので、args引数の受け渡しは不要 { if (args.Length > 0 && args[0].StartsWith("uf05.bluewatersoft.jp-timelinetest:") && Uri.TryCreate(args[0], UriKind.Absolute, out var uri)) return uri.Query.Substring(1); else return null; } void OnStartup(object sender, StartupEventArgs e) { // App.xamlから「StartupUri="MainWindow.xaml"」の部分を削除しておく MainWindow mainWindow = new MainWindow(); mainWindow.Show(); if (protocolActivationUrl != null) // プロトコルアクティベーションのときは、そのURLを表示する mainWindow.Navigate(protocolActivationUrl); } }
これで、「タイムライン」から起動されたときに、以前のWebページを表示するようになりました。