windows phone 8 中应用间的通信,之前在windows phone 7 在一部手机中的应用间想进行一些数据通信除了使用service, 在应用间几乎是不可能,但是在windows phone 8中SDK给了我们这样的API今天就为大家详细介绍下。

此文是 升级到WP8必需知道的13个特性 系列的一个更新 希望这个系列可以给 Windows Phone 8开发者带来一些开发上的便利。

同时欢迎大家在这里和我沟通交流或者在新浪微博上 @王博_Nick

1. 文件关联应用

作为一个接收共享文件的应用 是将一个文件保存在共享隔离存储器中然后由目标应用从共享隔离存储器中取出文件的过程。

首先介绍下如何注册成为一个可以接收文件的应用

注册您的应用为一个支持某种文件类型的应用,一旦你的应用安装到用户的机器上后用户尝试打开此种类型文件在选择列表中就会出现你的应用图标。

应用图标尺寸如下:

并且需要在Manifest文件中指定支持的文件类型:

   
   
   
   
  1.   
  2.    Name="Windows Phone SDK test file type" TaskID="_default" NavUriFragment="fileToken=%s">  
  3.          
  4.            Size="small" IsRelative="true">Assets/sdk-small-33x33.png  
  5.            Size="medium" IsRelative="true">Assets/sdk-medium-69x69.png  
  6.            Size="large" IsRelative="true">Assets/sdk-large-176x176.png  
  7.          
  8.          
  9.          "application/sdk">.sdkTest1  
  10.          "application/sdk">.sdkTest2 
  11.  
  12.          
  13.      
  14.  

Logo中指定在不同情况下显示的图标

FileType中注册的是支持文件类型 这里最多支持20个不同的文件类型

监听一个文件的操作:

实际上当你的应用受到一个打开文件的请求时 应用程序是接收到一个包含 获取在共享隔离存储器中的一个Token连接的:
/FileTypeAssociation?fileToken=89819279-4fe0-4531-9f57-d633f0949a19

所以在我们的TargetApp中需要处理下接收参数 方法如下使用App中的InitializePhoneApplication方法

   
   
   
   
  1. private void InitializePhoneApplication() 
  2.     if (phoneApplicationInitialized) 
  3.         return
  4.  
  5.     // Create the frame but don't set it as RootVisual yet; this allows the splash 
  6.     // screen to remain active until the application is ready to render. 
  7.     RootFrame = new PhoneApplicationFrame(); 
  8.     RootFrame.Navigated += CompleteInitializePhoneApplication; 
  9.  
  10.     // Assign the URI-mapper class to the application frame. 
  11.     RootFrame.UriMapper = new AssociationUriMapper(); 
  12.  
  13.     // Handle navigation failures 
  14.     RootFrame.NavigationFailed += RootFrame_NavigationFailed; 
  15.  
  16.     // Ensure we don't initialize again 
  17.     phoneApplicationInitialized = true

AssociationUriMapper 的实现

   
   
   
   
  1. using System; 
  2. using System.IO; 
  3. using System.Windows.Navigation; 
  4. using Windows.Phone.Storage.SharedAccess; 
  5.  
  6. namespace sdkAutoLaunch 
  7.     class AssociationUriMapper : UriMapperBase 
  8.     { 
  9.         private string tempUri; 
  10.  
  11.         public override Uri MapUri(Uri uri) 
  12.         { 
  13.             tempUri = uri.ToString(); 
  14.  
  15.             // File association launch 
  16.             if (tempUri.Contains("/FileTypeAssociation")) 
  17.             { 
  18.                 // Get the file ID (after "fileToken="). 
  19.                 int fileIDIndex = tempUri.IndexOf("fileToken=") + 10; 
  20.                 string fileID = tempUri.Substring(fileIDIndex); 
  21.  
  22.                 // Get the file name
  23.                 string incomingFileName = 
  24.                     SharedStorageAccessManager.GetSharedFileName(fileID); 
  25.  
  26.                 // Get the file extension. 
  27.                 string incomingFileType = Path.GetExtension(incomingFileName); 
  28.  
  29.                 // Map the .sdkTest1 and .sdkTest2 files to different pages. 
  30.                 switch (incomingFileType) 
  31.                 { 
  32.                     case ".sdkTest1"
  33.                         return new Uri("/sdkTest1Page.xaml?fileToken=" + fileID, UriKind.Relative); 
  34.                     case ".sdkTest2"
  35.                         return new Uri("/sdkTest2Page.xaml?fileToken=" + fileID, UriKind.Relative); 
  36.                     default
  37.                         return new Uri("/MainPage.xaml", UriKind.Relative); 
  38.                 } 
  39.             } 
  40.             // Otherwise perform normal launch. 
  41.             return uri; 
  42.         } 
  43.     } 

导航页面中获取参数的方法

   
   
   
   
  1. // Get a dictionary of URI parameters and values
  2. IDictionary queryStrings = this.NavigationContext.QueryString; 

当你获取到共享文件的Token后你就可以从共享存储空间通过 GetSharedFileName文件名称(包括文件在拓展名)和 CopySharedFileAsync 将共享文件拷贝到Target应用的隔离存储区

   
   
   
   
  1. protected override async void OnNavigatedTo(NavigationEventArgs e) 
  2.     base.OnNavigatedTo(e); 
  3.     IDictionary queryStrings = this.NavigationContext.QueryString; 
  4.     string fileToken = queryStrings["fileToken"]; 
  5.     var filename = SharedStorageAccessManager.GetSharedFileName(fileToken); 
  6.  
  7.     var file = await SharedStorageAccessManager.CopySharedFileAsync(Windows.Storage.ApplicationData.Current.LocalFolder, 
  8.                                                                       filename, Windows.Storage.NameCollisionOption.ReplaceExisting, 
  9.                                                                       fileToken); 
  10.     StreamResourceInfo reader = Application.GetResourceStream(new Uri(file.Path, UriKind.Relative)); 
  11.     StreamReader streamRead = new StreamReader(reader.Stream); 
  12.     string responseString = streamRead.ReadToEnd(); 
  13.     streamRead.Close(); 
  14.     streamRead.Dispose(); 
  15.  
  16.     MessageBox.Show(responseString); 

 作为一个发出共享文件的应用要做的相对简单许多使用  Windows.System.Launcher.LaunchFileAsync 即可

   
   
   
   
  1. private async void LaunchFileButton_Click(object sender, RoutedEventArgs rea) 
  2.  
  3.     // Access isolated storage. 
  4.     StorageFolder local = Windows.Storage.ApplicationData.Current.LocalFolder; 
  5.  
  6.     // Access the bug query file. 
  7.     StorageFile bqfile = await local.GetFileAsync("file1.bqy"); 
  8.  
  9.     // Launch the bug query file. 
  10.     Windows.System.Launcher.LaunchFileAsync(bqfile); 
  11.  

 2. URl关联应用 简单的说就是使用一个类似 URL的string 字符串来启动某个应用程序 (传参数形式和传统的网页十分相似)

首先介绍如何注册成为一个支持 URI assocations 的一个应用

每个应用可以声明为一个契约 Protocol Name 这个契约名称是启动这个 target app 的关键字也是要在Manifest文件中声明

Name的string 长度要求在2-18个char之间的数字小写字母 英文句点(.)和连字符(-)

   
   
   
   
  1.  
  2.   Name="contoso" NavUriFragment="encodedLaunchUri=%s" TaskID="_default" /> 
  3.  

如何监听一个URl并且获得参数

 同样在target App中的InitializePhoneApplication 使用 AssociationUriMapper来实现判断

   
   
   
   
  1. private void InitializePhoneApplication() 
  2.     if (phoneApplicationInitialized) 
  3.         return
  4.  
  5.     // Create the frame but don't set it as RootVisual yet; this allows the splash 
  6.     // screen to remain active until the application is ready to render. 
  7.     RootFrame = new PhoneApplicationFrame(); 
  8.     RootFrame.Navigated += CompleteInitializePhoneApplication; 
  9.  
  10.     // Assign the URI-mapper class to the application frame. 
  11.     RootFrame.UriMapper = new AssociationUriMapper(); 
  12.  
  13.     // Handle navigation failures 
  14.     RootFrame.NavigationFailed += RootFrame_NavigationFailed; 
  15.  
  16.     // Ensure we don't initialize again 
  17.     phoneApplicationInitialized = true

AssociationUriMapper 和 文件的稍有不同

   
   
   
   
  1. private void InitializePhoneApplication()  
  2. {  
  3.     if (phoneApplicationInitialized)  
  4.         return;  
  5.   
  6.     // Create the frame but don't set it as RootVisual yet; this allows the splash  
  7.     // screen to remain active until the application is ready to render.  
  8.     RootFrame = new PhoneApplicationFrame();  
  9.     RootFrame.Navigated += CompleteInitializePhoneApplication;  
  10.   
  11.     // Assign the URI-mapper class to the application frame.  
  12.     RootFrame.UriMapper = new AssociationUriMapper();  
  13.   
  14.     // Handle navigation failures  
  15.     RootFrame.NavigationFailed += RootFrame_NavigationFailed;  
  16.   
  17.     // Ensure we don't initialize again  
  18.     phoneApplicationInitialized = true;  
  19. }  

同样在Target app 的 target page的OnNavigatedTo事件中获取参数

   
   
   
   
  1. // Get a dictionary of URI parameters and values.
    IDictionary<string, string> queryStrings = this.NavigationContext.QueryString;

 在source App中调用 target App相对来说非常简单

   
   
   
   
  1. private async void LaunchContosoNewProductsButton_Click(object sender, RoutedEventArgs rea) {     // Launch URI.
        Windows.System.Launcher.LaunchUriAsync(new System.Uri("contoso:NewProducts")); }

这里要特别强调的一点是 目标应用受到的信息是

“/Protocol?encodedLaunchUri=contoso%3ANewProducts”. 这样的一段URI 需要你的AssociationUriMapper帮忙decode处理一下

URL的Launching同样支持使用与基于NFC的近场通讯技术

   
   
   
   
  1. ProximityDevice device = ProximityDevice.GetDefault();  // Make sure NFC is supported
    if (device != null) {     long Id = device.PublishUriMessage(new System.Uri("contoso:NewProducts"));     Debug.WriteLine("Published Message. ID is {0}", Id);      // Store the unique message Id so that it      // can be used to stop publishing this message
    }

LaunchUriAsync 不仅仅可以Launch其他应用 同样可以唤起URL Email 和各种Setting 以及 WindowsPhone应用商店中的内容

详细内容 :http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj662937(v=vs.105).aspx

应用的关联可以是

  • 邮件的附件
  • IE浏览器中的一个文件
  • 或者是一个NFC的Tag标签
  • 一个应用程序的共享文件

系统保留的文件类型和scheme name 列表

请参考:

http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj207065(v=vs.105).aspx

 

今天就给大家介绍到这里,说的不明白的欢迎大家拍砖 也可以在新浪微博上 @王博_Nick