Verificar Android App Links

Um Android App Link é um tipo especial de link direto que permite que os URLs do seu site abram imediatamente o conteúdo correspondente no app para Android, sem exigir que o usuário selecione o app. Os Android App Links usam a API Digital Asset Links para estabelecer confiança de que o app foi aprovado pelo site para abrir automaticamente links para esse domínio. Se o sistema verificar que você é o proprietário dos URLs, ele encaminhará automaticamente esses intents de URL para o app.

Para verificar se você é o proprietário do app e dos URLs do site, siga estas etapas:

  1. Adicione filtros de intent que contenham o atributo autoVerify. Esse atributo sinaliza ao sistema que ele precisa verificar se o app pertence aos domínios de URL usados nos filtros de intent.

  2. Declare a associação entre o site e os filtros de intent hospedando um arquivo JSON de links de ativos digitais no seguinte local:

    https://domain.name/.well-known/assetlinks.json

É possível encontrar informações relacionadas nos seguintes recursos:

Adicionar filtros de intent para a verificação de links de apps

Para ativar a verificação de processamento de links no seu app, adicione filtros de intent que correspondam a este formato:

<!-- Make sure you explicitly set android:autoVerify to "true". -->
<intent-filter android:autoVerify="true">
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />

    <!-- If a user clicks on a shared link that uses the "http" scheme, your
         app should be able to delegate that traffic to "https". -->
    <!-- Do not include other schemes. -->
    <data android:scheme="http" />
    <data android:scheme="https" />

    <!-- Include one or more domains that should be verified. -->
    <data android:host="..." />
</intent-filter>

Embora seja suficiente incluir autoVerify em apenas uma declaração <intent-filter> para cada host, mesmo que ele seja usado em outras declarações não marcadas, é recomendável adicionar autoVerify a cada elemento <intent-filter> para manter a consistência. Isso também garante que, depois de remover ou refatorizar elementos no arquivo de manifesto, o app continue associado a todos os domínios que você ainda definir.

O processo de verificação de domínio exige uma conexão com a Internet e pode levar algum tempo para ser concluído. Para ajudar a melhorar a eficiência do processo, o sistema verifica um domínio para um app direcionado ao Android 12 ou mais recente apenas se esse domínio estiver em um elemento <intent-filter> que contenha o formato exato especificado no snippet de código anterior. Por exemplo, esquemas diferentes de "http" e "https", como <data android:scheme="custom" />, impedem que uma <intent-filter> acione a verificação de domínio.

Oferecer compatibilidade com links de app para diversos hosts

O sistema precisa verificar o host especificado nos elementos de dados dos filtros de intent de URL do app em relação aos arquivos Digital Asset Links hospedados nos respectivos domínios da Web nesse filtro de intent. Se a verificação falhar, o sistema vai usar o comportamento padrão para resolver a intent, conforme descrito em Criar links diretos para conteúdo de app. No entanto, o app ainda pode ser verificado como gerenciador padrão para qualquer um dos padrões de URL definidos nos outros filtros de intent do app.

Observação:no Android 11 (nível 30 da API) e versões anteriores, o sistema não verifica o app como gerenciador padrão, a menos que encontre um arquivo Digital Asset Links correspondente para todos os hosts que você define no manifesto.

Por exemplo, um app com os seguintes filtros de intent vai passar na verificação apenas para https://www.example.com se um arquivo assetlinks.json for encontrado em https://www.example.com/.well-known/assetlinks.json, mas não https://www.example.net/.well-known/assetlinks.json:

<application>

  <activity android:name=”MainActivity”>
    <intent-filter android:autoVerify="true">
      <action android:name="android.intent.action.VIEW" />
      <category android:name="android.intent.category.DEFAULT" />
      <category android:name="android.intent.category.BROWSABLE" />
      <data android:scheme="http" />
      <data android:scheme="https" />
      <data android:host="www.example.com" />
    </intent-filter>
  </activity>
  <activity android:name=”SecondActivity”>
    <intent-filter>
      <action android:name="android.intent.action.VIEW" />
      <category android:name="android.intent.category.DEFAULT" />
      <category android:name="android.intent.category.BROWSABLE" />
      <data android:scheme="https" />
     <data android:host="www.example.net" />
    </intent-filter>
  </activity>

</application>

Observação:todos os elementos <data> no mesmo filtro de intent são mesclados para considerar todas as variações dos atributos combinados. Por exemplo, o primeiro filtro de intent acima inclui um elemento <data> que declara apenas o esquema HTTPS. Mas ele é combinado com o outro elemento <data> para que o filtro de intent seja compatível com http://www.example.com e https://www.example.com. Dessa forma, você precisará criar filtros de intent separados quando quiser definir combinações específicas de esquemas de URI e domínios.

Oferecer compatibilidade com links de app para diversos subdomínios

O protocolo Digital Asset Links trata subdomínios nos seus filtros de intent como hosts exclusivos e separados. Portanto, se o filtro de intent listar vários hosts com subdomínios diferentes, será necessário publicar um assetlinks.json válido em cada domínio. Por exemplo, o filtro de intent a seguir inclui www.example.com e mobile.example.com como hosts de URL de intent aceitos. Portanto, um assetlinks.json válido precisa ser publicado em https://www.example.com/.well-known/assetlinks.json e https://mobile.example.com/.well-known/assetlinks.json.

<application>
  <activity android:name=”MainActivity”>
    <intent-filter android:autoVerify="true">
      <action android:name="android.intent.action.VIEW" />
      <category android:name="android.intent.category.DEFAULT" />
      <category android:name="android.intent.category.BROWSABLE" />
      <data android:scheme="https" />
      <data android:scheme="https" />
      <data android:host="www.example.com" />
      <data android:host="mobile.example.com" />
    </intent-filter>
  </activity>
</application>

Como alternativa, se você declarar o nome do host com um caractere curinga (como *.example.com), publique o arquivo assetlinks.json no nome do host raiz (example.com). Por exemplo, um app com o seguinte filtro de intent vai passar na verificação de qualquer subnome de example.com (como foo.example.com), desde que o arquivo assetlinks.json seja publicado em https://example.com/.well-known/assetlinks.json:

<application>
  <activity android:name=”MainActivity”>
    <intent-filter android:autoVerify="true">
      <action android:name="android.intent.action.VIEW" />
      <category android:name="android.intent.category.DEFAULT" />
      <category android:name="android.intent.category.BROWSABLE" />
      <data android:scheme="https" />
      <data android:host="*.example.com" />
    </intent-filter>
  </activity>
</application>

Verificar se há vários apps associados ao mesmo domínio

Se você publicar vários apps, cada um associado ao mesmo domínio, todos eles poderão ser verificados. No entanto, se os apps puderem resolver exatamente o mesmo host de domínio e caminho, assim como ocorre com as versões Lite e completas de um app, apenas o app instalado mais recentemente poderá resolver intents da Web para o domínio.

Nesse caso, verifique se há apps conflitantes no dispositivo do usuário, contanto que você tenha a visibilidade de pacotes necessária. Em seguida, no app, exiba uma caixa de diálogo de seletor personalizada que contenha os resultados da chamada de queryIntentActivities(). O usuário poderá selecionar o app preferido na lista de apps correspondentes exibidos na caixa de diálogo.

Declarar associações de site

É preciso publicar um arquivo JSON Digital Asset Links no seu site para indicar os apps para Android associados ao site e verificar os intents de URL do app. O arquivo JSON usa os seguintes campos para identificar apps associados:

  • package_name: o ID do aplicativo declarado no arquivo build.gradle do app.
  • sha256_cert_fingerprints: as impressões digitais SHA256 do certificado assinado do app. É possível usar o Java Keytool para gerar a impressão digital usando o seguinte comando:
    keytool -list -v -keystore my-release-key.keystore
    
    Esse campo é compatível com várias impressões digitais, que podem ser usadas para fins de compatibilidade com diferentes versões do seu app, como versões de depuração e de produção.

    Se você estiver usando a Assinatura de apps do Google Play no seu app, a impressão digital do certificado produzida ao executar keytool localmente geralmente não corresponderá à dos dispositivos dos usuários. Você pode verificar se está usando a Assinatura de apps do Google Play para seu app na sua conta de desenvolvedor do Play Console em Release > Setup > App signing. Se fizer isso, você também vai encontrar o snippet JSON correto do Digital Asset Links do app na mesma página.

O seguinte arquivo de exemplo assetlinks.json concede direitos de abertura de links a um app para Android com.example:

[{
  "relation": ["delegate_permission/common.handle_all_urls"],
  "target": {
    "namespace": "android_app",
    "package_name": "com.example",
    "sha256_cert_fingerprints":
    ["14:6D:E9:83:C5:73:06:50:D8:EE:B9:95:2F:34:FC:64:16:A0:83:42:E6:1D:BE:A8:8A:04:96:B2:3F:CF:44:E5"]
  }
}]

Como associar um site com diversos apps

Um site da Web pode declarar associações com diversos apps dentro do mesmo arquivo assetlinks.json. A seguinte lista de arquivos exibe um exemplo de arquivo de declaração de associação com dois apps separadamente e está localizada em https://www.example.com/.well-known/assetlinks.json:

[{
  "relation": ["delegate_permission/common.handle_all_urls"],
  "target": {
    "namespace": "android_app",
    "package_name": "com.example.puppies.app",
    "sha256_cert_fingerprints":
    ["14:6D:E9:83:C5:73:06:50:D8:EE:B9:95:2F:34:FC:64:16:A0:83:42:E6:1D:BE:A8:8A:04:96:B2:3F:CF:44:E5"]
  }
  },
  {
  "relation": ["delegate_permission/common.handle_all_urls"],
  "target": {
    "namespace": "android_app",
    "package_name": "com.example.monkeys.app",
    "sha256_cert_fingerprints":
    ["14:6D:E9:83:C5:73:06:50:D8:EE:B9:95:2F:34:FC:64:16:A0:83:42:E6:1D:BE:A8:8A:04:96:B2:3F:CF:44:E5"]
  }
}]

Diferentes apps podem processar links para recursos distintos sob o mesmo host da Web. Por exemplo, o app1 pode declarar um filtro de intent para https://example.com/articles, e o app2 pode declarar um filtro de intent para https://example.com/videos.

Observação: diversos apps associados a um domínio podem ser assinados com o mesmo certificado ou com certificados diferentes.

Associar diversos sites a um único app

Vários sites podem declarar associações com o mesmo app nos respectivos arquivos assetlinks.json. As listas de arquivos a seguir mostram um exemplo de como declarar a associação de example.com e example.net com o app1. A primeira lista mostra a associação de example.com ao app1:

https://www.example.com/.well-known/assetlinks.json

[{
  "relation": ["delegate_permission/common.handle_all_urls"],
  "target": {
    "namespace": "android_app",
    "package_name": "com.mycompany.app1",
    "sha256_cert_fingerprints":
    ["14:6D:E9:83:C5:73:06:50:D8:EE:B9:95:2F:34:FC:64:16:A0:83:42:E6:1D:BE:A8:8A:04:96:B2:3F:CF:44:E5"]
  }
}]

A próxima lista mostra a associação de example.net ao app1. Somente o local em que esses arquivos estão hospedados é diferente (.com e .net):

https://www.example.net/.well-known/assetlinks.json

[{
  "relation": ["delegate_permission/common.handle_all_urls"],
  "target": {
    "namespace": "android_app",
    "package_name": "com.mycompany.app1",
    "sha256_cert_fingerprints":
    ["14:6D:E9:83:C5:73:06:50:D8:EE:B9:95:2F:34:FC:64:16:A0:83:42:E6:1D:BE:A8:8A:04:96:B2:3F:CF:44:E5"]
  }
}]

Publicar o arquivo de verificação JSON

É preciso publicar o arquivo de verificação JSON no seguinte local:

https://domain.name/.well-known/assetlinks.json

As condições a seguir precisam ser atendidas:

  • O arquivo assetlinks.json é exibido com tipo de conteúdo application/json.
  • O arquivo assetlinks.json precisa ser acessível por meio de uma conexão HTTPS, independentemente de os filtros de intent do app declararem HTTPS como o esquema de dados ou não.
  • O arquivo assetlinks.json precisa ser acessível sem redirecionamentos (sem redirecionamentos 301 ou 302).
  • Se os links do app forem compatíveis com vários domínios de host, publique o arquivo assetlinks.json em cada domínio. Consulte Como oferecer compatibilidade com links de app para diversos hosts.
  • Não publique seu app com URLs de desenvolvimento/teste em arquivos de manifesto que podem não ser publicamente acessíveis (por exemplo, todos aqueles que só podem ser acessados com uma VPN). Uma solução alternativa nesses casos é configurar variantes de compilação para gerar outro arquivo de manifesto para versões de desenvolvimento.

Verificação de Links do app Android

Quando android:autoVerify="true" está presente em pelo menos um dos filtros de intent do app, a instalação do app em um dispositivo com o Android 6.0 (nível 23 da API) ou mais recente faz com que o sistema verifique automaticamente os hosts associados aos URLs nos filtros de intent do app. No Android 12 e mais recentes, também é possível invocar o processo de verificação manualmente para testar a lógica de verificação.

Verificação automática

A verificação automática do sistema envolve o seguinte:

  1. O sistema inspeciona todos os filtros de intent que incluem:
    • Ação: android.intent.action.VIEW
    • Categorias: android.intent.category.BROWSABLE e android.intent.category.DEFAULT
    • Esquema de dados: http ou https
  2. Para cada nome de host exclusivo encontrado nos filtros de intent acima, o Android consulta os sites correspondentes para o arquivo Digital Asset Links em https://hostname/.well-known/assetlinks.json.

Depois de confirmar a lista de sites a serem associados ao app e que o arquivo JSON hospedado é válido, instale o app no dispositivo. Aguarde pelo menos 20 segundos para que o processo de verificação assíncrona seja concluído. Use o seguinte comando para verificar se o sistema verificou o app e definiu as políticas corretas de tratamento de links:

adb shell am start -a android.intent.action.VIEW \
    -c android.intent.category.BROWSABLE \
    -d "http://domain.name:optional_port"

Verificação manual

A partir do Android 12, é possível invocar manualmente a verificação de domínio para um app instalado em um dispositivo. É possível realizar esse processo sendo o app direcionado ao Android 12 ou não.

Estabelecer uma conexão com a Internet

Para realizar a verificação de domínio, o dispositivo de teste precisa estar conectado à Internet.

Oferecer compatibilidade com o processo de verificação de domínio atualizado

Se o app for destinado ao Android 12 ou versões mais recentes, o sistema vai usar o processo de verificação de domínio atualizado automaticamente.

Caso contrário, é possível ativar manualmente o processo de verificação atualizado. Para fazer isso, execute os comandos a seguir em uma janela de terminal:

adb shell am compat enable 175408749 PACKAGE_NAME

Redefinir o estado de Links do app Android em um dispositivo

Antes de invocar manualmente a verificação de domínio em um dispositivo, você precisa redefinir o estado de Links do app Android no dispositivo de teste. Para fazer isso, execute os comandos a seguir em uma janela de terminal:

adb shell pm set-app-links --package PACKAGE_NAME 0 all

Esse comando coloca o dispositivo no mesmo estado em que estava antes do usuário escolher apps padrão para qualquer domínio.

Invocar o processo de verificação do domínio

Depois de redefinir o estado de Links do app Android em um dispositivo, você poderá fazer a verificação por conta própria. Para fazer isso, execute os comandos abaixo em uma janela de terminal:

adb shell pm verify-app-links --re-verify PACKAGE_NAME

Analisar os resultados da verificação

Após aguardar um tempo para que o agente de verificação conclua as solicitações, analise os resultados. Para isso, execute o comando a seguir:

adb shell pm get-app-links PACKAGE_NAME

A saída deste comando será parecida com esta:

com.example.pkg:
    ID: 01234567-89ab-cdef-0123-456789abcdef
    Signatures: [***]
    Domain verification state:
      example.com: verified
      sub.example.com: legacy_failure
      example.net: verified
      example.org: 1026

Os domínios aprovados na verificação têm um estado de verificação de domínio verified (verificado). Qualquer outro estado indica que não foi possível realizar a verificação de domínio. Especificamente, o estado none (nenhum) indica que talvez o agente de verificação ainda não tenha concluído o processo.

A lista a seguir mostra os possíveis valores que a verificação pode retornar para um domínio:

none
Nada foi registrado para este domínio. Aguarde mais alguns minutos para que o agente de verificação conclua as solicitações relacionadas à verificação de domínio e invoque o processo de verificação de domínio novamente.
verified
O domínio foi verificado para o app de declaração.
approved
O domínio foi aprovado de maneira forçada, geralmente pela execução de um comando do shell.
denied
O domínio foi negado de maneira forçada, geralmente pela execução de um comando do shell.
migrated
O sistema manteve o resultado de um processo anterior que usava a verificação de domínio legada.
restored
O domínio foi aprovado após a restauração de dados do usuário. Presume-se que o domínio foi verificado anteriormente.
legacy_failure
O domínio foi rejeitado por um verificador legado. O motivo específico da falha é desconhecido.
system_configured
O domínio foi aprovado automaticamente pelo configurador do dispositivo.
Código de erro de 1024 ou maior.

Código de erro personalizado específico do verificador do dispositivo.

Confira se você estabeleceu uma conexão de rede e invoque o processo de verificação de domínio novamente.

Solicitar ao usuário para associar o app a um domínio

Outra maneira de aprovar o app para um domínio é pedir ao usuário para associá-lo a esse domínio.

Conferir se o app já foi aprovado para o domínio

Antes de solicitar ao usuário, confira se o app é o gerenciador padrão dos domínios definidos nos elementos <intent-filter>. Consulte o estado da aprovação usando um dos métodos a seguir:

DomainVerificationManager

O snippet de código a seguir demonstra como usar a API DomainVerificationManager:

Kotlin

val context: Context = TODO("Your activity or fragment's Context")
val manager = context.getSystemService(DomainVerificationManager::class.java)
val userState = manager.getDomainVerificationUserState(context.packageName)

// Domains that have passed Android App Links verification.
val verifiedDomains = userState?.hostToStateMap
    ?.filterValues { it == DomainVerificationUserState.DOMAIN_STATE_VERIFIED }

// Domains that haven't passed Android App Links verification but that the user
// has associated with an app.
val selectedDomains = userState?.hostToStateMap
    ?.filterValues { it == DomainVerificationUserState.DOMAIN_STATE_SELECTED }

// All other domains.
val unapprovedDomains = userState?.hostToStateMap
    ?.filterValues { it == DomainVerificationUserState.DOMAIN_STATE_NONE }

Java

Context context = TODO("Your activity or fragment's Context");
DomainVerificationManager manager =
        context.getSystemService(DomainVerificationManager.class);
DomainVerificationUserState userState =
        manager.getDomainVerificationUserState(context.getPackageName());

Map<String, Integer> hostToStateMap = userState.getHostToStateMap();
List<String> verifiedDomains = new ArrayList<>();
List<String> selectedDomains = new ArrayList<>();
List<String> unapprovedDomains = new ArrayList<>();
for (String key : hostToStateMap.keySet()) {
    Integer stateValue = hostToStateMap.get(key);
    if (stateValue == DomainVerificationUserState.DOMAIN_STATE_VERIFIED) {
        // Domain has passed Android App Links verification.
        verifiedDomains.add(key);
    } else if (stateValue == DomainVerificationUserState.DOMAIN_STATE_SELECTED) {
        // Domain hasn't passed Android App Links verification, but the user has
        // associated it with an app.
        selectedDomains.add(key);
    } else {
        // All other domains.
        unapprovedDomains.add(key);
    }
}

Programa de linha de comando

Quando testar o app durante o desenvolvimento, você pode executar o comando a seguir para consultar o estado da verificação dos domínios da sua organização:

adb shell pm get-app-links --user cur PACKAGE_NAME

Na saída de exemplo a seguir, mesmo que o app tenha falhado na verificação para o domínio "example.org", o usuário 0 aprovou manualmente o app nas configurações do sistema e nenhum outro pacote foi verificado para esse domínio.

com.example.pkg:
ID: ***
Signatures: [***]
Domain verification state:
  example.com: verified
  example.net: verified
  example.org: 1026
User 0:
  Verification link handling allowed: true
  Selection state:
    Enabled:
      example.org
    Disabled:
      example.com
      example.net

Você também pode usar comandos de shell para simular o processo em que o usuário seleciona qual app é associado a um determinado domínio. Uma explicação completa desses comandos está disponível na saída de adb shell pm.

Fornecer contexto para a solicitação

Antes de fazer essa solicitação de aprovação de domínio, forneça um contexto para o usuário. Por exemplo, você pode mostrar uma tela de apresentação, uma caixa de diálogo ou um elemento de IU parecido que explique ao usuário por que o app precisa ser o gerenciador padrão de um determinado domínio.

Fazer a solicitação

Após o usuário entender o que o app está pedindo, faça a solicitação. Para fazer isso, invoque uma intent que inclua a ação da intenet ACTION_APP_OPEN_BY_DEFAULT_SETTINGS e uma string de dados correspondente a package:com.example.pkg para o app de destino, conforme mostrado no snippet de código a seguir:

Kotlin

val context: Context = TODO("Your activity or fragment's Context")
val intent = Intent(Settings.ACTION_APP_OPEN_BY_DEFAULT_SETTINGS,
    Uri.parse("package:${context.packageName}"))
context.startActivity(intent)

Java

Context context = TODO("Your activity or fragment's Context");
Intent intent = new Intent(Settings.ACTION_APP_OPEN_BY_DEFAULT_SETTINGS,
    Uri.parse("package:" + context.getPackageName()));
context.startActivity(intent);

Quando a intent for invocada, os usuários verão uma tela de configurações chamada Abrir por padrão. Essa tela tem um botão de opção chamado Abrir links compatíveis, conforme mostrado na Figura 1.

Quando o usuário ativa a opção Abrir links compatíveis, um conjunto de caixas de seleção aparece em uma seção chamada Links a serem abertos no app. Nessa seção, os usuários podem selecionar os domínios que querem associar ao app. Eles também podem selecionar Adicionar link para adicionar domínios, conforme mostrado na Figura 2. Mais tarde, quando os usuários selecionarem um link nos domínios adicionados, ele será aberto automaticamente no app.

Quando o botão de opção estiver ativado, uma seção perto da parte inferior
    incluirá caixas de seleção e um botão &quot;Adicionar link&quot;
Figura 1. Tela de configurações do sistema em que os usuários podem escolher quais links são abertos no app por padrão.
Cada caixa de seleção representa um domínio que você pode adicionar. Os
    botões da caixa de diálogo são &quot;Cancelar&quot; e &quot;Adicionar&quot;.
Figura 2. Caixa de diálogo em que os usuários podem escolher outros domínios para associar ao app.

Domínios abertos no app que não podem ser verificados por ele

A função principal do app pode ser a de abrir links como um terceiro, sem a capacidade de verificar os domínios processados. Se esse for o caso, explique aos usuários que, ao selecionar um link da Web, eles não poderão escolher entre um app primário e seu app (de terceiros). Os usuários precisam associar manualmente os domínios ao app de terceiros.

Além disso, considere apresentar uma caixa de diálogo ou atividade trampolim, que possibilite que o usuário abra o link no app primário, se ele preferir, agindo como um proxy. Antes de configurar essa atividade de caixa de diálogo ou trampolim, configure seu app para que ele tenha a visibilidade de pacote nos apps primários correspondentes ao filtro de intent da Web do app.

Testar links de app

Ao implementar o recurso de vinculação de apps, teste essa funcionalidade para verificar se o sistema consegue associar seu app aos sites e processar solicitações de URL conforme esperado.

Para testar um arquivo de instrução já existente, use a ferramenta Statement List Generator and Tester.

Confirmar a lista de hosts a serem verificados

Durante os testes, confirme a lista de hosts associados que o sistema precisa verificar para o app. Faça uma lista de todas os URLs da Web com filtros de intent que incluem os seguintes atributos e elementos:

  • Atributo android:scheme com um valor de http ou https
  • Atributo android:host com um padrão de URL de domínio
  • Elemento de ação android.intent.action.VIEW
  • Elemento de categoria android.intent.category.BROWSABLE

Use essa lista para verificar se um arquivo JSON Digital Asset Links foi disponibilizado para cada host e subdomínio nomeado.

Confirmar os arquivos Digital Asset Links

Para cada site, use a API Digital Asset Links para confirmar se o arquivo JSON Digital Asset Links está hospedado e definido corretamente:

https://digitalassetlinks.googleapis.com/v1/statements:list?
   source.web.site=https://domain.name:optional_port&
   relation=delegate_permission/common.handle_all_urls

Como parte do processo de testes, é possível verificar as definições atuais do sistema para o processamento de links. Use o seguinte comando para ver uma lista das políticas de processamento de links já existentes para todos os apps no dispositivo conectado:

adb shell dumpsys package domain-preferred-apps

O comando abaixo, que tem o mesmo efeito:

adb shell dumpsys package d

Observação: aguarde pelo menos 20 segundos depois da instalação do app para que o sistema conclua o processo de verificação.

O comando retorna uma lista de cada usuário ou perfil definido no dispositivo, precedida por um cabeçalho no seguinte formato:

App linkages for user 0:

Depois desse cabeçalho, o resultado usa o seguinte formato para listar as configurações de processamento de links para esse usuário:

Package: com.android.vending
Domains: play.google.com market.android.com
Status: always : 200000002

A lista indica quais apps foram associados a cada domínio para o usuário:

  • Package: identifica um app pelo nome do pacote, como declarado no manifesto.
  • Domains: mostra a lista completa de hosts cujos links da Web são processados pelo app, usando espaços em branco como delimitadores.
  • Status: mostra a configuração atual de processamento de links para o app. Um app que passou na verificação e cujo manifesto contém android:autoVerify="true" mostra o status always. O número hexadecimal depois desse status refere-se ao registro do sistema Android das preferências de vinculação de app do usuário. Esse valor não indica se a verificação foi concluída.

Observação: se o usuário alterar as configurações de vinculação de app antes de concluir a verificação, poderá ver um falso positivo de verificação bem-sucedida, mesmo que ela tenha falhado. No entanto, a falha dessa verificação não fará diferença se o usuário tiver ativado o app de maneira explícita para abrir links compatíveis sem perguntar. Isso acontece porque as preferências do usuário têm precedência sobre a verificação programática (ou a falta dela). Como resultado, o link acessa diretamente o app, sem mostrar caixas de diálogo, como se a verificação tivesse sido bem-sucedida.

Exemplo de teste

Para que a verificação de vinculação de app seja realizada corretamente, o sistema precisa verificar seu app com todos os sites especificados em um determinado filtro de intent que atenda aos critérios de vinculação de app. O exemplo abaixo mostra uma configuração de manifesto com diversos links de aplicativo definidos:

<application>

    <activity android:name=”MainActivity”>
        <intent-filter android:autoVerify="true">
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:scheme="https" />
            <data android:scheme="https" />
            <data android:host="www.example.com" />
            <data android:host="mobile.example.com" />
        </intent-filter>
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:scheme="https" />
            <data android:host="www.example2.com" />
        </intent-filter>
    </activity>

    <activity android:name=”SecondActivity”>
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:scheme="https" />
            <data android:host="account.example.com" />
        </intent-filter>
    </activity>

      <activity android:name=”ThirdActivity”>
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <data android:scheme="https" />
            <data android:host="map.example.com" />
        </intent-filter>
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:scheme="market" />
            <data android:host="example.com" />
        </intent-filter>
      </activity>

</application>

A lista de hosts que a plataforma tentaria verificar do manifesto acima é:

www.example.com
mobile.example.com
www.example2.com
account.example.com

A lista de hosts que a plataforma não tentaria verificar do manifesto acima é:

map.example.com (it does not have android.intent.category.BROWSABLE)
market://example.com (it does not have either an "http" or "https" scheme)

Para saber mais sobre listas de instruções, consulte Criar uma lista de instruções.

Corrigir erros comuns de implementação

Se você não conseguir verificar os links de app Android, verifique os seguintes erros comuns. Esta seção usa example.com como um nome de domínio de marcador de posição. Ao realizar essas verificações, substitua example.com pelo nome de domínio real do servidor.

Configuração incorreta do filtro de intent
Verifique se você incluiu um URL que não pertence ao seu app em um elemento <intent-filter>.
Configuração incorreta do servidor

Verifique a configuração JSON do servidor e confirme se o valor SHA está correto.

Além disso, verifique se example.com. (com o ponto final) exibe o mesmo conteúdo que example.com.

Redirecionamentos do lado do servidor

O sistema não vai verificar nenhum Link do app Android para seu app se você configurar um redirecionamento, como este:

  • http://example.com a https://example.com
  • example.com a www.example.com

Esse comportamento protege a segurança do app.

Robustez do servidor

Verifique se o servidor pode se conectar aos apps do cliente.

Links não verificáveis

Para fins de teste, você pode adicionar links não verificáveis intencionalmente. Lembre-se de que, no Android 11 e versões anteriores, esses links fazem com que o sistema não verifique todos os Links do app Android para seu app.

Assinatura incorreta em assetlinks.json

Verifique se a assinatura está correta e corresponde à assinatura usada para assinar o app. Erros comuns incluem:

  • Assinaturar o app com um certificado de depuração e ter apenas a assinatura de lançamento em assetlinks.json.
  • Ter uma assinatura em letras minúsculas em assetlinks.json. A assinatura precisa ser em maiúsculas.
  • Se você estiver usando a Assinatura de apps do Google Play, confira se está usando a assinatura que o Google usa para assinar cada versão. É possível verificar esses detalhes, incluindo um snippet JSON completo, seguindo as instruções sobre como declarar associações de sites.