上一篇提到Windows Store協議的使用,其實Windows Store協議僅是系統內建的一種協議規則。咱們也能夠本身定義一套規範的URI-Scheme,除了能夠給其餘App調用外,本應用也能夠進行調用,解決一些特殊的場景,本講具體探討這一問題。html
關於Windows Store協議的解析和使用,可先閱讀上一篇:http://www.cnblogs.com/zhxilin/p/4819372.html前端
前面提到,經過協議,應用能夠被「激活(Activated)」,而且能夠自行處理激活以後的操做。應用商店這個App的原理很簡單,它在Package.appxmanifest裏定義了一個「協議」類型的聲明叫ms-windows-store,咱們能夠模擬一下:web
因爲ms-windows-store被定義爲內建的協議,咱們自定義協議時並不能使用這個名稱,這裏用ms-windows-store1代替。windows
關於更多內建協議的使用規則,請參考:https://msdn.microsoft.com/en-us/library/windows/apps/mt228340.aspxapp
回到App.cs裏,重載OnActivated方法,該方法接收一個IActivatedEventArgs類型的參數:async
1 protected override async void OnActivated(IActivatedEventArgs args) 2 { 3 // TODO: handle activate action 4 }
經過args參數的Kind屬性來肯定具體是哪一種類型激活了應用,咱們這裏只處理Protocol類型的激活(由於自定義協議就是一種Protocol):ide
1 protected override async void OnActivated(IActivatedEventArgs args) 2 { 3 if (args.Kind == ActivationKind.Protocol) 4 { 5 if (!_hasLaunched) 6 { 7 CreateRootFrame(); 8 _hasLaunched = true; 9 } 10 11 var protocalArgs = (ProtocolActivatedEventArgs) args; 12 if (protocalArgs.Uri.Scheme == AppConfig.MyAppScheme) 13 { 14 UrlSchemeHelper.ParseScheme(protocalArgs.Uri); 15 } 16 } 17 Window.Current.Activate(); 18 }
肯定了屬於協議激活後,將args轉成對應類型的參數ProtocolActivatedEventArgs,最終咱們如同處理一個普通http url同樣,自定義個一個UrlSchemeHelper類進行解析和頁面導航,具體處理請自行腦洞。函數
自定義協議,對呼叫協議做不一樣的響應,這是一件很是酷的事情。不只能夠給第三方應用調用,還能夠給應用自己調用,處理一些特殊場景!我這裏要說的一個特殊的適用場景就是App和Web頁面的交互。url
App和Web頁面的交互是很是廣泛的情景,通常頁面都會考慮直接使用腳本進行通知,而且我相信絕大部分前端開發者都已經被逼瘋:WP須要一種處理,iOS又是另外一種處理;前端得判斷請求來自什麼平臺,並且還不許確,BlaBla....總之問題很是多!spa
如今有這樣一個需求,好比在一個Web頁面裏有一個按鈕,觸發了這個按鈕以後要求App跳轉到某一個指定頁面,一般寫個腳本的話應該是這樣的(UWP應使用window.external.notify("")函數,且只能返回字符串)
1 function onNavigateClick() { 2 window.external.notify("navigate:some_page"); 3 }
App在WebView上註冊void Browser_ScriptNotify(object sender, NotifyEventArgs e)事件,經過參數e.Value將web頁面的通知內容「navigate:some_page」取出來作相應處理。
然而ScriptNotify事件的侷限性很是大:
1.window.external.notify只能返回字符串
2.只有本地的Web頁面(ms-appdata、ms-local-stream或ms-appx-web),或者受信任的HTTPS才能觸發事件;普通HTTP沒法觸發
大多數Web頁面都是HTTP的,而且若是下載到本地再顯示每每有問題,所以對UWP來講,這種交互方式簡直就是噩夢!不只前端痛苦,客戶端也痛苦!
這時候自定義協議就能夠發揮其功力了!一樣的例子,如今徹底能夠改爲協議的形式來進行通知:
1 function onNavigateClick() { 2 window.location.href = 'myapp://page?id=1&title=hero'; 3 }
App裏就用上述提到的方式接收通知!
且慢,在UWP項目中,在一個WebView裏,某一個html頁面經過自定義的URI-Scheme的形式來通知APP時,WebView會觸發一個UnsupportedUriSchemeIdentified事件,表示WebView並不認識這個協議,是否要處理取決於你。
UWP的WebView默認只能處理http, https, ms-appx-web和ms-local-stream這幾種協議,對於其餘協議,都會觸發UnsupportedUriSchemeIdentified事件,而且會彈出一個警告對話框:
爲了避免顯示這個對話框,咱們須要手動處理一下:
1 private async void WebView_OnUnsupportedUriSchemeIdentified(WebView sender, WebViewUnsupportedUriSchemeIdentifiedEventArgs args) 2 { 3 args.Handled = true; 4 if (args.Uri.Scheme == AppConfig.MyAppScheme) 5 { 6 await Launcher.LaunchUriAsync(args.Uri); 7 } 8 }
先將args.Handled標記爲true,警告對話框就不會彈出了;而後再經過Launcher嘗試啓動這個WebView不識別的URI;最後用咱們上述講到的處理方式在App.OnActivated中接收並解析。
這樣的好處徹底解放了前端開發的壓力,這套機制適用於各類各樣的客戶端(iOS、Android、WP、Windows等);對於客戶端而言,定義規範化的URI-Scheme有助於維護和擴展,甚至能夠發展成開發平臺或開放應用(如同商店APP同樣)。