使用扩展 SDK 编程
为了了解Windows 10如何使通用 Windows 平台 (UWP) 应用以最有效地面向不同类别的设备,本主题介绍了以下概念。
- 设备系列
- 扩展 SDK
- API 协定
我们还介绍如何在编程中使用它们。
视频 - UWP 和设备系列简介
设备系列和应用的目标设备系列
设备系列可标识在一个设备类所需的 API、系统特性和行为。
设备系列是操作系统 (操作系统) 的基础。 例如,电脑和平板电脑运行基于桌面设备系列的 OS 桌面版。 IoT 设备运行基于 IoT 设备系列的 OS 的 IoT 版本。
每个子设备系列将自己的 API 添加到它从通用设备系列继承的 API。 子设备系列中生成的 API 联合保证存在于基于该设备系列的 OS 中,因此存在于运行该 OS 的每个设备上。
决定应用) 目标 的设备系列 (或系列由你自己决定。 并且该决定将从以下重要方面影响你的应用。 它确定
- 应用提供给从 Microsoft Store (安装的设备系列,以及设计应用的 UI) 时需要考虑的外形规格,以及
- 可依赖在运行应用的设备上存在的特定 API 集 (主机设备) 。
通过 依赖于存在,这意味着你可以调用这些 API,而无需先测试以查看它们是否存在于主机设备上。 目标设备系列为不同的设备系列) 提供不同的保证 (不同的保证。
配置目标设备系列
在应用包清单源文件 (Package.appxmanifest
文件 ) ,TargetDeviceFamily 元素具有 Name 属性。 该属性的值是应用面向的设备系列的名称。 以下值有效。
- Windows.Desktop
- Windows.Holographic
- Windows.IoT
- Windows.Mobile
- Windows.Team
- Windows.Universal
- Windows.Xbox
默认情况下,UWP 应用面向通用设备系列 (即 Microsoft Visual Studio 为 TargetDeviceFamily) 指定Windows.Universal
。 这意味着你的应用可以安装在所有Windows 10设备上,并且你可以依赖于主机设备上存在的一组大型核心 API。 此类应用需要具有高度自适应的 UI 和全面的输入功能,因为它可以在各种设备上运行。 请参阅本主题后面的 在不同屏幕大小上预览 UI 。
如果要限制从 Microsoft Store 提供应用安装的设备系列,可以选择面向其他设备系列,例如桌面设备系列 () Windows.Desktop
或 IoT 设备系列 (Windows.IoT
) 。 当然,可以托管应用的设备会更少,但你将能够依赖于这些设备上存在的更大一组 API, (这些设备系列中将设置的 API,以及目标设备系列) 中的设置。 此类应用通常只需要适度自适应;它可以在 UI 和输入功能方面具有一定的专用性,因为它只能在特定类型的设备上运行。
提示
但你也可以拥有两全其美的。 你可以将应用配置为在所有Windows 10设备上运行,并且当你发现你在一个设备上运行时,还可以访问某些设备系列的特殊功能。 这种两全其美的方案确实需要一些额外的工作,我们将在本主题的后面部分介绍具体内容。
配置目标设备系列版本
API 会随着时间推移添加到 Windows,因此选择设备系列的另一个维度是决定 () 目标版本。 Visual Studio 中的某些项目类型具有属性页,可在其中配置目标平台版本。 但对于所有项目类型,可以直接在项目文件中配置目标平台版本。
以下示例显示了项目文件中的相关属性。
<!-- MyProject.Xxxproj -->
<PropertyGroup Label="Globals">
...
<WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformMinVersion>10.0.17134.0</WindowsTargetPlatformMinVersion>
...
</PropertyGroup>
在生成时,这些值 (与) Package.appxmanifest
TargetDeviceFamily@Name值一起复制到AppxManifest.xml
项目的输出文件夹中生成的文件中。 下面是一个示例。
<!-- AppxManifest.xml -->
<Dependencies>
<TargetDeviceFamily Name="Windows.Universal"
MaxVersionTested="10.0.19041.0"
MinVersion="10.0.17134.0" />
...
</Dependencies>
MaxVersionTested 指定应用针对的设备系列的最高版本,你已针对它进行测试。 MinVersion 指定应用面向的设备系列的最低版本。 有关更多详细信息,请参阅 TargetDeviceFamily。
重要
应通过 Visual Studio 项目的属性页或项目文件中 的 WindowsTargetPlatformVersion 和 WindowsTargetPlatformMinVersion 的值来配置这些版本号。 请勿编辑 AppxManifest.xml
,因为生成会覆盖该文件。 并且不要在应用包清单源文件中编辑 TargetDeviceFamily 元素的 MinVersion 和 MaxVersionTested 属性, (Package.appxmanifest
文件) ,因为这些值将被忽略。
扩展 SDK 及其引用方式
如果在 Visual Studio 项目中将目标从通用设备系列更改为其他某个设备系列,则需要添加对与该设备系列对应的扩展 SDK 的引用。 这使该设备系列中的 API 可供项目使用。
例如,如果以 IoT 设备系列为目标,则 (解决方案资源管理器) 选中的项目节点解决方案资源管理器) 单击“项目>添加引用...”。>通用 Windows>扩展,并为 UWP 选择适当版本的 Windows IoT 扩展。 例如,如果要调用的最新 IoT API 在版本 10.0.17134.0 中引入,请选择该版本。
这就是该引用在项目文件中的外观。
<ItemGroup>
<SDKReference Include="WindowsIoT, Version=10.0.17134.0" />
</ItemGroup>
名称和版本号需与 SDK 的安装位置所在的文件夹匹配。 例如,上述信息与名为 的文件夹匹配
\Program Files (x86)\Windows Kits\10\Extension SDKs\WindowsIoT\10.0.17134.0
其他扩展 SDK 包括 适用于 UWP 的 Windows 桌面扩展、适用于 UWP的 Windows 移动扩展和 适用于 UWP 的 Windows 团队扩展。
如果将应用保留为面向通用设备系列,则仍可以添加对一个或多个扩展 SDK 的引用。 引用包含要调用的其他 API 的扩展 SDK。 请记住,你的目标是通用设备系列,因此这些是唯一可以 依赖 存在的 API。 对于引用的扩展 SDK () 中的 API,在调用它们之前,需要测试它们在运行时是否存在,然后再调用它们 (本主题后面的 编写代码 部分中的更多详细信息) 。 当然,不需要对通用设备系列中的 API 执行该测试。 这是我们在上一部分提到的两全其美方案。
通过使用扩展 SDK,可以面向特定设备系列的唯一 API,从而访问其专用功能。 无论是否面向相应的设备系列,都可以执行此操作。
API 协定,以及如何查找它们
设备系列中的 API 被细分为称为 API 协定的组。 当设备系列的新版本发布时,该新版本实质上只是表示属于该设备系列的所有 API 协定的新版本的集合。
例如,在通用设备系列的版本 10.0.0.17134.0 随附时,名为 的 Windows.Foundation.UniversalApiContract
API 协定在版本 6.0 中。 但是,当同一设备系列的 10.0.19041.0 版本随附时,该合约在版本 10.0 中。
查找 WinRT API 的 API 协定
让我们看看如何查找任何给定Windows 运行时 API 的 API 协定名称和版本号。 在本主题后面的 编写代码 部分中,你将了解使用该信息的原因和方式。
作为第一个示例,我们将采用 StorageFolder.TryGetChangeTracker 方法。 在该主题的“Windows 10要求”部分中,我们可以看到 StorageFolder.TryGetChangeTracker 是在 6.0 版 中首次引入的Windows.Foundation.UniversalApiContract
。
接下来,让我们看一下 StorageFolder.TryGetItemAsync 方法的主题。 该主题中没有Windows 10要求部分。 请改为查看 StorageFolder 类本身的主题。 Windows 10要求部分有答案。 由于 StorageFolder.TryGetItemAsync 主题没有说明任何不同,因此我们可以得出结论,它与其父类共享其要求。 因此 ,StorageFolder.TryGetItemAsync 是随 版本 1.0 一起引入的 Windows.Foundation.UniversalApiContract
。
如何选择要面向的设备系列
下面是一些注意事项,可帮助你确定要面向的设备系列。 有关更多详细信息,请参阅 TargetDeviceFamily。
最大化应用覆盖
若要使用应用达到设备种类的最大范围,并使其在尽可能多的设备上运行,你的应用应面向通用设备系列。 具体而言,正如我们所看到的,你将面向通用设备系列的一系列版本。
将应用限制为一种设备
你可能不希望应用在各种设备外形规格上运行;也许它专用于台式电脑或 Xbox 主机。 在这种情况下,可以选择以子设备系列之一为目标。
将应用限制为所有可能设备的子集
可以改为面向两个 (或更多) 子设备系列,而不是面向通用设备系列或其中一个子设备系列。 面向桌面和移动设备可能对你的应用有意义。 或桌面和团队。 或桌面、移动和团队等。
排除对设备系列特定版本的支持
在极少数情况下,你可能希望你的应用在任意位置运行, 但 特定设备系列的特定版本除外。 例如,假设你的应用面向通用设备系列的版本 10.0.x.0。 当将来的操作系统版本发生更改(例如 10.0.x.2)时,你可以通过将你的应用定位到 10.0.x.0 的通用版本和 10.0.x.2 的 Xbox 版本来指定你的应用在除 Xbox 版本 10.0.x.1 之外的所有位置运行。 然后,你的应用将不适用于 Xbox 10.0.x.1(含该版本号)以及早期版本内的设备系列版本集。
编写代码
大部分代码都是通用的,因为它在每个设备上都以相同的方式运行。 但对于针对特定设备系列定制的代码,可以选择使用自适应代码。 让我们考虑这些不同的情况。
调用由目标设备系列实现的 API
每当你想要在 UWP 应用中调用 API 时,你都会想知道该 API 是否由你的应用所面向的设备系列实现。 Visual Studio IntelliSense 显示通用设备系列中的 API 以及 可用于任何扩展 SDK (引用的) 的 API。
Windows 运行时 API 参考文档介绍了 API 所属的设备系列。 如果查找Windows 运行时 API 的 API 参考主题并查找Windows 10要求部分,则会看到实现的设备系列是什么,以及 API 首次出现在该设备系列的哪个版本。 如果没有Windows 10要求部分,请查看成员的拥有类,并在该部分中查看Windows 10要求部分中的信息。 该信息也适用于该成员。
调用未由目标设备系列实现的 API
在某些情况下,你想要在引用的扩展 SDK 中调用 API,但该 API 不属于目标设备系列。
例如,你可能面向通用设备系列,但每当应用在桌面设备上运行时,你想要调用一个桌面 API。
或者,你的应用可能支持设备系列的早期版本,但你希望调用的 API 仅在同一设备系列的最新版本中可用。
在这种情况下,可以选择编写自适应代码,以便安全地调用这些 API。 下一部分介绍如何操作。
使用 ApiInformation 编写自适应代码
使用自适应代码有条件地调用 API 涉及两个步骤。 第一步是使 API 可用于项目。 为此,请添加对扩展 SDK 的引用,该 SDK 表示拥有 API 的设备系列。
第二步是在代码中的某个条件中使用 ApiInformation 类,以测试是否存在要调用的 API。 无论何时何地运行应用,都会评估此条件。 但它仅在存在 API 并因此可供调用的设备上计算 true
结果为 。
如果只想调用少量 API,则可以使用 ApiInformation.IsTypePresent 方法,如下所示。
// Cache the value, instead of querying it multiple times.
bool isHardwareButtonsAPIPresent =
Windows.Foundation.Metadata.ApiInformation.IsTypePresent("Windows.Phone.UI.Input.HardwareButtons");
if (isHardwareButtonsAPIPresent)
{
Windows.Phone.UI.Input.HardwareButtons.CameraPressed += HardwareButtons_CameraPressed;
}
在这种情况下,可以确信 HardwareButtons 类的存在意味着 存在 CameraPressed 事件,因为类和成员具有相同的要求信息。 但随着时间的推移,新成员将添加到已引入的类,这些成员稍后将在版本号 中引入 。 在此情况下,你可以使用 IsEventPresent、IsMethodPresent、IsPropertyPresent 和类似的方法来测试是否存在各个成员,而无需使用 IsTypePresent。 下面是一个示例。
bool isHardwareButtons_CameraPressedAPIPresent =
Windows.Foundation.Metadata.ApiInformation.IsEventPresent
("Windows.Phone.UI.Input.HardwareButtons", "CameraPressed");
我们知道,设备系列中的 API 集进一步细分为称为 API 协定的细分。 你可以使用 ApiInformation.IsApiContractPresent 方法来测试是否存在 API 合约。 这是一种执行单个条件的有效方法,以便了解是否存在大量 API,这些 API 都属于同一版本的 API 协定。
有关如何确定首次引入 API (相关) 的 API 协定的信息,请参阅本主题前面的 查找 WinRT API 的 API 协定 部分。
获得该信息后,即可将其插入自适应代码。 例如,如果 API 协定的名称为 Windows.Devices.Scanners.ScannerDeviceContract
,并且其主版本号和次要版本号分别为 1 和 0,则条件将如以下示例所示。
bool isWindows_Devices_Scanners_ScannerDeviceContract_1_0Present =
Windows.Foundation.Metadata.ApiInformation.IsApiContractPresent
("Windows.Devices.Scanners.ScannerDeviceContract", 1, 0);
在不同的屏幕大小上预览 UI
建议最大化应用覆盖范围。 但是,即使你只针对一种设备外形规格,你的应用最终仍可能会显示不同的屏幕大小。
当你准备好查看应用在特定大小的屏幕上的外观和布局时,请使用 Visual Studio 中的设备预览工具栏在小型或中型移动设备、电脑或大型电视屏幕上预览 UI。 这样,如果你已使用 XAML 的自适应布局功能 () 查看 具有视觉状态和状态触发器的自适应布局 ,那么也可以对其进行测试。
无需事先决定将支持的每种设备类型。 可以随时向项目添加其他设备大小。