Universal Links Descomplicado: Conexão Web-Mobile para Todos os Desenvolvedores #1 — Mundo iOS

Este artigo nasceu da minha vivência na área de TI, onde me deparei com o desafio de migrar um projeto PWA para aplicativos nativos, o que despertou diversas dúvidas sobre comportamentos, especialmente relacionados aos universal links e ao login social.
Movido por essa experiência, decidi compartilhar minhas reflexões neste primeiro artigo. Caso o artigo receba um feedback positivo e veja engajamento, pretendo dar continuidade a essa jornada com um segundo artigo, abordando o universo Android, e incluindo apêndices dedicados ao Flutter e React Native.
This post was also written in English, click here to access the version
Introdução
Vamos começar com a situação de um projeto em que você tem um e-mail marketing ou uma landing page e deseja direcionar o usuário para clicar em um link específico, o qual abrirá o aplicativo instalado no dispositivo.
Nosso objetivo inicial está definido: clicar em um link específico e abrir o aplicativo instalado.
Como podemos fazer isso? Com isso em mente, meu objetivo é estabelecer uma conexão entre profissionais de front-end web e profissionais mobile, que precisarão colaborar para alcançar esse objetivo.
Estamos prestes a entrar na parte do código, certo, dev? Antes disso, gostaria de introduzir o tema de Associated Domains.
Em relação aos Associated Domains da Apple, existem dois tipos distintos: "webcredentials" e "applinks". Ambos desempenham funções diferentes e são essenciais para a integração entre aplicativos e websites.
Mundo Apple
Webcredentials
Webcredentials: Este é um tipo de Associated Domain que permite que um aplicativo iOS declare associações com credenciais de websites. Isso é útil para autenticação de usuário única (SSO) e preenchimento automático de credenciais de login. Quando um usuário tenta fazer login em um site associado ao aplicativo, o iOS pode sugerir automaticamente as credenciais salvas no aplicativo para preenchimento.
Applinks
Applinks: Os Applinks, por outro lado, são utilizados para vincular conteúdo entre o seu aplicativo e o seu website. Eles permitem que você associe determinados URLs em seu website com conteúdo específico em seu aplicativo. Por exemplo, se você tiver um link para uma página específica em seu website e desejar que ele abra o conteúdo correspondente em seu aplicativo, você pode usar Applinks para isso. Quando um usuário clica em um link associado em seu website, o iOS pode abrir o aplicativo apropriado, se instalado, e navegar diretamente para o conteúdo relacionado.
Mundo Android
Em um próximo artigo me aprofundo mais no mundo Android, mas para o Android, não existe um equivalente direto ao recurso Associated Domains do iOS. No entanto, há algumas funcionalidades relacionadas que podem ser utilizadas para propósitos semelhantes:
App Links (Deep Links)
App Links (Deep Links): Assim como os Applinks da Apple, os App Links são links que permitem que um site direcione os usuários para o conteúdo específico do aplicativo, se o aplicativo estiver instalado no dispositivo. Eles são uma forma de vincular o conteúdo entre o aplicativo e o website, permitindo uma transição suave entre os dois. Quando um usuário clica em um link de App Link em um navegador, o sistema operacional Android pode abrir o aplicativo apropriado e direcionar o usuário para o conteúdo relevante dentro do aplicativo.
Smart Lock for Passwords
Smart Lock for Passwords: Este recurso do Google permite que os usuários salvem e autentiquem automaticamente em aplicativos e sites sem a necessidade de digitar manualmente suas credenciais. Assim como os "webcredentials" da Apple, o Smart Lock for Passwords facilita a autenticação única (SSO) em aplicativos Android e websites associados. Quando os usuários fazem login em um aplicativo ou site que utiliza o Smart Lock for Passwords, eles têm a opção de salvar suas credenciais no Google, e o Android pode então preencher automaticamente essas credenciais quando necessário.
Abaixo uma tabela resumindo o comparativo entre recursos de iOS e Android:

Vamos aos códigos

Todos os códigos apresentados aqui estão disponíveis no meu GitHub e os links serão fornecidos no final do artigo.
Este projeto serve como base para uma série de testes e publicações que estou preparando para a minha equipe de desenvolvimento móvel. Portanto, você pode notar que a estrutura do projeto está um pouco diferente, pois eu o organizei em módulos e optei por não utilizar storyboards, entre outros aspectos. No entanto, não se preocupe se você está começando, pois abordarei os pontos importantes e relevantes aqui.
Iniciado com as configurações para a web
Primeiramente você precisa de um arquivo json chamado:
_apple-app-site-association_
ATENÇÃO! O Arquivo não deve conter a extensão _.json_
De acordo com a documentação o arquivo deve ficar na raiz do seu site ou dentro de uma pasta nomeada .well-known no exemplo deste artigo é o formato que usei.
Esta será a estrutura básica para o conteúdo do arquivo que usaremos neste exemplo:
{
"applinks": {
"apps": [],
"details": [
{
"appID": "35RIDB766W.me.micheltlutz.MobLab",
"paths": [
"/moblab.micheltlutz.me/settings-app"
]
}
]
}
}O atributo appID é a junção de "TEAMID.BUNDLE ID"
Em nosso caso vamos usar o atributo path apenas com o subdominio que tenho comfigurado e qualquer outro caminho que segue depois da barra, não adicione nenhum schema (http, https, meuapp) neste path.
Você pode ter mais detalhes sobre estas configurações no link da documentação oficial.
Vamos para o Xcode
Um ponto importante aqui é que será necessário ter uma conta de desenvolvedor no portal developer.apple.com, se você não ira publicar o app não é necessário pagar somente registre-se. Você precisa disso pois o é necessário os profile e certificados que são vinculados ao seu TeamID configurados para usar o Associated Domains. Caso contrário você recebera um aviso assim:

Aonde encontro meu TeamID?
Uma vez logado no portal developer da apple role a página principal até encontrar a área Informações da assinatura

_Nota: Não tente usar este TeamID pois alterei ele para evitar uso indevido_
Primeira coisa que precisamos fazer é selecionar o Projeto no Project Navigator
Irmos na aba Signing & Capabilities e adicionarmos suporte a Associated Domains, depois precisamos colocar nossa url em uma entrada applinks:
Veja a Imagem abaixo:

Ao final deve ficar assim como na imagem, lembre-se de usar a url do seu projeto web.
Vamos agora para a configuração do scheme:
Abra o Arquivo Info.plist Acesse a ramificação _URL types > Item > URL Schemes_ e adicione o scheme que deseja mapear no nosso caso moblab

Feito, essas foram as configurações do projeto que precisam ser feitas, agora para finalizar vamos aos códigos.
Importante!
O projeto está utilizando versão mais atual do Xcode até a data da publicação (Version 15.3 (15E204a) Configurei o projeto para usar UIKit. Neste caso o projeto tem o arquivo AppDelegate.swift e também o SceneDelegate.swift
Implementação no SceneDelegate
Vamos trabalhar no SceneDelegate será necessário criar o método openURLContexts onde faremos os tratamentos necessários.
O método `openURLContexts` é um método do protocolo `UISceneDelegate`, que é chamado quando a cena recebe um URL para abrir. Ele é usado para lidar com URLs recebidos pela cena da sua aplicação iOS. Esse método recebe um conjunto (Set) de objetos `UIOpenURLContext`, que contém informações sobre os URLs que estão sendo abertos.
Cada objeto `UIOpenURLContext` contém o próprio URL e outras informações relevantes, como o aplicativo que está abrindo o URL e o motivo pelo qual o URL está sendo aberto.
Ao implementar o método `scene(_:openURLContexts:)` no seu `SceneDelegate`, você pode acessar esses objetos `UIOpenURLContext` e processar os URLs recebidos conforme necessário. Isso pode incluir a manipulação do URL para navegar para uma determinada tela dentro do seu aplicativo, extrair informações do URL para processamento adicional ou realizar outras ações com base no conteúdo do URL.
Método `scene(_:openURLContexts:)` é fundamental para lidar com URLs recebidos pela sua aplicação iOS e permite que você responda adequadamente a esses URLs, conforme necessário para a funcionalidade do seu aplicativo.
Aqui está uma estrutura da utilização do método:
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
guard let url = URLContexts.first?.url else {
return
}
// Verifica se o URL possui um esquema associado
if let scheme = url.scheme {
// Verifica se o esquema é o esperado
if scheme == "meuapp" {
// Faça o que for necessário com o URL
// Por exemplo, manipule o URL para navegar para uma determinada tela
// ou extraia informações do URL para processamento adicional
}
}
}Em nosso projeto vamos fazer o seguinte:
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
guard let url = URLContexts.first?.url else {
return
}
if let scheme = url.scheme {
if scheme == "moblab" {
appManager?.start(with: url)
}
}
}Nele vamos confirmar se o scheme é o mesmo que mapeamos e vamos, a validação inicial é bem simples vamos apenas checar se o schema é o que queremos realmente abrir. Se sim neste momento você já poderia carregar sua ViewController.
Está feito, agora basta rodar o projeto no Simulador ou no Device acessar a url do seu projeto web e acessar o link.
Aqui para o projeto foi criado a seguinte página:
https://moblab.micheltlutz.me/
Veja a demonstração funcional:
Implementação no AppDelegate (versões anteriores)
Caso você esteja utilizando alguma versão anterior de código que não faça uso do SceneDelegate.swift você precisara fazer o mesmo procedimento no AppDelegate.swift veja o exemplo abaixo:
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
// Verifica se o URL possui um esquema associado
if let scheme = url.scheme {
// Verifica se o esquema é o esperado
if scheme == "meuapp" {
// Faça o que for necessário com o URL
// Por exemplo, manipule o URL para navegar para uma determinada tela
// ou extraia informações do URL para processamento adicional
return true
}
}
return false
}O método `application(_:open:options:)` é um método do protocolo `UIApplicationDelegate`, que é chamado quando a aplicação é aberta com um URL. Ele é usado para lidar com URLs recebidos pela aplicação iOS.
Este método recebe três parâmetros:
- `app`: A instância de `UIApplication` representando a aplicação.
- `url`: O URL que está sendo aberto.
- `options`: Um dicionário contendo informações adicionais sobre a forma como o URL está sendo aberto.
O retorno deste método é um booleano indicando se a aplicação foi capaz de lidar com o URL com sucesso.
Dentro deste método, você pode verificar o URL recebido e tomar as ações apropriadas com base no conteúdo do URL, da mesma forma como feito no _openURLContexts_.
Conclusão
Até a próxima, se você leu até aqui por favor deixe pelo menos 1 clap.
Repositórios
- Site: https://github.com/micheltlutz/moblab-site
- App: https://github.com/micheltlutz/moblab-ios
- Winged-Python: https://github.com/micheltlutz/Winged-Python
Referências
- Supporting associated domains | Apple Developer Documentation - Connect your app and a website to provide both a native app and a browser experience.
Meu post no dev.to: https://dev.to/micheltlutz/universal-links-made-easy-web-mobile-connection-for-all-developers-1-ios-world-5bia
