過去介紹過 註冊 URI scheme 就利用自定義的 URI scheme 在網頁或是 App 裏面呼叫自己的 App 起來做事情。 Windows 10(14393) 加入新功能(web-to-app linking),讓 user 開啓 http/https 的網站連結時,不是開啓 web browser 而是開啓 App。
web-to-app linking 技術讓 App 與 website 可以互相串聯,例如:原本在 App 已經做好購物機制,在用戶在瀏覽網頁或是點到特定的 URL link 時就會開啓 App 進去必要的流程跟畫面。
如果 website 未註冊支援該 App,用戶點擊了連結一樣只是開啟 web browser,使用經驗是不會有影響的。
要做到這樣的效果有幾個重點:
- 在 App 的 package.manifest 宣告要處理的網站路徑
- 在該網站的 root 目錄層加入特定的檔案,裡面宣告要支援的 App package family name
- 在 App 加入 OnActived 的事件處理由連結送入的内容
Step1. 在 package.manifest 宣告要處理的 http 與 https link:
<Application>
<Extensions>
<uap3:Extension Category="windows.appUriHandler">
<uap3:AppUriHandler>
<!-- 可以加入到 1000 組 -->
<uap3:Host Name="botwebhook.azurewebsites.net" />
</uap3:AppUriHandler>
</uap3:Extension>
</Extensions>
</Application>
uap3 來自 http://schemas.microsoft.com/appx/manifest/mobile/windows10 的定義,需要把 App 升級到 target version: 14393 才會被讀取。
另外,在 uap3 裏面還有更多的説明可以參考 uap3:AppUriHandler。
Step2. 在網站的根目錄加入 JSON 格式的檔案,命名為: windows-app-web-link 不需要副檔名 :
[
{
"packageFamilyName": "d78b1add-10d6-43c8-b4d9-445edc861b0f_s1mb6h805jdtj",
"paths": [ "*" ],
"excludePaths" : [ "/news/*", "/blog/*" ]
},
{
"packageFamilyName": "Your2ndAppsPFN",
"paths": [ "/example/*", "/links/*" ]
}
]
格式説明:
- packageFamilyName:可以從 package.manifest 中取得,代表該 App
- paths: 定義可以被註冊的網站路徑。衹有被寫在這裏的路徑,App 才會被觸發
- excludePaths: 定義被排除不可以被訪問的網站路徑
由於網站的目錄很多層,因此,可以利用萬用字元(wildcards)來定義,如下説明:
Wildcard | Description |
\* | Represents any substring |
? | Represents a single character |
例如上述範例, /news/* 代表 news 目錄下的檔案都可以存取;如果是 /new*/ 代表是任何 new 起頭的目錄都可以使用;
盡量多使用 excludePaths 規範 App 所要支援的範圍,避免用戶點擊 link 後進入到 App 不能處理的範圍反而更糟糕。
放在 web server 根目錄的 JSON 檔案會在 App 被安裝的時候,Windows 系統利用 https 連線去檢查是否符合格式。
Step3. App.xaml.cs 註冊處理 OnActivated 事件:
protected override void OnActivated(IActivatedEventArgs e)
{
Frame rootFrame = Window.Current.Content as Frame;
if (rootFrame == null)
{
// 建立 rootFrame 邏輯與還原之前的 App 狀態
}
// Check ActivationKind, Parse URI, and Navigate user to content
Type deepLinkPageType = typeof(MainPage);
if (e.Kind == ActivationKind.Protocol)
{
var protocolArgs = (ProtocolActivatedEventArgs)e;
switch (protocolArgs.Uri.AbsolutePath)
{
// ... 利用 url path 來拆解要前往的目錄
}
}
// Default navigation
rootFrame.Navigate(deepLinkPageType, e);
// Ensure the current window is active
Window.Current.Activate();
}
上面是截取 Support web-to-app linking with app URI handlers 的程式片段。
可以看出在 JSON 裏面定義的路徑,在 OnActivated 事件拿到的就是可存取範圍的 path,藉由拆開 path 轉還到特定的頁面,link 裏面有帶一些 query string 一樣可以被處理。
[補充]
1. 根據 Support web-to-app linking with app URI handlers 提到:
- 需要確定寫在 windows-app-web-link 裡的路徑(link) 都是 App 可以處理的,如果不行要記得移除以免用戶錯亂
- 在宣告處理多個 host 時,要注意 www.example.com 與 example.com 是不同的 host
- 用戶可以自行從設定中選擇開啓 link 的對象是誰
- windows-app-web-link 檔案必須上傳到有支援 https 的 server
- 如果需要更換支援的 link,不需要更新 App 只要更新 windows-app-web-link 檔案,用戶在 1-8 天之内就會更新
- 宣告在 package.manifest 的 host 時,系統會自動去驗證該 host 是否有 windows-app-web-link 檔案,不需要自己上傳
- This feature works whenever your app is a UWP app launched with LaunchUriAsync or a Windows desktop app launched with ShellExecuteEx. If the URL corresponds to a registered App URI handler, the app will be launched instead of the browser.
2. 如果在 Desktop 下, 開啓 Edge (或是其他的 browser) 點擊 link 是不會開啓 App 的,只能透過 Windows Key + R 輸入要測試的 link 。
或是把 link 傳給其他的 app (例如:LINE, Facebook messenger) 從裡面點擊 link 也是可以。
3. 在 Mobile 下,在 Edge 裏面點擊註冊 host 的 link 是可以直接開啓 App 的 4. 如果想要從設定裏面調整 apps for websites 的設定可以參考下圖:
- Mobile 在 settings/Apps/Apps for websites
- Desktop 在 settings/System/Apps for websites
[範例程式]
Link: DeeplinkSample
根據上面介紹的内容,我建立一個比較常見的網站範例來做說明,例如:網站有分語系,分功能範圍,因此網址如下:
- https://{domain}/{language}/{function}/{path}
- {language} 提供: en, tw, cn
- {function} 提供: food, book, ticket
- {path} 屬於隨意檔案類型: *
- host name: depplinksampleweb.azurewebsites.net
參考上面的説明,需要在 windows-app-web-link 這個 JSON 定義開發對應的路徑,如下:
[
{
"packageFamilyName": "5a578a94-4456-40e4-ac47-7ce11352856b_s1mb6h805jdtj",
"paths": [ "/en/*", "/tw/*", "/cn/*" ],
"excludePaths": [ "/en/food/*", "/tw/food", "/cn/food/" ]
}
]
接著在 UWP 的 package.manifest 加入 windows.appUriHandler 的定義,以及 OnActivated 的事件:
protected override void OnActivated(IActivatedEventArgs args)
{
var rootFrame = GetOrCreateRootFrame(null);
if (args.Kind != ActivationKind.Protocol)
{
return;
}
var protocolArgs = args as ProtocolActivatedEventArgs;
// linkL https://{domain}/{language}/{function}/{file}?{query_string}
Uri linkUri = protocolArgs.Uri;
Type pageType = typeof(MainPage);
// 利用 {function} 路徑識別,如果 {file} 也是判斷依據可以再寫下一層的邏輯
switch (linkUri.Segments[2].Replace("/",string.Empty))
{
case "book":
pageType = typeof(BookPage);
break;
case "ticket":
pageType = typeof(TicketPage);
break;
default:
break;
}
rootFrame.Navigate(pageType, linkUri.Query);
}
根據拿到的 link 做拆解,因爲可以拿得到 query string 的内容,更可以拿來做一些判斷,非常容易。
======
這個用途在 Android, iOS 系統很常見,作爲 UWP 開發人員是一定要加入的。趕快來試看看吧,希望對大家有幫助。
References:
- Support web-to-app linking with app URI handlers
- Launch an app with a URI
- Handle URI activation
- Deep Linking with UWP
- Web-to-App Linking with AppUriHandlers
- Handle app activation
- Extensions (in Application) (Windows 10)
- Create a Universal Windows App Target
- Deep link from a background app in Cortana to a foreground app
- Deep links and app-to-app communication
- Launch an app on a remote device
- Reserved file and URI associations for Windows Phone 8
- uap3:Extension (Windows 10)
- uap3:AppExtensionHost
- uap3:AppUriHandler
- Hyperlinks
- Create a Cortana skill