Verificar Android App Links

Android App Links são um tipo especial de link direto que permite que os URLs do seu site abram o conteúdo correspondente de imediato no app para Android, sem exigir que o usuário selecione o app.

Para adicionar Android App Links ao seu app, defina filtros de intent que abram o conteúdo do app usando URLs HTTP (conforme descrito em Criar links diretos para conteúdo de app) e verifique se você possui os URLs do app e do site (conforme descrito neste guia). Se o sistema verificar que você possui os URLs, ele encaminhará automaticamente esses intents de URL para o app.

Para verificar a propriedade do app e do site, as seguintes etapas são obrigatórias:

  • Solicite a verificação automática do link de app no seu manifesto. Isso indica para o sistema Android que é preciso verificar se o app pertence ao domínio de URL usado nos filtros de intent.
  • Declare o relacionamento entre o site e os filtros de intent hospedando um arquivo JSON de Digital Asset Links no seguinte local:
    https://domain.name/.well-known/assetlinks.json
    .

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

  • Compatibilidade com URLs e indexação de apps no Android Studio
  • Como criar uma lista de instruções
  • A diferença entre links diretos e links de app

    Um link direto é um filtro de intent que permite aos usuários inserir diretamente uma atividade específica no app para Android. Clicar em um desses links pode abrir uma caixa de diálogo de desambiguação, que permite ao usuário selecionar um dos vários apps (incluindo o seu) que podem processar o URL fornecido. Por exemplo, a Figura 1 mostra a caixa de diálogo de desambiguação depois que o usuário clica em um link de mapa, perguntando se ele quer abrir o link no Maps ou no Chrome.

    Figura 1. Caixa de diálogo de desambiguação.

    Um Android App Link é um link direto baseado no URL do site que foi verificado como pertencente ao seu site. Por isso, a ação de clicar em um deles abre o app de imediato (se estiver instalado). A caixa de diálogo de desambiguação não é exibida. Mas, posteriormente, o usuário pode mudar a preferência para o modo de processar esses links.

    A tabela a seguir descreve diferenças mais específicas.

    Links diretosLinks do app
    Esquema do URL de intent http, https ou um esquema personalizado Requer http ou https
    Ação da intent Qualquer ação Requer android.intent.action.VIEW
    Categoria de intent Qualquer categoria Requer android.intent.category.BROWSABLE e android.intent.category.DEFAULT
    Verificação de link Nenhuma Requer um arquivo Digital Asset Links exibido no seu site com HTTPS
    Experiência do usuário Pode mostrar uma caixa de diálogo de desambiguação para o usuário selecionar qual app abrirá o link Nenhuma caixa de diálogo. O app é aberto para processar os links do seu site
    Compatibilidade Todas as versões do Android Android 6.0 e posterior

    Solicitar verificação de links de app

    Para ativar a verificação de processamento de links para seu app, defina android:autoVerify="true" em qualquer um dos filtros de intent de URL da Web no manifesto do app que inclua a ação de intent android.intent.action.VIEW e a categoria de intent android.intent.category.BROWSABLE, conforme mostrado no seguinte snippet de código de manifesto:

    <activity ...>
    
      <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" android:host="www.example.com" />
          <data android:scheme="https" />
      </intent-filter>
    
    </activity>
    

    Quando android:autoVerify="true" está presente em qualquer um dos filtros de intent, a instalação do app em dispositivos com o Android 6.0 e versões mais recentes faz com que o sistema tente verificar todos os hosts associados aos URLs em qualquer um dos filtros de intent do app. A verificação 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.

    O sistema só estabelecerá seu app como o gerenciador tradicional para os padrões de URL especificados se encontrar um arquivo Digital Asset Links correspondente para todos os hosts no manifesto.

    Como oferecer compatibilidade com links de app para diversos hosts

    O sistema precisa verificar cada host especificado nos elementos de dados dos filtros de intent de URL do app com relação aos arquivos Digital Asset Links hospedados em todos os respectivos domínios da Web. Se alguma verificação falhar, o app não será considerado gerenciador tradicional para nenhum padrão de URL definido nos próprios filtros de intent. Nesse caso, o sistema usará o próprio comportamento padrão para resolver o intent, conforme descrito em Criar links diretos para conteúdo de app.

    Por exemplo, um app com os seguintes filtros de intent falharia na verificação se um arquivo assetlinks.json não fosse encontrado em https://www.example.com/.well-known/assetlinks.json e 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" android:host="www.example.com" />
        <data android:scheme="https" />
      </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" android:host="www.example.net" />
      </intent-filter>
    </activity>
    
    </application>
    

    Lembre-se de que todos os elementos <data> no mesmo filtro de intent são mesclados para considerar todas as variações dos seus 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" android:host="www.example.com" />
        <data android:scheme="https" 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), será necessário publicar o arquivo assetlinks.json no nome do host raiz (example.com). Por exemplo, um app com o seguinte filtro de intent 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" android:host="*.example.com" />
      </intent-filter>
    </activity>
    </application>
    

    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 diversas 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.

    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) e ser acessível por bots. O robots.txt precisa permitir o rastreamento de /.well-known/assetlinks.json.
    • 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.

    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 testar uma intent de URL

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

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

    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 por você nos filtros de intent e atender aos critérios de vinculação de app. O exemplo abaixo mostra uma configuração de manifesto com diversos links de apps 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" android:host="www.example.com" />
              <data android:scheme="https" 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" 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" 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" 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" 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.