UWP: Extensions and ApiInformation

Universal Windows Platform allows to build universal applications for all devices which run Windows 10. I have already published several posts about new controls which allow to create universal interfaces for different screen sizes and resolutions. But what about device-specific features? For example: Raspberry Pi has set of pins which are not available for phone and tablets; you can use desktops and laptops in order to print something directly from your application but this functionality is not available for phones; lots of phones support vibration what is very uncommon for laptops etc. That’s why all contracts with device-specific functionality were moved to special libraries called extensions.

You can include existing extensions to your project using Add Reference dialog and open Extensions tabs. Today you can find three most important extensions there like Mobile Extension, Desktop Extension and IoT Extension.

 

Of course you might see more extensions soon. For example, Microsoft might publish some extensions for Xbox and Hololens but you will be able to create your own for own Windows 10 devices.

If you want to see all contracts which were included to the extension, you can open the manifest file for the selected extension and check all contracts there. For example, you can find the IoT manifest using the following folder C:\Program Files (x86)\Windows Kits\10\Extension SDKs\WindowsIoT\10.0.10069.0 and manifest looks like:

 <?xml version="1.0" encoding="utf-8"?>
<FileList TargetPlatform="UAP" TargetPlatformMinVersion="10.0.0.1" TargetPlatformVersion="10.0.10069.0" SDKType="Platform" DisplayName="Windows IoT Extension SDK" AppliesTo="WindowsAppContainer" MinVSVersion="14.0" ProductFamilyName="Windows.IoT" SupportsMultipleVersion="Error" TargetFramework=".NETCore, version=v4.5.3;" SupportPrefer32Bit="True" MoreInfo="https://www.microsoft.com/en-us/server-cloud/internet-of-things.aspx">
 <ContainedApiContracts>
 <ApiContract name="Windows.Devices.DevicesLowLevelContract" version="1.0.0.0"/>
 <ApiContract name="Windows.System.SystemManagementContract" version="1.0.0.0"/>
 </ContainedApiContracts>
</FileList>

So, right now there are two contracts only and you can find all classes there using Object Browser in the Visual Studio.

I already published how to use IoT extensions for Raspberry Pi 2. So, in this article I want to talk more about how to implement universal approach even if you add an extension.

The main idea of Universal Windows Platform is to give a way to create just one application and one binary for all devices. But what happens when we add an extension? Should we recompile our application for different platforms with this extension and without the extension?  The answer is No.

Extensions are designed in the way when you can continue to run your code on a platform which doesn’t support extensions which you have included to your project. But if you try to call methods and create objects based on classes from the extensions, these calls will generate runtime exception. 

That’s why you need to check in runtime if selected extension is available on the platform. Of course, you should not do it in exception handler. It’s better to adopt the interface of your application for the specific device rather than notify users about some unsupported feature when the application is running. So, developers need to have better tool to check availability of contract and Microsoft implemented all needed features in ApiInformation class.

ApiInformation is located in Windows.Foundation.Metadata namespace and contains several static methods like IsApiContractPresent, IsEventPresent, IsMethodPresent etc.

So, if you want to check, if GPIO is available, you can use the following code:

 if (ApiInformation.IsApiContractPresent("Windows.Devices.DevicesLowLevelContract", 1))
{
 //doing something with GPIO
}

Pay special attention that IsApiContractPresent requires two parameters. The second one is major version (you can use minor version as well – third parameter). This parameter is needed because Microsoft can update some of contracts and you can target specific version(s).

The code above doesn’t mean that you need to create hundreds of if blocks if you include one or several contracts. It’s better to create a custom trigger based on this information and implement several visual states.