当另一个应用启动特定的文件类型或 URI 方案时,您可以使用 Windows Phone 8 中的文件和 URI 关联自动启动您的应用。启动后,深层链接 URI 将被用来向应用发送文件(对文件的引用)或 URI。您也可以使用关联启动 API 以相同的方式启动另一个应用。本主题描述了文件和 URI 关联以及如何在应用中使用它们。
提示: |
---|
类似于 Windows 8,Windows Phone 8 使用 LaunchFileAsync 启动文件,并使用 LaunchUriAsync 启动 URI。但是,Windows Phone XAML 应用接收文件或 URI 的方式却是不同的。此外, Windows Phone 没有“默认的”商店 应用。如果存在多个能够处理某个特定文件或 URI 关联的 商店 应用,用户可以从菜单中选择接收应用。 |
本主题包含以下各节。
当用户想要打开某个特定文件时,文件关联允许您的应用自动启动。该文件可能来自不同的来源,这包括但不限于以下来源:
-
电子邮件附件
-
Internet Explorer 中的网站
-
近距离无线通信 (NFC) 标记
-
商店 中的其他应用
文件关联还可以用来确定,通过使用外部存储 API,应用可以从 SD 卡读取哪些文件类型。有关这些 API 的更多信息,请参见 Windows Phone 的数据。
注册文件关联
要处理特定的文件类型,请在应用清单文件中注册文件关联。应用能够指定任何可处理的文件关联。但是,任何由内置应用保留的文件关联将被忽略。有关更多信息,请参见 Windows Phone 8 的保留文件和 URI 关联。
注意: |
---|
有时 Internet Explorer 重写文件关联:它启动内置的媒体播放器来处理所有的音乐和视频文件类型。具体来说,具有audio/或video/内容类型的任何文件。例如,应用从电子邮件附件启动时,它可以处理(非保留的)音乐和视频文件。但是如果从 Internet Explorer 启动相同的文件,则内置的媒体播放器将处理该文件。 |
要向在内置应用中显示的自定义文件类型提供“集成”外观,您可以选择是否提供在文件旁边显示的徽标(图像文件)。例如,如果文件(您自定义的类型)被附加到电子邮件,下载附件后,附件的旁边将显示一个小型的徽标。
文件类型徽标显示在白色背景前,请确保在测试应用时,检查您的徽标在手机上的显示方式。还请注意,如果不止一个应用注册了相同的文件类型,那么您将看不到您的徽标。在这种情况下,则使用常规徽标。下表列出了三种可向每个文件关联提供的图像大小。
徽标大小 | 用途 | 维度 |
---|---|---|
小 | 电子邮件附件 | 33x33 像素 |
中 | Office 中心列表视图 | 69x69 像素 |
大 | 浏览器下载 | 176x176 像素 |
提示: |
---|
作为最佳做法,我们建议您将徽标存储在应用包的资产文件夹中。 |
要注册文件关联,您必须使用 XML(文本)编辑器编辑 WMAppManifest.xml。在“解决方案资源管理器”中,右键单击 WMAppManifest.xml 文件,然后单击“打开方式”。在“打开方式”窗口中,选择“XML(文本)编辑器”,然后单击“确定”。
在应用清单文件的Extensions元素中,文件关联是使用FileTypeAssociation元素所指定的。请注意,Extensions元素必须紧跟在Tokens元素之后。下面的示例演示了称为“Windows Phone SDK 测试文件类型”的假想文件类型的文件关联,该关联能够处理两种不同文件扩展名:“.sdkTest1”和“.sdkTest2”。
<Extensions> <FileTypeAssociation Name="Windows Phone SDK test file type" TaskID="_default" NavUriFragment="fileToken=%s"> <Logos> <Logo Size="small" IsRelative="true">Assets/sdk-small-33x33.png</Logo> <Logo Size="medium" IsRelative="true">Assets/sdk-medium-69x69.png</Logo> <Logo Size="large" IsRelative="true">Assets/sdk-large-176x176.png</Logo> </Logos> <SupportedFileTypes> <FileType ContentType="application/sdk">.sdkTest1</FileType> <FileType ContentType="application/sdk">.sdkTest2</FileType> </SupportedFileTypes> </FileTypeAssociation> </Extensions>
下表描述了所有这些元素。
元素 | 父元素 | 说明 |
---|---|---|
Extensions | App | 必须跟在Tokens元素之后。 |
FileTypeAssociation | Extensions | 描述文件关联。您最多可以注册 20 个文件关联。必须提供Name特性,但您可以选择自己的友好名称。根据指示指定TaskID和NavUriFragment元素。 |
Logos | FileTypeAssociation | 列出文件关联的所有徽标。如果没有指定任何徽标,这是可选的。 |
Logo | Logos | 可选项。列出要显示在文件旁边的图像文件。若要提供大小,您必须提供所有大小(小、中等和大)。IsRelative特性必须存在并等于true。 |
SupportedFileTypes | FileTypeAssociation | 列出与文件类型相关联的所有文件扩展名。 |
FileType | SupportedFileTypes | 列出与文件类型相关的文件扩展名,包括句点 (‘.’)。每个文件关联最多可以关联 20 个文件扩展名。若您的应用从 SD 卡读取文件,您还必须指定ContentType特性以描述文件的类型。 |
侦听文件启动
当您的应用启动以处理某个特定的文件类型时,深层链接 URI 用于将用户带到您的应用。在 URI 中,FileTypeAssociation字符串指定 URI 的源为文件关联且fileToken参数包含文件标记。例如,以下代码显示了文件关联的深层链接 URI。
/FileTypeAssociation?fileToken=89819279-4fe0-4531-9f57-d633f0949a19
启动时,将传入的深层链接 URI 映射到能够处理该文件的应用页面。如果您拥有用于处理多个文件类型的多个页面,请在映射 URI 之前使用自定义的 URI 映射器和 GetSharedFileName 方法检查文件类型。例如,以下代码演示了用于分析深层链接 URI 并根据文件的类型映射不同页面的 URI 映射器。如果映射器不是从文件关联启动的,它会在保持 URI 不变的情况下,将完整的 URI 字符串发回到App对象。
using System; using System.Windows.Navigation; using Windows.Phone.Storage.SharedAccess; namespace sdkAutoLaunch { class AssociationUriMapper : UriMapperBase { private string tempUri; public override Uri MapUri(Uri uri) { tempUri = uri.ToString(); // File association launch if (tempUri.Contains("/FileTypeAssociation")) { // Get the file ID (after "fileToken="). int fileIDIndex = tempUri.IndexOf("fileToken=") + 10; string fileID = tempUri.Substring(fileIDIndex); // Get the file name. string incomingFileName = SharedStorageAccessManager.GetSharedFileName(fileID); // Get the file extension. int extensionIndex = incomingFileName.LastIndexOf('.'); string incomingFileType = incomingFileName.Substring(extensionIndex).ToLower(); // Map the .sdkTest1 and .sdkTest2 files to different pages. switch (incomingFileType) { case ".sdkTest1": return new Uri("/sdkTest1Page.xaml?fileToken=" + fileID, UriKind.Relative); case ".sdkTest2": return new Uri("/sdkTest2Page.xaml?fileToken=" + fileID, UriKind.Relative); default: return new Uri("/MainPage.xaml", UriKind.Relative); } } // Otherwise perform normal launch. return uri; } } }
在此类情况下,若要在您的应用中使用 URI 映射器类,请将其分配到该应用在 App.xaml.cs 文件中所对应的框架。在InitializePhoneApplication方法中,在RootFrame.Navigated已被分配后,紧接着将RootFrame.UriMapper属性设置为与您的 URI 映射器类相等。在下列示例中,AssociationUriMapper类被分配给框架的UriMapper属性。
private void InitializePhoneApplication() { if (phoneApplicationInitialized) return; // Create the frame but don't set it as RootVisual yet; this allows the splash // screen to remain active until the application is ready to render. RootFrame = new PhoneApplicationFrame(); RootFrame.Navigated += CompleteInitializePhoneApplication; // Assign the URI-mapper class to the application frame. RootFrame.UriMapper = new AssociationUriMapper(); // Handle navigation failures RootFrame.NavigationFailed += RootFrame_NavigationFailed; // Ensure we don't initialize again phoneApplicationInitialized = true; }
启动应用后,它将在初始化期间分配 URI 映射器。在启动任何页面之前,应用将调用 URI 映射器的MapUri 方法确定要启动的页面。URI 映射器返回的 URI 即应用所启动的页面。
启动页面时,通过使用页面的 NavigationContext 对象的 QueryString 属性,页面可以访问 URI(启动了该页面)中的所有参数。例如,以下代码将所有的 URI 参数和值都放置在 IDictionary 对象中。
// Get a dictionary of URI parameters and values. IDictionary<string, string> queryStrings = this.NavigationContext.QueryString;
检索文件
当您获得了深层链接 URI 的文件标记后,使用 Windows.Phone.Storage.SharedAccess 命名空间中的SharedStorageAccessManager 静态类访问该文件。 SharedStorageAccessManager 提供了以下方法。
方法 | 返回类型 | 说明 |
---|---|---|
System.String | 返回文件名(包括文件扩展名)。 | |
Windows.Storage.StorageFile | 将文件复制到特定的位置并返回副本。 |
启动文件
如前所述,您的应用也可以启动文件,以便另一个应用能够打开它。为此,请使用 Windows.System 命名空间的启动器对象的 LaunchFileAsync 方法。例如,下列代码从本地存储启动了一个假想 Contoso Bug 查询文件。
private async void LaunchFileButton_Click(object sender, RoutedEventArgs rea) { // Access isolated storage. StorageFolder local = Windows.Storage.ApplicationData.Current.LocalFolder; // Access the bug query file. StorageFile bqfile = await local.GetFileAsync("file1.bqy"); // Launch the bug query file. Windows.System.Launcher.LaunchFileAsync(bqfile); }
URI 关联允许应用在另一个应用启动了特殊的 URI 时自动启动。URI 的特别之处在于,它以应用注册的 URI 方案名为开头。URI 方案名是 URI 的一部分,它位于冒号 (‘:’) 之前。URI 方案包括 URI 方案名以及跟随在冒号后的所有 URI。例如,在下面的 URI 方案中,contoso为 URI 方案名。
contoso:ShowProducts?CategoryID=aea6ae1f-9894-404e-8bca-ec47ec5b9c6c
不论您是否愿意,冒号之后的其余 URI 始终将公开以允许使用 URI 关联。您的应用启动后,它可以检查 URI 并根据 URI 的内容呈现不同的行为。在本示例中,接收应用用于显示特定类别中所有的产品。
提示: |
---|
如果您只感兴趣启动您自己的应用,则考虑使用来自 Windows.Phone.Management.Deployment 命名空间的 API。您可以使用该 API 来检查您已经发布的其他应用,如果它们已经安装,则启动它们。有关更多信息,请参见 Windows Phone 的启动、恢复和多任务处理。 |
注册 URI 关联
要处理 URI 关联,请在应用清单文件 WMAppManifest.xml 中指定相应的 URI 方案名。您的 URI 方案名可以是字母和数字的任意组合;但是任何由内置应用保留的方案名都将被忽略。有关更多信息,请参见Windows Phone 8 的保留文件和 URI 关联。
要注册 URI 关联,您必须使用 XML(文本)编辑器编辑 WMAppManifest.xml。在“解决方案资源管理器”中,右键单击 WMAppManifest.xml 文件,然后单击“打开方式”。在“打开方式”窗口中,选择“XML(文本)编辑器”,然后单击“确定”。
在应用清单文件的Extensions元素中,URI 关联是使用Protocol元素所指定的。请注意,Extensions元素必须紧跟在Tokens元素之后。每个应用中最多可以注册 10 个 URI 关联。下面的示例演示了能够处理contosoURI 方案名的假想应用的 URI 关联。
<Extensions> <Protocol Name="contoso" NavUriFragment="encodedLaunchUri=%s" TaskID="_default" /> </Extensions>
Protocol元素由以下特性组成。
特性 | 说明 |
---|---|
名称 | 自定义的 URI 方案的前缀。包含数字、小写字母、句点 (‘.’) 或连字符 (‘-’) 且长度介于 3 和 39 个字符的字符串。它不包含冒号 (‘:’)或任何紧跟其后的 URI 中的内容。 |
NavUriFragment | 必须始终等于encodedLaunchUri=%s |
TaskID | 必须始终等于_default |
侦听 URI
当您的应用自动启动以处理某个 URI 关联时,深层链接 URI 用于将用户带到您的应用。在 URI 中,Protocol字符串指定 URI 的源为 URI 关联。名为encodedLaunchuri的 URI 参数等于从源应用发送的整个 URI 方案的 URI 编码版本。例如,以下代码演示了当假想应用作为contosoURI 关联的结果被启动后,该应用将显示的启动 URI。
/Protocol?encodedLaunchUri=contoso%3AShowProducts%3FCategoryID%3Daea6ae1f-9894-404e-8bca-ec47ec5b9c6c
重要说明: |
---|
启动应用后,URI 方案中所有保留的字符都将自动进行百分比编码。例如,一个应用启动 URI“contoso:NewProducts”后,会导致另一个应用接收深层链接 URI“/Protocol?encodedLaunchUri=contoso%3ANewProducts”。 |
应用启动时,将传入的深层链接 URI 映射到能够处理 URI 关联的应用页面。以下示例演示了使用 ShowProducts.xaml 页面映射 Contoso“显示产品”请求的自定义 URI 映射器。如果没有使用 Contoso URI 方案名,完整的 URI 将被发送到 MainPage.xaml 页面。
using System; using System.Windows.Navigation; namespace sdkAutoLaunch { class AssociationUriMapper : UriMapperBase { private string tempUri; public override Uri MapUri(Uri uri) { tempUri = System.Net.HttpUtility.UrlDecode(uri.ToString()); // URI association launch for contoso. if (tempUri.Contains("contoso:ShowProducts?CategoryID=")) { // Get the category ID (after "CategoryID="). int categoryIdIndex = tempUri.IndexOf("CategoryID=") + 11; string categoryId = tempUri.Substring(categoryIdIndex); // Map the show products request to ShowProducts.xaml return new Uri("/ShowProducts.xaml?CategoryID=" + categoryId, UriKind.Relative); } // Otherwise perform normal launch. return uri; } } }
在此类情况下,若要在您的应用中使用 URI 映射器类,请将其分配到该应用在 App.xaml.cs 文件中所对应的框架。在InitializePhoneApplication方法中,在RootFrame.Navigated已分配后,紧接着将RootFrame.UriMapper属性分配给您的 URI 映射器类。在下列示例中,AssociationUriMapper类被分配给框架的UriMapper属性。
private void InitializePhoneApplication() { if (phoneApplicationInitialized) return; // Create the frame but don't set it as RootVisual yet; this allows the splash // screen to remain active until the application is ready to render. RootFrame = new PhoneApplicationFrame(); RootFrame.Navigated += CompleteInitializePhoneApplication; // Assign the URI-mapper class to the application frame. RootFrame.UriMapper = new AssociationUriMapper(); // Handle navigation failures RootFrame.NavigationFailed += RootFrame_NavigationFailed; // Ensure we don't initialize again phoneApplicationInitialized = true; }
启动应用后,它将在初始化期间分配 URI 映射器。在启动任何页面之前,应用将调用 URI 映射器的MapUri 方法确定要启动的页面。URI 映射器返回的 URI 即应用所启动的页面。
启动页面时,通过使用页面的 NavigationContext 对象的 QueryString 属性,页面可以访问 URI(启动了该页面)中的所有参数。例如,以下代码将所有的 URI 参数和值都放置在 IDictionary 对象中。
// Get a dictionary of URI parameters and values. IDictionary<string, string> queryStrings = this.NavigationContext.QueryString;
启动 URI
通过使用关联启动 API,您的应用可以通过启动自定义的 URI 自动启动另一个应用。为此,请使用 Windows.System 命名空间的启动器对象的 Launcher..::.LaunchUriAsync(Uri) 方法。例如,以下代码启动了一个假想 Contoso 应用以显示新产品。
private async void LaunchContosoNewProductsButton_Click(object sender, RoutedEventArgs rea) { // Launch URI. Windows.System.Launcher.LaunchUriAsync(new System.Uri("contoso:NewProducts")); }
当您的 URI 被传递到附带 URI 关联的接收应用,已启动 URI 中所有的保留字符都将自动进行百分比编码。例如,一个应用启动 URI“contoso:NewProducts”后,会导致另一个应用接收深层链接 URI“/Protocol?encodedLaunchUri=contoso%3ANewProducts”。