為應用程式注冊協定後,可以通過URI來激活目前應用程式,并且還可以在激活應用程式的URI中附加上參數,應用程式在完成激活操作的過程中可以根據URI傳遞的參數來做出相應的處理。
協定URI是以協定名稱開頭,後面緊跟一個英文冒号。冒号後面的内容可以根據實際情況來定義,是可選的。假設某個應用程式注冊了名為"topic"的協定,那麼要激活該應用程式的話,可以使用Launcher類的LaunchUriAsync方法啟動,傳入方法參數的URI為:
topic:
帶參數的URI可以這樣寫:
topic:12345
冒号後面的所有内容都可以視為附加參數,參數的格式沒有特殊要求,因為當應用程式被激活後,該URI會被傳遞到應用程式中進行處理,是以對URI的分析和處理都可以由開發者自行控制。
在App類中重寫的OnActivated方法中,根據方法參數的Kind屬性的值來判斷應用程式是否由協定URI激活。如果屬性的值為ActivationKind.Protocol,則表明應用程式确實是通過協定相關的URI激活的。
下面将通過示例來示範一下如何為應用程式自定義協定資訊。該示例注冊一個名為"color"的協定,當通過該協定相關的URI激活應用程式後,應用程式會分析URI中所指定的的RGB顔色值,導航到一個應用頁面,頁面中有一個矩形,程式将使用URI傳遞的RGB值來填充該矩形。
App類中重寫的OnActivated方法實作如下,以響應協定激活行為:
protected override void OnActivated(IActivatedEventArgs args)
{
base.OnActivated(args);
if (args.Kind == ActivationKind.Protocol)
{
ProtocolActivatedEventArgs protoarg = args as ProtocolActivatedEventArgs;
//分析URI
Uri actUri = protoarg.Uri;
//擷取查詢字元串
string q = actUri.Query;
//去掉查詢字元串前面的"?"
q = q.Replace("?", "");
//通過正規表達式來查找URI參數中的key -value對
Regex r = new Regex(@"((?<key>[^&=]+)=(?<value>[^&=]+))+");
MatchCollection matches = r.Matches(q);
IDictionary<string, string> dic = new Dictionary<string, string>();
//将識别出來的各組key-value對存入字典對象中
foreach (Match match in matches)
{
string _key = match.Groups["key"].Value;
string _value = match.Groups["value"].Value;
dic.Add(_key,_value);
}
//導航到顯示顔色效果的頁面
Frame rootFrame = Window.Current.Content as Frame;
if (rootFrame is null)
{
rootFrame = new Frame();
Window.Current.Content = rootFrame;
}
else
{
//清除後退導航堆棧
rootFrame.BackStack.Clear();
}
//導航并傳遞參數
rootFrame.Navigate(typeof(ShowColorPage),dic);
Window.Current.Activate();
}
}
由args.Kind屬性确認應用程式的激活行為是通過協定URI完成的,之後需要将方法參數轉換為ProtocolActivatedEventArgs,ProtocolActivatedEventArgs類公開了一個Uri屬性,激活應用程式所使用的的URI被傳遞到該屬性中。
本例中使用的協定URI的格式如下:
color:?r=100&g=50&b=70
之是以在參數前面加上一個"?“符号,是為了讓Uri類的Query屬性能夠分析出查詢字元串,URI的查詢字元串一般都是以”?"開頭的,如http://abc.com/?cid=200。
但是,在處理URI的參數時要把“?”去掉,這樣一來,随後的正規表達式就可以正确地比對出r=100,g=50,b=70這三段字元了,即:
//去掉查詢字元串前面的"?"
q = q.Replace("?", "");
//通過正規表達式來查找URI參數中的key -value對
Regex r = new Regex(@"((?<key>[^&=]+)=(?<value>[^&=]+))+");
MatchCollection matches = r.Matches(q);
當正規表達式比對完成後,将分析出來的字元串添加到一個字典對象中。
//将識别出來的各組key-value對存入字典對象中
foreach (Match match in matches)
{
string _key = match.Groups["key"].Value;
string _value = match.Groups["value"].Value;
dic.Add(_key,_value);
}
由于指定的正規表達式中命名了兩個組:key和value,當比對=成功後,每一段字元串中名為key的分組中的值為"r",value分組的值則為100。最終字典對象中的内容為:
r:100
g:50
b:70
分析完成後,會導航到ShowColorPage頁面,并把該字典對象作為導航參數傳遞。接下來需要完成ShowColorPage頁面。其XAML如下:
<Grid>
<Rectangle Width="200" Height="250">
<Rectangle.Fill>
<SolidColorBrush x:Name="sldBrush"/>
</Rectangle.Fill>
</Rectangle>
</Grid>
背景代碼中,重寫OnNavigatedTo方法,如下:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
IDictionary<string, string> dic = e.Parameter as Dictionary<string, string>;
if (dic != null)
{
//讀出各個顔色通道的值
byte r, g, b;
if (!byte.TryParse(dic["r"],out r))
{
r = 0;
}
if (!byte.TryParse(dic["g"],out g))
{
g = 0;
}
if (!byte.TryParse(dic["b"],out b))
{
b = 0;
}
//修改畫刷的顔色
sldBrush.Color = Color.FromArgb(255,r,g,b);
}
}
最後,在項目清單檔案中,聲明協定擴充項,應用程式才會在安裝時自動向作業系統注冊協定。打開清單檔案(Package.appxmanifest),在Application節點下輸入以下XML:
<Extensions>
<uap:Extension Category="windows.protocol">
<uap:Protocol Name="color"/>
</uap:Extension>
</Extensions>
Protocol元素的Name特性指定協定的名字為"color"。
建立另一個uwp項目用來啟動該協定,以啟動目标用戶端:
<Grid>
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Spacing="10">
<TextBox x:Name="tb" MinWidth="200" MinHeight="100"/>
<Button Content="啟動目标用戶端" Tapped="Button_Tapped"/>
</StackPanel>
</Grid>
按鈕Tapped事件處理程式:
private async void Button_Tapped(object sender, TappedRoutedEventArgs e)
{
if (string.IsNullOrEmpty(tb.Text))
{
return;
}
await Launcher.LaunchUriAsync(new Uri(tb.Text));
}
運作效果:uwp,協定激活示例