WP8 - App2App Communication - Protocol (URI Schema)

Windows Phone 8 - App2App Communication - Protocol (URI Schema)

終於等到Windows Phone 8提供讓應用程式之間可以相溝通的能力了,記得在Windows Phone 7.1的時候,

開發者們聊天時如果談到應用程式溝通在Android/iOS裡都相當容易時,但在7.1 SDK時並未支援這樣豐富的功能,

好在這樣的需求終於在Windows Phone 8有了解決的方式。

 

馬上來看看Windows Phone 8如何提供應用程式之間互動的溝通吧。

 

〉Protocol

     在WP8 SDK提供開發人員可設計自己的應用程式,可以接受其他程式的串聯或是針對某特定檔案類型進行讀取

讓應用程式與特定檔案之間可以溝通,那其中的關鍵在於:Protocol。例如:email中夾帶的附件是PDF,那在自己

的應用程式裡增加對PDF的識別,即可以在email中開啟PDF附件的程式清單出現自己的應用程式;或是程式裡有一

個Web URL可以串聯Browser進行瀏覽;更或是有多個程式可以管理航班資訊,可定義Protocol來與其他旅行用的應

用程式互相串聯,如同一個航班到達一個目的地,即串聯該旅行程式的相關資訊。

 

上述說明可以了解WP8開始支援互動的方式,因此,每一個應用程式可以宣告一個固定的URI Schema Name與File Type

來進行處理,當系統遇到固定的URI Schema Name或File Type時,即會執行有宣告的應用程式

 

在Windows Phone 8 SDK裡針對應用程式之間的互動提供二個重要的關聯方式:(1) File Association;(2) URI Schema

關於File Associations使用,可參考<Windows Phone 8 - 應用程式互相溝通方式(App-to-App Communication) - 2>的說明。

以下針對Protocol Invoke (URI Schema) 進行說明:

 

〉Protocol Invoke (URI Schema)

     針對特定的URI格式來啟動另一個應用程式。其原理在實作一個應用程式並註冊它監聽某一個特定的Protocol

當有其他應用程式利用此Protocol建立一個URI並呼叫它時,該監聽的應用程式會自動收到並啟動。其URI裡也可以

額外夾帶參數進行傳遞,如同網頁的QueryString使用方式。

 

A. 設定URI schema name associations:以recipe://為例

     今天想讓應用程式接收固定的URI schema,假設宣告對 recipe:// 該URI Schema的監聽。那應用程式要如何調整才能在

系統遇到該URI Schema時可找得到應用程式。

(A-1). 開啟WMAppManifest.xml中的<Extension />標籤中加入新的標籤,來註冊要監聽的URI Schema

            [注意]

             1. 注意<Extension />的標籤必需接在<Token />標籤之後;

             2. 定義的URI Schema name不可以為保留字(例如:http、tel、mailto等),使用保留字系統會自動勿略不註冊;

   1: <Extensions>
   2:     <!-- 注意Name與NaviUriFragment的屬性值 -->
   3:     <!-- Name 代表 URI Schema name -->
   4:     <!-- NavUriFragment 代表 App收到的完整URI資料,%s是系統放值的部分,LaunchUri是前註詞,可自訂 -->
   5:     <Protocol Name="recipe" TaskID="_default" 
   6:               NavUriFragment="LaunchUri=%s" />
   7: </Extensions>

 

(A-2). 定義URI Mapping處理URI Schema的Associations

             要如何實作URI Mapping,如果大家有讀過<WP7 修練 DAY 02:如何在頁面顯示前自動轉向到其他頁面>與

             <Windows Phone 7 - 動態轉換初始的Default Page>便可得知SDK裡提供一個UriMapBase的類別與UriMapper類別,

             讓開發者可以自訂應用程式一開始要進入的Page。因此,相同的道理套入,往下便加以說明如何處理URI Mapping

             與Query String的使用;

             (A-2-1). 建立個新的Class,並繼承UriMapBase,修改MapUri方法,為收到特定的URI可以轉向指定的Page

                             定義了一個目標的Page:SecondPage.xaml,準備接受來自URI Schema的串聯;然而,下方有一個變數:

                            ProtocolTemplate,該變數的值有注意到了嗎?它與在WMAppManifest.xml中的NavUriFragement是相同的

                             只是前方加上了"/Protocol?"字段。因此,可以導出,在運作MapUri()這個方法時,預期會收到的完整URI字串為:

                             "/Protocol?LaunchUri=recipe%3A%2F%2FShowRecipe%2F%3FName%3D1003%26Age%3D29",透過HttpUtility.UrlDecode()

                             變成"/Protocol?LaunchUri=recipe://ShowRecipe/?Name=1003&Age=29"。

   1: public class MyUriMapper :UriMapperBase
   2: {
   3:     //指定要前往的Page
   4:     private static string TargetPageName = "SecondPage.xaml";
   5:     //指定要拆解的Protocol Template,該字段是固定由系統組合的,在拆時可以先去掉;
   6:     private static string ProtocolTemplate = "/Protocol?LaunchUri=";
   7:     private static int ProtocolTemplateLength = ProtocolTemplate.Length;
   8:     private string tempUri;
   9:  
  10:     //必須需作的override範圍
  11:     public override Uri MapUri(Uri uri)
  12:     {
  13:         tempUri = uri.ToString();
  14:         //判斷URI是否具有/Protocol的字段,有此字段代表是URI Schema Associations;
  15:         if (tempUri.Contains("/Protocol") == true)
  16:         {
  17:             //UrlDecoding
  18:             tempUri = HttpUtility.UrlDecode(tempUri);
  19:             //判斷是否具有監控的Schema
  20:             if (tempUri.Contains("recipe:") == true)
  21:             {
  22:                 return GetMappedUri(tempUri, 0);
  23:             }
  24:         }
  25:         return uri;
  26:     }
  27:  
  28:     private Uri GetMappedUri(string pUri, int X)
  29:     {
  30:         string tQueryString = string.Empty;
  31:         if (pUri.IndexOf(ProtocolTemplate) > -1)
  32:         {
  33:             //由於組合的來的URI為:/Protocol?LaunchUri=recipe://ShowRecipe?ID=1003
  34:             //因此,拆出?{parameter}={value}&{parameter}={value}.的值
  35:             int operationLen = pUri.IndexOf("?", ProtocolTemplateLength);
  36:             //取得實際用的QueryString
  37:             tQueryString = pUri.Substring(operationLen + 1);
  38:         }
  39:         //重建一個新的URI
  40:         string tNewUri = string.Format("/{0}?{1}", TargetPageName, tQueryString);
  41:         return new Uri(tNewUri, UriKind.Relative);
  42:     }
  43: }

         

(A-3).  將實作好的UriMapper取代App.cs.InitializePhoneApplication()裡RootFrame的UriMapper

              只有實作(A-2). 的UriMapper作好是不足的,還要用它去取代掉現有RootFrame.UriMapper才有辦法完成轉換URI的功能

   1: // Do not add any additional code to this method
   2: private void InitializePhoneApplication()
   3: {
   4:     if (phoneApplicationInitialized)
   5:         return;
   6:  
   7:     // Create the frame but don't set it as RootVisual yet; this allows the splash
   8:     // screen to remain active until the application is ready to render.
   9:     RootFrame = new PhoneApplicationFrame();
  10:     RootFrame.Navigated += CompleteInitializePhoneApplication;
  11:  
  12:     // Handle navigation failures
  13:     RootFrame.NavigationFailed += RootFrame_NavigationFailed;
  14:  
  15:     // Handle reset requests for clearing the backstack
  16:     RootFrame.Navigated += CheckForResetNavigation;
  17:  
  18:     //使用自訂的UriMapper,才能實現轉換URI的功能
  19:     RootFrame.UriMapper = new MyUriMapper();
  20:  
  21:     // Ensure we don't initialize again
  22:     phoneApplicationInitialized = true;
  23: }

 

(A-4). 實作SecondPage.xaml接收來自URI Schema所帶入的QueryString:Name與Age二個Key

            很簡單在SencondPage.xaml進行override它的OnNavigatedTo,以取得QueryString中的值並且顯示於畫面上,如下:

   1: protected override void OnNavigatedTo(NavigationEventArgs e)
   2: {
   3:     base.OnNavigatedTo(e);
   4:     //確認在QueryString中是否有存在的Key
   5:     if (NavigationContext.QueryString.ContainsKey("Name") == true)
   6:     {
   7:         string tName = NavigationContext.QueryString["Name"];
   8:         string tOld = NavigationContext.QueryString["Age"];
   9:         //取得值後並顯示於畫面上
  10:         tblName.Text = tName;
  11:         tblOld.Text = tOld;
  12:     }
  13: }

 

以上的步驟就實作完成讓自己的應用程式可以支援特定URI Schema的互動,總結其中重點在於:UriMapper的改寫,實作出可

自訂的URI Mapping Rules以及取出必要的QueryString值,以轉接給目標的Page或任務進行執行。

 

最後,還有一個步驟即是撰寫一個簡單的App,來完成App-to-App Communication的情境。

B. 建立一個簡單的Windows Phone專案,並且加上一個按鈕,按鈕事件則是呼叫A定義好的URI Schema

     如下程式段,透過指定的URI Schema來與註冊監聽該Schema的App進行互動;

   1: private void Button_Click_1(object sender, RoutedEventArgs e)
   2: {
   3:     //注意uURI Schema一定要與App註冊的相同
   4:     Uri tUri = new Uri("recipe://ShowRecipe?Name=1003&Age=29");
   5:     Windows.System.Launcher.LaunchUriAsync(tUri);
   6: }

上述程式有一段使用Windows.System.Launcher.LaunchUriAsync,這個是新的指令。特別用於指定的URI來啟動應用程式。

 

[執行結果]

111112113

圖示分別代表由:Another App把Name與Age帶至Second Page中的Name與Age。

 

[範例程式]

 

[補充]

UriMapperBase

    一個基礎的類別根據指定的Mapping Rules轉換一個URI的請求至另一個新URI的機制。

    透過Override該類別的MapUri方法即可以自訂轉換的邏輯。

    另外,自訂好的UriMapper 必須指定給Silverlight應用程式中的Frame物件,才會有效果

   

Windows.System.Launcher.LaunchUriAsync

     專用於透過指定的URI去關聯並啟動應用程式。啟動的方式有三種,如下:

Option Method Description
Default Launch LaunchUriAsync(Uri) Launch the specified Uri with the default handler.
Launch with a warning dialog LaunchUriAsync (Uri, LauncherOptions) Windows will show a warning dialog before launching the specified uri.
Launch with a recommended app fallback LaunchUriAsync (Uri, LauncherOptions) Launch the specified Uri with the default handler. If no handler is installed on the system recommend an app in the Windows Store to the user.

     目前使用的是第一種,不同的LauncherOptions會有對應的功能。

======

了解了Windows Phone 8如何處理應用程式之間的溝通後,不難發現其實三個平台的作法均相同,

所以如果您了解過Android或iOS的觀念,其實對於Windows Phone 8的觀念也不會太難理解了。

接下來會繼續介紹更多Windows Phone 8開發的新功能與技巧,希望對大家有所幫助。

 

References

Auto Launching Apps now possible using file associations for Windows Phone 8

[DEVDIV原创] WP8新特性【6】从一个应用程序启动另一个第三方应用程序(Protocol association)

How to launch the default app for a URI (Windows Store apps using C#/VB/C++ and XAML)

Guidelines and checklist for file types and URIs (Windows Store apps)

What's new in Windows Phone 8 (重要)

http://www.developer.nokia.com/Community/Wiki/URI_Association_Schemes_List (列出其他App的開放出來的URI association)

‧在Windows 8支援了更多的方式:

    ‧Auto-launching with file and URI associations (Windows Store apps using JavaScript and HTML)

    ‧How to handle file activation (Windows Store apps using JavaScript and HTML)

    ‧How to handle protocol activation (Windows Store apps using JavaScript and HTML)

    ‧How to launch the default app for a file (Windows Store apps using JavaScript and HTML)

 

Dotblogs Tags: