天天看点

协议激活(uwp)

为应用程序注册协议后,可以通过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,协议激活示例