Программирование с использованием пакетов SDK расширений
Чтобы понять, как Windows 10 позволяет приложению универсальная платформа Windows (UWP) наиболее эффективно ориентироваться на различные классы устройств, в этом разделе объясняется следующее.
- Семейство устройств
- Пакет SDK для расширения
- API на основе контракта
Мы также покажем, как использовать их в программировании.
Видео. Общие сведения о UWP и семействах устройств
Семейства устройств и целевое семейство устройств вашего приложения
Семейство устройств определяет API-интерфейсы, характеристики системы и поведения, ожидаемые на устройствах определенного класса.
Семейство устройств является основой операционной системы (ОС). Например, на компьютерах и планшетах работает настольный выпуск ОС, основанный на семействе настольных устройств. На устройствах Интернета вещей используется выпуск IoT ОС, основанный на семействе устройств Интернета вещей.
Каждое дочернее семейство устройств добавляет собственные API-интерфейсы к ИНТЕРФЕЙСАм API, которые наследуются от семейства универсальных устройств. Итоговое объединение API-интерфейсов в дочернем семействе устройств гарантированно будет присутствовать в ОС, основанной на этом семействе устройств, и, следовательно, на каждом устройстве под управлением этой ОС.
Решение о том, какое семейство устройств (или семьи) будет предназначено для вашего приложения, будет принято вами. Этот выбор влияет на важные аспекты вашего приложения. Он определяет
- семейства устройств, к которым предлагается ваше приложение для установки из Microsoft Store (и, следовательно, форм-факторы, которые необходимо учитывать при разработке пользовательского интерфейса приложения); и
- определенный набор API, который можно использовать на устройстве, на котором выполняется приложение (хост-устройство).
Мы подразумеваем, что вы можете вызывать эти API без предварительного тестирования, чтобы узнать, присутствуют ли они на хост-устройстве. Целевое семейство устройств предоставляет такую гарантию (разные гарантии для разных семейств устройств).
Настройка семейства целевых устройств
В исходном файле манифеста Package.appxmanifest
пакета приложения элемент TargetDeviceFamily имеет атрибут Name . Значение этого атрибута — это имя семейства устройств, на которое нацелено ваше приложение. Допустимы следующие значения.
- Windows.Desktop
- Windows.Holographic
- Windows.IoT
- Windows.Mobile
- Windows.Team
- Windows.Universal
- Windows.Xbox
По умолчанию приложение UWP предназначено для семейства универсальных устройств (то есть Microsoft Visual Studio указывает Windows.Universal
для TargetDeviceFamily). Это означает, что ваше приложение можно установить на всех Windows 10 устройствах и что вы можете полагаться на большой набор основных API, присутствующих на главном устройстве. Такое приложение должно иметь адаптивный пользовательский интерфейс и комплексные возможности ввода, так как оно может работать на самых разных устройствах. См . раздел Предварительный просмотр пользовательского интерфейса на экранах разных размеров далее в этом разделе.
Если вы хотите ограничить семейства устройств, которыми предлагается ваше приложение для установки из Microsoft Store, можно выбрать другое семейство устройств, например семейство настольных устройств (Windows.Desktop
) или семейство устройств Интернета вещей (Windows.IoT
). Конечно, будет меньше устройств, на которых может размещаться ваше приложение, но вы сможете полагаться на более широкий набор API- интерфейсов, присутствующих на этих устройствах (это будет набор в семействе универсальных устройств, а также набор в семействе целевых устройств). Такое приложение обычно должно быть лишь умеренно адаптивным; он может быть несколько специализирован в пользовательском интерфейсе и возможностях ввода, так как он может работать только на определенном типе устройства.
Совет
Но вы также можете иметь лучшее из обоих миров. Вы можете настроить приложение для запуска на всех Windows 10 устройствах, а также получить доступ к специализированным возможностям определенных семейств устройств, если обнаружите, что работаете на одном из них. Этот лучший сценарий для обоих миров требует немного дополнительной работы, и мы рассмотрим его особенности далее в этом разделе.
Настройка версии семейства целевых устройств
API-интерфейсы добавляются в Windows со временем, поэтому другим аспектом выбора семейства устройств является выбор целевой версии (или версий). Некоторые типы проектов в Visual Studio имеют страницу свойств, на которой можно настроить версии целевой платформы. Но для всех типов проектов можно настроить версии целевой платформы прямо в файле проекта.
Ниже приведен пример соответствующих свойств в файле проекта.
<!-- MyProject.Xxxproj -->
<PropertyGroup Label="Globals">
...
<WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformMinVersion>10.0.17134.0</WindowsTargetPlatformMinVersion>
...
</PropertyGroup>
Во время сборки эти значения (вместе со значением TargetDeviceFamily@Name из Package.appxmanifest
) копируются в 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
, так как сборка перезаписывает этот файл. Не изменяйте атрибуты MinVersion и MaxVersionTested элемента TargetDeviceFamily в исходном файле манифеста Package.appxmanifest
пакета приложения (файл), так как эти значения игнорируются.
Пакеты SDK для расширений и ссылки на них
Если в проекте Visual Studio вы изменяете целевой объект с универсального семейства устройств на другое семейство устройств, необходимо добавить ссылку на пакет SDK расширения, соответствующий этому семейству устройств. Это делает API в этом семействе устройств доступными для проекта.
Если, например, вы нацелены на семейство устройств Интернета вещей, то (с узлом проекта, выбранным в Обозреватель решений) щелкните Проект>Добавить ссылку...>Универсальная система Windows>Расширения и выберите соответствующую версию расширений Интернета вещей Windows для UWP. Например, если новейший 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 расширений включают расширения windows desktop для UWP, расширения Windows Mobile для UWP и windows team extensions для UWP.
Если ваше приложение предназначено для семейства универсальных устройств, вы по-прежнему можете добавить ссылку на один или несколько пакетов SDK расширений. Укажите, какие пакеты SDK расширений содержат дополнительные API, которые вы хотите вызвать. Помните, что вы используете семейство универсальных устройств, поэтому это единственные API, на которые вы можете полагаться . Для API в пакетах SDK для расширений, на которые вы ссылаетесь, необходимо проверить, присутствуют ли они на хост-устройстве во время выполнения, прежде чем вызывать их (дополнительные сведения см. в разделе Написание кода далее в этом разделе). Конечно, вам не нужно выполнять этот тест для API в семействе универсальных устройств. Это лучший сценарий для обоих миров, который мы упоминали в предыдущем разделе.
С помощью пакета SDK расширения можно ориентироваться на уникальные API определенного семейства устройств и, таким образом, получить доступ к их специализированным возможностям. Это можно сделать независимо от того, нацелились ли вы на соответствующее семейство устройств или нет.
Контракты API и их поиск
API в семействе устройств подразделяются на группы, называемые контрактами API. При выпуске новой версии семейства устройств эта новая версия по сути представляет собой коллекцию новых версий всех контрактов API, принадлежащих к данному семейству устройств.
Например, контракт API с именем Windows.Foundation.UniversalApiContract
был в версии 6.0, когда он поставлялся с версией 10.0.17134.0 семейства универсальных устройств. Но тот же контракт был в версии 10.0, когда он поставлялся с версией 10.0.19041.0 того же семейства устройств.
Поиск контракта API для API WinRT
Давайте посмотрим, как можно найти имя контракта API и номер версии для любого среда выполнения Windows 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. В этом случае можно выбрать одно из семейств дочерних устройств.
Ограничьте приложение подмножеством всех возможных устройств
Вместо того, чтобы ориентироваться на семейство универсальных устройств или одно из дочерних семейств устройств, можно выбрать два (или более) семейства дочерних устройств. Для вашего приложения может быть целесообразно нацеливание на настольные компьютеры и мобильные устройства. Или рабочий стол и команда. Или Desktop, Mobile, Team и т. д.
Исключение поддержки определенной версии семейства устройств
В редких случаях может потребоваться, чтобы приложение выполнялось везде, за исключением устройств с определенной версией определенного семейства устройств. Например, предположим, что ваше приложение предназначено для версии 10.0.x.0 семейства универсальных устройств. Когда в будущем версия операционной системы изменится, скажем, до 10.0.x.2, вы можете указать, что приложение работает везде, кроме версии 10.0.x.1 Xbox, нацелив приложение на 10.0.x.0 универсального и 10.0.x.2 xbox. После этого ваше приложение окажется недоступным для набора версий семейства устройств в рамках Xbox 10.0.x.1 (включительно) и более ранних версий.
Написание кода
Большая часть кода будет универсальной в том смысле, что он будет выполняться одинаково на каждом устройстве. Но для кода, предназначенного для определенного семейства устройств, вы можете использовать адаптивный код. Рассмотрим эти различные случаи.
Вызов API, реализованный целевым семейством устройств
Всякий раз, когда вы хотите вызвать API в приложении UWP, необходимо знать, реализован ли API семейством устройств, на которое нацелено ваше приложение. Visual Studio IntelliSense показывает API в семействе универсальных устройств , а также API, доступные для любых пакетов SDK расширений, на которые вы ссылаетесь.
В справочной документации по API среда выполнения Windows показано, к какому семейству устройств относится API. Если вы найдите раздел справочника по API среда выполнения Windows API и найдите раздел Windows 10 требования, вы увидите, что такое реализующее семейство устройств и какая версия этого семейства устройств впервые отображается. Если раздел требований Windows 10 отсутствует, просмотрите класс владельцев члена и просмотрите сведения в разделе Windows 10 requirements там. Эта информация будет применяться и к участнику.
Вызов API, который не реализован целевым семейством устройств
В таких случаях требуется вызвать API в пакете SDK расширения, на который вы ссылаетесь, но этот API не входит в семейство устройств, для которого вы ориентируетесь.
Например, вы можете использовать семейство универсальных устройств, но есть API для настольных компьютеров, который вы хотите вызывать при каждом запуске приложения на настольном устройстве.
Или ваше приложение может поддерживать ранние версии семейства устройств, но есть API, который требуется вызвать, который доступен только в последних версиях того же семейства устройств.
В таких случаях можно написать адаптивный код, чтобы можно было безопасно вызывать эти API. В следующем разделе показано, как это сделать.
Написание адаптивного кода с помощью ApiInformation
Использование адаптивного кода для условного вызова API выполняется двумя шагами. Первый шаг — сделать API доступным для вашего проекта. Для этого добавьте ссылку на пакет SDK расширения, представляющий семейство устройств, которым принадлежит API.
Второй шаг — использование класса ApiInformation в условии в коде для проверки наличия API, который требуется вызвать. Это условие оценивается везде и при каждом запуске приложения. Но он оценивается true
только на устройствах, где api присутствует и, следовательно, доступен для вызова.
Если вы хотите вызвать только небольшое количество 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 , так как класс и член имеют одинаковые сведения о требованиях. Но со временем новые члены будут добавлены в уже представленные классы, и эти члены будут позже представлены в номерах версий. В этом случае вместо использования метода IsTypePresent вы можете проверить наличие отдельных членов с помощью IsEventPresent, IsMethodPresent, IsPropertyPresent и похожих методов. Пример приведен ниже.
bool isHardwareButtons_CameraPressedAPIPresent =
Windows.Foundation.Metadata.ApiInformation.IsEventPresent
("Windows.Phone.UI.Input.HardwareButtons", "CameraPressed");
Как мы знаем, набор API в семействе устройств далее разбивается на подразделы, известные как контракты API. Вы можете использовать метод ApiInformation.IsApiContractPresent, чтобы проверить наличие контракта API. Это эффективный способ выполнения одного условия, чтобы знать о наличии или ином количестве API, которые принадлежат одной версии контракта API.
Сведения об определении контракта API, который впервые представил интересующие API, см. в разделе Поиск контракта API для API WinRT ранее в этом разделе.
Получив эти сведения, вы можете подключить их к адаптивный код. Например, если имя контракта 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);
Предварительный просмотр пользовательского интерфейса на экранах разных размеров
Рекомендуется максимизировать охват приложения. Но даже если вы нацелены только на один тип форм-фактора устройства, вероятно, будут разные размеры экрана, на которых может отображаться ваше приложение.
Когда вы будете готовы увидеть, как ваше приложение выглядит и размещается на экране определенного размера, используйте панель инструментов предварительного просмотра устройства в Visual Studio, чтобы просмотреть пользовательский интерфейс на небольших или средних мобильных устройствах, на компьютере или на большом экране телевизора. Таким образом, если вы использовали функции адаптивного макета XAML (см. раздел Адаптивные макеты с визуальными состояниями и триггерами состояния), вы также можете проверить это.
Вам не нужно заранее принимать решение о каждом типе устройств, которые вы будете поддерживать. В проект можно в любой момент добавить дополнительный размер устройства.