Cómo verificar Android App Links

Los Android App Links son un tipo especial de vínculo directo que permite que las URL de tu sitio web abran inmediatamente el contenido correspondiente en tu app para Android (sin requerir que el usuario seleccione la app).

Para agregar Android App Links a tu app, define filtros de intents que abran el contenido de tu app con URL HTTP (como se describe en Cómo crear vínculos directos al contenido de la app), y verifica que posees las URL de app y del sitio web (como se describe en esta guía). Si el sistema verifica con éxito que posees las URL, automáticamente enruta esos intents de URL a tu app.

Para verificar la propiedad de tu app y tu sitio web, se requieren los siguientes pasos:

  • Solicita la verificación automática del vínculo de la app en tu manifiesto. Esto le indica al sistema Android que debería verificar que tu app pertenece al dominio URL utilizado en tus filtros de intents.
  • Declara la relación entre tu sitio web y tus filtros de intents. Para ello, aloja un archivo JSON de Vínculos de recursos digitales en la siguiente ubicación:
    https://domain.name/.well-known/assetlinks.json
    .

Puedes encontrar información relacionada en los siguientes recursos:

  • Compatibilidad con URL y App Indexing en Android Studio
  • Cómo crear una lista de instrucciones
  • Diferencia entre vínculos directos y vínculos de la app

    Un vínculo directo es un filtro de intents que permite a los usuarios ingresar directamente una actividad específica de tu app para Android. Cuando haces clic en uno de estos vínculos, es posible que se abra un diálogo de desambiguación, que permite al usuario seleccionar una app entre varias (incluida la tuya) que pueden administrar la URL determinada. Por ejemplo, en la figura 1, se muestra el cuadro de diálogo de desambiguación después de que el usuario hace clic en un vínculo del mapa y le pregunta si desea abrirlo en Maps o Chrome.

    Figura 1: Diálogo de desambiguación

    Un Android App Link es un vínculo directo basado en la URL de tu sitio web que tiene la verificación de que pertenece a tu sitio web. Por lo tanto, cuando haces clic en uno de estos vínculos, se abre tu app de inmediato, si está instalada. El diálogo de desambiguación no aparece. Sin embargo, el usuario puede cambiar su preferencia para manejar este tipo de vínculos más adelante.

    En la siguiente tabla, se describen diferencias más específicas.

    Vínculos directosVínculos de apps
    Esquema de URL del intent http, https o un esquema personalizado Requiere http o https
    Acción de intent Cualquier acción Requiere android.intent.action.VIEW
    Categoría del intent Cualquier categoría Requiere android.intent.category.BROWSABLE y android.intent.category.DEFAULT
    Verificación del vínculo Nada Requiere un archivo de Vínculos de recursos digitales en tu sitio web con HTTPS
    Experiencia del usuario Puede mostrar un diálogo de desambiguación para que el usuario seleccione la app que desea abrir Sin diálogo; se abre tu app para manejar los vínculos de tu sitio web
    Compatibilidad Todas las versiones de Android Android 6.0 y versiones posteriores

    Cómo solicitar verificación de vínculos de apps

    A fin de habilitar la verificación de control de vínculos para tu app, configura android:autoVerify="true" en cualquiera de los filtros de intents de URL web en el manifiesto de tu app que incluye la acción de intent android.intent.action.VIEW y la categoría de intent android.intent.category.BROWSABLE como se muestra en el siguiente fragmento de código de manifiesto:

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

    Cuando android:autoVerify="true" está presente en cualquiera de tus filtros de intents, instalar tu app en dispositivos con Android 6.0 y versiones posteriores hace que el sistema intente verificar todos los hosts asociados con las URL en cualquiera de los filtros de intents de tu app. A continuación, se describe qué implica la verificación:

    1. El sistema inspecciona todos los filtros de intents que incluyen:
      • Acción: android.intent.action.VIEW
      • Categorías: android.intent.category.BROWSABLE y android.intent.category.DEFAULT
      • Esquema de datos: http o https
    2. Por cada nombre de host único que se encuentra en los filtros de intents anteriores, Android consulta los sitios web correspondientes para el archivo de Vínculos de recursos digitales en https://hostname/.well-known/assetlinks.json.

    Solo si el sistema encuentra un archivo de Vínculos de recursos digitales coincidente para todos los hosts del manifiesto, establece tu app como el controlador predeterminado para los patrones de URL especificados.

    Cómo admitir vínculos de apps para varios hosts

    El sistema debe poder verificar cada host especificado en los elementos de datos de los filtros de intents de URL de la app en comparación con los archivos de Vínculos de recursos digitales alojados en los dominios web respectivos. Si falla alguna verificación, no se verificará que la app sea un controlador predeterminado para ninguno de los patrones de URL definidos en los filtros de intents de la app. Luego, el sistema adopta su comportamiento estándar de forma predeterminada para resolver el intent, como se describe en Cómo crear vínculos directos al contenido de la app.

    Por ejemplo, la verificación de una app con los siguientes filtros de intents fallará si no se encuentra un archivo assetlinks.json en https://www.example.com/.well-known/assetlinks.json y 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>
      

    Recuerda que se fusionan todos los elementos <data> en el mismo filtro de intents para representar todas las variaciones de sus atributos combinados. Por ejemplo, el primer filtro de intents anterior incluye un elemento <data> que solo declara el esquema HTTPS. Sin embargo, se combina con el otro elemento <data> para que el filtro de intents sea compatible con http://www.example.com y https://www.example.com. Por lo tanto, debes crear filtros de intents separados cuando desees definir combinaciones específicas de dominios y esquemas de URI.

    Cómo admitir vínculos de apps para varios subdominios

    El protocolo Vínculos de recursos digitales trata los subdominios de tus filtros de intents como hosts independientes y únicos. Por lo tanto, si tu filtro de intents enumera varios hosts con subdominios diferentes, debes publicar un assetlinks.json válido en cada dominio. Por ejemplo, el siguiente filtro de intents incluye www.example.com y mobile.example.com como hosts de URL de intents aceptados. Por lo tanto, un assetlinks.json válido debe publicarse en https://www.example.com/.well-known/assetlinks.json y 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, si declaras tu nombre de host con un comodín (como *.example.com), debes publicar tu archivo assetlinks.json en el nombre de host raíz (example.com). Por ejemplo, una app con el siguiente filtro de intents pasará la verificación de cualquier subnombre de example.com (como foo.example.com) siempre que se publique el archivo assetlinks.json en 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>
      

    Cómo declarar la asociación de sitios web

    Debes publicar un archivo JSON de Vínculos de recursos digitales en tu sitio web para indicar las apps para Android que están asociadas con el sitio web y verificar los intents de URL de la app. El archivo JSON usa los siguientes campos para identificar aplicaciones asociadas:

    • package_name: El ID de aplicación declarado en el archivo build.gradle de la app.
    • sha256_cert_fingerprints: Son las huellas digitales SHA256 del certificado de firma de tu app. Puedes usar el siguiente comando para generar la huella digital mediante la herramienta Keytool de Java:
        $ keytool -list -v -keystore my-release-key.keystore
        
      Este campo admite varias huellas digitales, que pueden usarse para brindar compatibilidad con diferentes versiones de tu app, como depuración y compilación de producción.

    En el siguiente ejemplo, el archivo assetlinks.json otorga derechos de apertura de vínculos a una 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"]
        }
      }]
      

    Cómo asociar un sitio web a varias apps

    Un sitio web puede declarar asociaciones con varias apps dentro del mismo archivo assetlinks.json. En la siguiente lista de archivos, se muestra un ejemplo de un archivo de instrucción que declara asociación con dos apps, por separado, y reside en 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"]
        }
      }]
      

    Distintas apps pueden manejar los vínculos para recursos diferentes en el mismo host web. Por ejemplo, la app1 puede declarar un filtro de intents para https://example.com/articles, y la app2 puede declarar un filtro de intents para https://example.com/videos.

    Nota: Varias apps asociadas a un dominio pueden firmarse con el mismo o con diferentes certificados.

    Cómo asociar varios sitios web a una sola app

    Varios sitios web pueden declarar asociaciones con la misma app en sus respectivos archivos assetlinks.json. En las siguientes listas de archivos, se muestra un ejemplo para declarar la asociación de example.com y example.net con app1. En la primera lista, se muestra la asociación de example.com con la 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"]
        }
      }]
      

    En la siguiente lista, se muestra la asociación de example.net con la app1. Solo la ubicación donde se alojan estos archivos es diferente (.com y .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"]
        }
      }]
      

    Publicación del archivo de verificación JSON

    Debes publicar tu archivo de verificación JSON en la siguiente ubicación:

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

    Asegúrate de lo siguiente:

    • Se publica el archivo assetlinks.json con el tipo de contenido application/json.
    • Se debe poder acceder al archivo assetlinks.json mediante una conexión HTTPS, independientemente de si los filtros de intents de la app declaran HTTPS como el esquema de datos.
    • Se debe poder acceder al archivo assetlinks.json sin redireccionamientos (sin redireccionamientos 301 o 302), y los bots deben poder acceder a él (su robots.txt debe permitir el rastreo de /.well-known/assetlinks.json).
    • Si los vínculos de tu app admiten varios dominios de host, debes publicar el archivo assetlinks.json en cada dominio. Consulta Cómo admitir vínculos de apps para varios hosts.
    • No publiques tu app con URL de desarrollo y prueba en el archivo de manifiesto que podría no estar disponible para el público (como los archivos que solo están disponibles con una VPN). En esos casos, una solución es configurar variantes de compilación para generar un archivo de manifiesto diferente para las compilaciones de desarrollo.

    Cómo probar vínculos de apps

    Cuando implementas la función de vínculos de apps, debes probar la funcionalidad de vinculación para asegurarte de que el sistema pueda asociar tu app con tus sitios web y manejar las solicitudes de URI, tal como lo quieres.

    Para probar un archivo de instrucciones existente, puedes usar la herramienta Generador y comprobador de listas de instrucciones.

    Cómo confirmar la lista de hosts que se deben verificar

    Cuando se realiza la prueba, debes confirmar la lista de hosts asociados que el sistema debe verificar para tu app. Haz una lista de todas las URL cuyos filtros de intents correspondientes incluyen los siguientes atributos y elementos:

    • Atributo android:scheme con un valor de http o https
    • Atributo android:host con un patrón de URL de dominio
    • Elemento de acción android.intent.action.VIEW
    • Elemento de categoría android.intent.category.BROWSABLE

    Usa esta lista para comprobar que se proporcione un archivo JSON de Vínculos de recursos digitales en cada host y subdominio nombrado.

    Cómo confirmar los archivos de Vínculos de recursos digitales

    En cada sitio web, usa la API de Vínculos de recursos digitales para confirmar que el archivo JSON de Vínculos de recursos digitales se encuentre alojado y definido correctamente:

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

    Prueba un intent de URL

    Una vez que confirmes la lista de sitios web asociados con tu app y que hayas confirmado que el archivo JSON es válido, instala la app en tu dispositivo. Espera al menos 20 segundos a que se complete el proceso de verificación asíncrono. Usa el siguiente comando para comprobar si el sistema verificó tu app y configura las políticas de control de vínculos correctas:

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

    Como parte de tu proceso de prueba, puedes comprobar la configuración actual del sistema para el control de vínculos. Usa el siguiente comando a fin de obtener una lista de políticas de control de vínculos existentes para todas las apps de tu dispositivo conectado:

      adb shell dumpsys package domain-preferred-apps
      

    Lo siguiente hace lo mismo:

      adb shell dumpsys package d
      

    Nota: Asegúrate de esperar al menos 20 segundos luego de instalar tu app para permitir que el sistema complete el proceso de verificación.

    El comando muestra un listado de cada usuario o perfil definidos en el dispositivo, precedido por un encabezado en el siguiente formato:

      App linkages for user 0:
      

    Luego de este encabezado, el resultado usa el siguiente formato a fin de enumerar las configuraciones de control de vínculos para ese usuario:

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

    Este listado indica qué aplicaciones están asociadas con qué dominios para ese usuario:

    • Package: Identifica una app por el nombre de su paquete, como se encuentra declarado en su manifiesto.
    • Domains: Muestra la lista completa de hosts cuyos vínculos web maneja esta app; utiliza espacios en blanco como delimitadores.
    • Status: Muestra la configuración actual de control de vínculos para esta app. Una app que aprobó la verificación, y cuyo manifiesto contiene android:autoVerify="true", muestra un estado de always. El número hexadecimal que le sigue a ese estado está relacionado con el registro de las preferencias de usuario para la vinculación de apps del sistema Android. Este valor no indica si la verificación tuvo éxito.

    Nota: Si un usuario cambia la configuración de vínculos de apps antes de que se complete la verificación, puede que veas un falso positivo de una verificación exitosa, aunque esta falle. Sin embargo, esta falla es relevante si el usuario habilita explícitamente la app para abrir vínculos compatibles sin preguntar. Esto se debe a que las preferencias del usuario tienen prioridad ante la verificación programática (o la ausencia de esta). Como consecuencia, el vínculo dirige de forma directa a tu app, sin mostrar un diálogo, como si la verificación hubiese tenido éxito.

    Ejemplo de comprobación

    Para que tenga éxito la verificación de vínculos de apps, el sistema debe poder verificar tu app con todos los sitios web que especifiques en los filtros de intents de tu app, y que cumplan con los criterios para los vínculos de apps. En el siguiente ejemplo, se muestra la configuración de un manifiesto con varios vínculos 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>
      

    La siguiente es la lista de hosts que la plataforma intentaría verificar a partir del manifiesto anterior:

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

    La siguiente es la lista de hosts que la plataforma no intentaría verificar a partir del manifiesto anterior:

      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 obtener más información sobre las listas de instrucciones, consulta Cómo crear una lista de instrucciones.