プロトコルアクティベーションへの対応
マニフェストに宣言したので、「タイムライン」からプロトコルアクティベーションでアプリを起動してもらえるようにはなりました。でも、ただ起動するだけです。「ユーザーアクティビティ」として登録した状態を復元しましょう。また、このままでは、「タイムライン」で「ユーザーアクティビティ」をクリックするたびに新しいプロセスが起動してしまいます。複数のプロセスが立ち上がらないようにもしてみましょう。
デスクトップブリッジでのプロトコルアクティベーション
純粋な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ページを表示するようになりました。
