Programação com SDKs de extensão
Para entender como Windows 10 permite que seu aplicativo Plataforma Universal do Windows (UWP) direcione com mais eficiência diferentes classes de dispositivos, este tópico explica os conceitos a seguir.
- Família de dispositivos
- SDK de extensão
- Contrato da API
Também mostramos como usá-los em sua programação.
Vídeo – Introdução à UWP e às famílias de dispositivos
Famílias de dispositivos e a família de dispositivos de destino do aplicativo
Uma família de dispositivos identifica as APIs, as características do sistema e os comportamentos esperados em uma classe de dispositivos.
Uma família de dispositivos é a base de um sistema operacional (SO). Por exemplo, computadores e tablets executam uma edição desktop do sistema operacional e isso se baseia na família de dispositivos desktop. Os dispositivos IoT executam uma edição IoT do sistema operacional, que se baseia na família de dispositivos IoT.
Cada família de dispositivos filho adiciona suas próprias APIs às APIs herdadas da família de dispositivos Universal. A união resultante de APIs em uma família de dispositivos filho tem a garantia de estar presente em um sistema operacional baseado nessa família de dispositivos e, portanto, em todos os dispositivos que executam esse sistema operacional.
A decisão sobre qual família de dispositivos (ou famílias) seu aplicativo será direcionado é sua. E essa decisão afeta seu aplicativo nesses aspectos importantes. Ele determina
- as famílias de dispositivos aos quais seu aplicativo é oferecido para instalação da Microsoft Store (e, consequentemente, os fatores forma que você precisa considerar ao projetar a interface do usuário do aplicativo) e
- o conjunto específico de APIs que você pode confiar em estar presente em um dispositivo que executa seu aplicativo (o dispositivo host).
Dependendo de estar presente, queremos dizer que você pode chamar essas APIs sem primeiro precisar testar para ver se elas estão presentes no dispositivo host. A família de dispositivos direcionada fornece essa garantia (garantias diferentes para diferentes famílias de dispositivos).
Configurar sua família de dispositivos de destino
No arquivo de origem do manifesto do pacote do aplicativo (o Package.appxmanifest
arquivo), o elemento TargetDeviceFamily tem um atributo Name . O valor desse atributo é o nome da família de dispositivos que seu aplicativo tem como destino. Os valores a seguir são válidos.
- Windows.Desktop
- Windows.Holographic
- Windows.IoT
- Windows.Mobile
- Windows.Team
- Windows.Universal
- Windows.Xbox
Por padrão, seu aplicativo UWP tem como destino a família de dispositivos Universal (ou seja, o Microsoft Visual Studio especifica Windows.Universal
para TargetDeviceFamily). E isso significa que seu aplicativo pode ser instalado em todos os dispositivos Windows 10 e que você pode contar com um grande conjunto principal de APIs presentes no dispositivo host. Um aplicativo como esse precisa ter uma interface do usuário altamente adaptável e recursos de entrada abrangentes, pois ele pode ser executado em uma ampla variedade de dispositivos. Consulte Visualizar sua interface do usuário em diferentes tamanhos de tela mais adiante neste tópico.
Se você quiser limitar as famílias de dispositivos aos quais seu aplicativo é oferecido para instalação da Microsoft Store, poderá optar por direcionar uma família de dispositivos diferente, por exemplo, a família de dispositivos desktop (Windows.Desktop
) ou a família de dispositivos IoT (Windows.IoT
). É claro que haverá menos dispositivos que podem hospedar seu aplicativo, mas você poderá contar com um conjunto maior de APIs presentes nesses dispositivos (que serão definidos na família de dispositivos Universal, além do conjunto na família de dispositivos de destino). Um aplicativo como esse normalmente precisa ser apenas moderadamente adaptável; ele pode ser um pouco especializado em seus recursos de interface do usuário e entrada, pois pode ser executado em apenas um tipo específico de dispositivo.
Dica
Mas você também pode ter o melhor dos dois mundos. Você pode configurar seu aplicativo para ser executado em todos os dispositivos Windows 10 e também acessar as funcionalidades especializadas de determinadas famílias de dispositivos quando descobrir que está executando em um. Esse cenário de melhores de ambos os mundos requer um pouco de trabalho extra, e entraremos em detalhes sobre isso mais adiante neste tópico.
Configurar a versão da família de dispositivos de destino
As APIs são adicionadas ao Windows ao longo do tempo, portanto, outra dimensão para escolher uma família de dispositivos é decidir qual versão (ou versões) deve ser direcionada. Alguns tipos de projeto no Visual Studio têm uma página de propriedades na qual você pode configurar suas versões de plataforma de destino. Porém, para todos os tipos de projeto, você pode configurar suas versões de plataforma de destino diretamente no arquivo de projeto.
Aqui está um exemplo mostrando as propriedades relevantes em um arquivo de projeto.
<!-- MyProject.Xxxproj -->
<PropertyGroup Label="Globals">
...
<WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformMinVersion>10.0.17134.0</WindowsTargetPlatformMinVersion>
...
</PropertyGroup>
No momento da compilação, esses valores (juntamente com o valor de TargetDeviceFamily@Name de Package.appxmanifest
) são copiados para o AppxManifest.xml
arquivo gerado na pasta de saída do projeto. Veja um exemplo.
<!-- AppxManifest.xml -->
<Dependencies>
<TargetDeviceFamily Name="Windows.Universal"
MaxVersionTested="10.0.19041.0"
MinVersion="10.0.17134.0" />
...
</Dependencies>
MaxVersionTested especifica a versão máxima da família de dispositivos que seu aplicativo está direcionando para a qual você o testou. E MinVersion especifica a versão mínima da família de dispositivos que seu aplicativo está direcionando. Para obter mais detalhes, consulte TargetDeviceFamily.
Importante
Você deve configurar esses números de versão por meio das páginas de propriedades do projeto do Visual Studio ou dos valores de WindowsTargetPlatformVersion e WindowsTargetPlatformMinVersion no arquivo de projeto. Não edite AppxManifest.xml
, porque o build substitui esse arquivo. E não edite os atributos MinVersion e MaxVersionTested do elemento TargetDeviceFamily no arquivo de origem do manifesto do pacote do aplicativo (o Package.appxmanifest
arquivo), pois esses valores são ignorados.
SDKs de extensão e como referenciá-los
Se, em seu projeto do Visual Studio, você alterar seu destino da família de dispositivos Universal para alguma outra família de dispositivos, precisará adicionar uma referência ao SDK de extensão correspondente a essa família de dispositivos. Isso torna as APIs nessa família de dispositivos disponíveis para seu projeto.
Se, por exemplo, você tiver como destino a família de dispositivos IoT, então (com o nó do projeto selecionado em Gerenciador de Soluções) clique em Projeto>Adicionar Referência...>Universal do Windows>Extensões e selecione a versão apropriada das Extensões do Windows IoT para a UWP. Por exemplo, se a API IoT mais recente que você deseja chamar tiver sido introduzida na versão 10.0.17134.0, selecione essa versão.
E é assim que essa referência ficaria no arquivo de projeto.
<ItemGroup>
<SDKReference Include="WindowsIoT, Version=10.0.17134.0" />
</ItemGroup>
O nome e o número da versão correspondem às pastas no local instalado do SDK. Por exemplo, as informações acima correspondem à pasta chamada
\Program Files (x86)\Windows Kits\10\Extension SDKs\WindowsIoT\10.0.17134.0
Outros SDKs de extensão incluem Extensões da Área de Trabalho do Windows para a UWP, Extensões do Windows Mobile para a UWP e Extensões de Equipe do Windows para a UWP.
Se você deixar seu aplicativo direcionado à família de dispositivos Universal, ainda poderá adicionar uma referência a um ou mais SDKs de extensão. Faça referência a qualquer SDK de extensão que contenha as APIs adicionais que você gostaria de chamar. Lembre-se de que você está direcionando a família de dispositivos Universal, portanto, essas são as únicas APIs que você pode confiar em estar presente. Para APIs nos SDKs de extensão referenciados, você precisará testar se elas estão presentes no dispositivo host em tempo de execução antes de chamá-las (mais detalhes na seção Escrevendo código mais adiante neste tópico). É claro que você não precisa executar esse teste para APIs na família de dispositivos Universal. Este é o melhor cenário de ambos os mundos que mencionamos na seção anterior.
Usando um SDK de extensão, você pode direcionar as APIs exclusivas de uma família específica de dispositivos e, assim, acessar seus recursos especializados. Você pode fazer isso se você direcionar a família de dispositivos correspondente ou não.
Contratos de API e como procurá-los
As APIs em uma família de dispositivos são subdivididas em grupos conhecidos como contratos de API. Quando uma nova versão de uma família de dispositivos é lançada, essa nova versão representa essencialmente apenas a coleção de novas versões de todos os contratos de API que pertencem a essa família de dispositivos.
Por exemplo, o contrato de API chamado Windows.Foundation.UniversalApiContract
estava na versão 6.0 quando foi fornecido com a versão 10.0.17134.0 da família de dispositivos Universal. Mas esse mesmo contrato estava na versão 10.0 quando foi fornecido com a versão 10.0.19041.0 dessa mesma família de dispositivos.
Pesquisar o contrato de API para uma API do WinRT
Vamos ver como você pode pesquisar o nome do contrato de API e o número de versão de qualquer API de Windows Runtime fornecida. Na seção Escrevendo código mais adiante neste tópico, você verá por que e como você pode usar essas informações.
Como nosso primeiro exemplo, usaremos o método StorageFolder.TryGetChangeTracker . Na seção Windows 10 requisitos desse tópico, podemos ver que StorageFolder.TryGetChangeTracker foi introduzido pela primeira vez com a versão 6.0 do Windows.Foundation.UniversalApiContract
.
Em seguida, vamos examinar o tópico do método StorageFolder.TryGetItemAsync . Não há nenhuma seção de requisitos de Windows 10 nesse tópico. Em vez disso, examine o tópico da própria classe StorageFolder . A seção requisitos de Windows 10 tem a resposta. Como o tópico StorageFolder.TryGetItemAsync não diz diferente, podemos concluir que ele compartilha seus requisitos com sua classe pai. Portanto, StorageFolder.TryGetItemAsync foi introduzido pela primeira vez com a versão 1.0 do Windows.Foundation.UniversalApiContract
.
Como escolher uma família de dispositivos para direcionar
Aqui estão algumas considerações para ajudá-lo a decidir qual família de dispositivos direcionar. Para obter mais detalhes, consulte TargetDeviceFamily.
Maximizar o alcance do aplicativo
Para atingir o intervalo máximo de tipos de dispositivos com seu aplicativo e, consequentemente, executá-lo no maior número possível de dispositivos, seu aplicativo deve ter como destino a família de dispositivos Universal. Especificamente, como vimos, você terá como alvo uma variedade de versões da família de dispositivos Universal.
Limitar seu aplicativo a um tipo de dispositivo
Talvez você não queira que seu aplicativo seja executado em uma ampla variedade de fatores de forma de dispositivo; talvez seja especializado para um computador desktop ou para um console Xbox. Nesse caso, você pode optar por direcionar uma das famílias de dispositivos filho.
Limitar seu aplicativo a um subconjunto de todos os dispositivos possíveis
Em vez de direcionar para a família de dispositivos Universal ou direcionar uma das famílias de dispositivos filho, você pode, em vez disso, direcionar duas (ou mais) famílias de dispositivos filho. Direcionar Área de Trabalho e Móvel pode fazer sentido para seu aplicativo. Ou Área de Trabalho e Equipe. Ou Área de Trabalho, Móvel e Equipe, e assim por diante.
Excluir suporte para uma versão específica de uma família de dispositivos
Em casos raros, talvez você queira que seu aplicativo seja executado em todos os lugares, exceto em dispositivos com uma versão específica de uma família de dispositivos específica. Por exemplo, digamos que seu aplicativo tenha como destino a versão 10.0.x.0 da família de dispositivos universais. Quando a versão do sistema operacional mudar no futuro, digamos para 10.0.x.2, nesse ponto, você poderá especificar que seu aplicativo seja executado em todos os lugares, exceto a versão 10.0.x.1 do Xbox, direcionando seu aplicativo para 10.0.x.0 da Universal e 10.0.x.2 do Xbox. Seu aplicativo estará disponível para o conjunto de versões da família de dispositivos no Xbox 10.0.x.1 (inclusive) e versões anteriores.
Como escrever código
Grande parte do seu código será universal no sentido de que ele será executado da mesma maneira em todos os dispositivos. Mas para código adaptado a uma família de dispositivos específica, você terá a opção de usar código adaptável. Vamos considerar esses casos diferentes.
Chamar uma API implementada pela família de dispositivos de destino
Sempre que quiser chamar uma API em um aplicativo UWP, você desejará saber se a API é implementada ou não pela família de dispositivos que seu aplicativo está direcionando. O Visual Studio IntelliSense mostra as APIs na família de dispositivos Universal mais as APIs disponíveis para qualquer SDK de extensão referenciada.
A documentação de referência da API Windows Runtime informa de qual família de dispositivos uma API faz parte. Se você pesquisar o tópico de referência da API para uma API de Windows Runtime e procurar a seção Windows 10 requisitos, verá qual é a família de dispositivos em implementação e em qual versão da família de dispositivos a API aparece pela primeira vez. Se não houver nenhuma seção Windows 10 requisitos, examine a classe proprietária do membro e veja as informações na seção requisitos de Windows 10. Essas informações também se aplicarão ao membro.
Chamar uma API que não é implementada pela família de dispositivos de destino
Haverá casos em que você deseja chamar uma API em um SDK de extensão que você referenciou, mas essa API não faz parte da família de dispositivos que você está direcionando.
Por exemplo, você pode estar direcionando a família de dispositivos Universal, mas há uma API da área de trabalho que você gostaria de chamar sempre que seu aplicativo estiver em execução em um dispositivo da área de trabalho.
Ou seu aplicativo pode dar suporte a versões iniciais de uma família de dispositivos, mas há uma API que você deseja chamar que está disponível apenas em versões muito recentes da mesma família de dispositivos.
Em casos como esses, você pode optar por escrever código adaptável para que possa chamar essas APIs com segurança. A próxima seção mostra como.
Escrever código adaptável usando ApiInformation
Há duas etapas envolvidas no uso de código adaptável para chamar uma API condicionalmente. A primeira etapa é disponibilizar a API para seu projeto. Para fazer isso, adicione uma referência ao SDK de extensão que representa a família de dispositivos que possui a API.
A segunda etapa é usar a classe ApiInformation em uma condição em seu código para testar a presença da API que você deseja chamar. Essa condição é avaliada em qualquer lugar e sempre que seu aplicativo é executado. Mas ele é avaliado true
apenas em dispositivos em que a API está presente e, portanto, disponível para chamar.
Se você quiser chamar apenas um pequeno número de APIs, poderá usar o método ApiInformation.IsTypePresent como este.
// 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;
}
Nesse caso, há confiança de que a presença da classe HardwareButtons implica a presença do evento CameraPressed , pois a classe e o membro têm as mesmas informações de requisitos. Mas, com o tempo, novos membros serão adicionados a classes já introduzidas, e esses membros terão introduzidos posteriormente em números de versão. Nesses casos, em vez de usar IsTypePresent, você pode testar a presença de membros individuais usando IsEventPresent, IsMethodPresent, IsPropertyPresent e métodos semelhantes. Veja um exemplo.
bool isHardwareButtons_CameraPressedAPIPresent =
Windows.Foundation.Metadata.ApiInformation.IsEventPresent
("Windows.Phone.UI.Input.HardwareButtons", "CameraPressed");
Como sabemos, o conjunto de APIs dentro de uma família de dispositivos é dividido ainda mais em subdivisões conhecidas como contratos de API. Você pode usar o método ApiInformation.IsApiContractPresent para testar a presença de um contrato de API. Essa é uma maneira eficiente de executar uma única condição para saber sobre a presença ou de outra forma de um grande número de APIs que pertencem à mesma versão de um contrato de API.
Para obter informações sobre como determinar o contrato de API que introduziu pela primeira vez as API de interesse, consulte a seção Pesquisar o contrato de API para uma API WinRT anteriormente neste tópico.
Depois de ter essas informações, você poderá conectá-la ao código adaptável. Por exemplo, se o nome do contrato de API for Windows.Devices.Scanners.ScannerDeviceContract
e seus números de versão principal e secundária forem 1 e 0, respectivamente, sua condição será semelhante ao exemplo abaixo.
bool isWindows_Devices_Scanners_ScannerDeviceContract_1_0Present =
Windows.Foundation.Metadata.ApiInformation.IsApiContractPresent
("Windows.Devices.Scanners.ScannerDeviceContract", 1, 0);
Visualizar sua interface do usuário em diferentes tamanhos de tela
Recomendamos que você maximize o alcance do seu aplicativo. Mas mesmo que você direcione apenas um tipo de fator de forma de dispositivo, provavelmente ainda haverá tamanhos diferentes de tela em que seu aplicativo pode acabar sendo exibido.
Quando você estiver pronto para ver a aparência do aplicativo e se dispor em um determinado tamanho de tela, use a barra de ferramentas de visualização do dispositivo no Visual Studio para visualizar sua interface do usuário em um dispositivo móvel pequeno ou médio, em um computador ou em uma tela de TV grande. Dessa forma, se você usou os recursos de layout adaptável do XAML (consulte Layouts adaptáveis com estados visuais e gatilhos de estado), você também pode testar isso.
Você não precisa tomar uma decisão com antecedência sobre cada tipo de dispositivo que você oferecerá suporte. Você pode adicionar um tamanho de dispositivo adicional ao seu projeto a qualquer momento.