App-Links testen

Wenn du die App-Verknüpfungsfunktion implementierst, solltest du die Verknüpfungsfunktion testen, um sicherzustellen, dass das System deine App mit deinen Websites verknüpfen und URL-Anfragen wie erwartet verarbeiten kann.

Wenn Sie eine vorhandene Anweisungsdatei testen möchten, können Sie das Tool Statement List Generator and Tester verwenden.

In den folgenden Abschnitten wird beschrieben, wie Sie die App-Links-Überprüfung manuell testen. Sie können die Überprüfung auch mit dem Play-Tool für Deeplinks oder dem App-Link-Assistenten von Android Studio testen.

Liste der zu bestätigenden Hosts bestätigen

Beim Testen sollten Sie die Liste der verknüpften Hosts bestätigen, die das System für Ihre App prüfen soll. Erstellen Sie eine Liste aller URLs, deren entsprechende Intent-Filter die folgenden Attribute und Elemente enthalten:

  • Attribut android:scheme mit dem Wert http oder https
  • Attribut android:host mit einem Domain-URL-Muster
  • android.intent.action.VIEW-Aktionselement
  • android.intent.category.BROWSABLE-Kategorieelement

Anhand dieser Liste können Sie prüfen, ob auf jedem genannten Host und jeder genannten Subdomain eine Digital Asset Links-JSON-Datei vorhanden ist.

Digital Asset Links-Dateien bestätigen

Verwenden Sie für jede Website die Digital Asset Links API, um zu prüfen, ob die Digital Asset Links-JSON-Datei richtig gehostet und definiert ist:

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

Bei dynamischen App-Links können Sie auch die Beziehungserweiterungen prüfen.

https://digitalassetlinks.googleapis.com/v1/statements:list?source.web.site=https://www.example.com&relation=delegate_permission/common.handle_all_urls&return_relation_extensions=true

Im Rahmen des Testverfahrens können Sie die aktuellen Systemeinstellungen für die Linkverarbeitung prüfen. Verwenden Sie den folgenden Befehl, um eine Liste der vorhandenen Richtlinien für die Linkverarbeitung für alle Apps auf Ihrem verbundenen Gerät abzurufen:

adb shell dumpsys package domain-preferred-apps

Der folgende Befehl führt dieselbe Aktion aus:

adb shell dumpsys package d

Der Befehl gibt eine Liste aller auf dem Gerät definierten Nutzer oder Profile zurück, der ein Header im folgenden Format vorangestellt ist:

App linkages for user 0:

Nach dieser Überschrift werden die Einstellungen für die Linkverarbeitung für diesen Nutzer im folgenden Format aufgeführt:

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

In dieser Liste sehen Sie, welche Apps mit welchen Domains für diesen Nutzer verknüpft sind:

  • Package: Identifiziert eine App anhand ihres Paketnamens, wie im Manifest deklariert.
  • Domains: Zeigt die vollständige Liste der Hosts an, deren Weblinks von dieser App verarbeitet werden. Als Trennzeichen werden Leerzeichen verwendet.
  • Status: Zeigt die aktuelle Einstellung für die Linkverarbeitung für diese App an. Eine App, die die Bestätigung bestanden hat und deren Manifest android:autoVerify="true" enthält, hat den Status always. Die Hexadezimalzahl nach diesem Status bezieht sich auf den Eintrag des Android-Systems zu den Einstellungen des Nutzers für die App-Verknüpfung. Dieser Wert gibt nicht an, ob die Überprüfung erfolgreich war.

Testbeispiel

Damit die App-Link-Überprüfung erfolgreich ist, muss das System Ihre App mit jeder der Websites verifizieren können, die Sie in einem bestimmten Intent-Filter angeben, der die Kriterien für App-Links erfüllt. Das folgende Beispiel zeigt eine Manifestkonfiguration mit mehreren definierten App-Links:

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

Die Liste der Hosts, die die Plattform anhand des vorherigen Manifests zu bestätigen versucht, lautet:

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

Die Liste der Hosts, die die Plattform nicht aus dem vorherigen Manifest verifizieren würde, lautet:

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

Weitere Informationen zu Anweisungslisten finden Sie unter Anweisungsliste erstellen.

Ab Android 17 können Sie das Flag --debug-link mit dem Activity Manager-Befehl (am start) verwenden, um zu diagnostizieren, wie das System eine bestimmte URL auflöst. Dieses Tool bietet eine detaillierte Aufschlüsselung der Kandidaten-Apps, die dem Intent entsprechen, sowie die spezifischen Regeln aus dem App-Manifest und der assetlinks.json-Datei (für dynamische App-Links), die während der Auflösung ausgewertet wurden.

Führen Sie den folgenden Befehl in einem Terminalfenster aus, um die Linkauflösung für eine bestimmte URL zu testen:

adb shell am start --debug-link -a android.intent.action.VIEW -d "https://xyz.com/foo"

Die Diagnoseausgabe wird unter der Überschrift App Link Resolution Debug ausgegeben und enthält die folgenden Abschnitte, die Ihnen helfen, den Lösungsprozess zu verstehen:

  • Zieldetails:Identifiziert jede übereinstimmende Kandidaten-App anhand ihres Paketnamens und ihrer Zielaktivität.
  • Intent-Filter-Übereinstimmung (AndroidManifest.xml): Zeigt an, welche statischen Attribute im Intent-Filter des Manifests (z. B. scheme, host, path, pathPrefix oder pathPattern) mit dem URI übereinstimmen.
  • App-Link-Bestätigung:Zeigt den aktuellen Status der Domainbestätigung an (z. B. STATE_SUCCESS).
  • Dynamische App-Links:Wenn die App in ihrer assetlinks.json-Datei Regeln für dynamische App-Links verwendet, werden in diesem Abschnitt alle Regeln aufgeführt, die für den URI ausgewertet wurden. Jede Regel gibt die übereinstimmenden URI-Filter (z. B. Pfadpräfixe oder Muster) und ein allow-Feld an:
    • allow = 0: Eine Zulassungs-/Einschlussregel (allow: true). Wenn diese Regel zutrifft, darf die App den URI öffnen.
    • allow = 1: Eine Blockier-/Ausschlussregel (allow: false / exclude: true). Wenn diese Regel zutrifft, wird die App daran gehindert, den URI zu öffnen.
    • Hinweis: Ein leerer Filterstring (filter =) gibt ein leeres Pfadpräfix an, das mit allen Pfaden unter der Domain übereinstimmt (als Platzhalter oder Catch-all).

Beispiel für eine Debug-Ausgabe

Angenommen, eine App (com.example.xyzapp) ist mit der Domain https://xyz.com verknüpft und definiert in ihrer assetlinks.json-Datei dynamische Regeln, um /foo* auszuschließen, während alle anderen Pfade zulässig sind:

[
  {
    "relation": [
      "delegate_permission/common.handle_all_urls"
    ],
    "target": {
      "namespace": "android_app",
      "package_name": "com.example.xyzapp",
      "sha256_cert_fingerprints": ["..."]
    },
    "relation_extensions": {
      "delegate_permission/common.handle_all_urls": {
        "dynamic_app_link_components": [
          {"/": "/foo*", "exclude": true},
          {"/": "*"}
        ]
      }
    }
  }
]

Bei der Diagnose der URL https://xyz.com/foo mit --debug-link:

adb shell am start --debug-link -a android.intent.action.VIEW -d "https://xyz.com/foo"

Der Befehl gibt die folgende Diagnoseaufschlüsselung aus:

--- App Link Resolution Debug ---

URI: https://xyz.com/foo
Resolution: Ambiguous (Multiple apps or Browser fallback)
This usually happens when multiple apps can handle the link and no default is set.

All Matching Candidates:

Target:
  Package: com.example.xyzapp
  Activity: com.example.xyzapp.MainActivity

  Intent Filter Match (AndroidManifest.xml)
    Scheme: 'https' matched android:scheme="https"
    Host: 'xyz.com' matched android:host="xyz.com"

App Link Verification:
  Verification status: STATE_SUCCESS
  Dynamic App Links:
    -> Matched Rule 0: UriRelativeFilterGroup { allow = 1, uri_filters = {UriRelativeFilter { uriPart = PATH, patternType = PREFIX, filter = /foo }},  }
    -> Matched Rule 1: UriRelativeFilterGroup { allow = 0, uri_filters = {UriRelativeFilter { uriPart = PATH, patternType = PREFIX, filter =  }},  }

Target:
  Package: org.chromium.webview_shell
  Activity: org.chromium.webview_shell.WebViewBrowserActivity

  Intent Filter Match (AndroidManifest.xml)
    Scheme: 'https' matched android:scheme="https"

---------------------------------

Starting: Intent { act=android.intent.action.VIEW dat=https://xyz.com/foo }

In diesem Beispiel hat das System die beiden Regeln für dynamische App-Links aus assetlinks.json ausgewertet:

  • Regel 0 (allow = 1, filter = /foo): Diese Regel wurde aus {"/": "/foo*", "exclude": true} generiert und ist eine Ausschlussregel (allow: false), die URLs blockiert, die mit dem Pfadpräfix /foo beginnen.
  • Regel 1 (allow = 0, filter =): Diese Regel wurde aus {"/": "*"} generiert und ist eine Einschlussregel (allow: true) mit einem leeren Pfadpräfix (filter =), die mit allen Pfaden unter xyz.com übereinstimmt (Catch-all).

So funktioniert die Auflösung in diesem Szenario:

  1. Sowohl Regel 0 als auch Regel 1 stimmen mit der URL https://xyz.com/foo überein.
  2. Regeln für dynamische App-Links werden nacheinander von oben nach unten ausgewertet. Die erste übereinstimmende Regel wird angewendet.
  3. Da Regel 0 zuerst in der Anweisungsliste aufgeführt ist und eine Ausschlussregel (allow = 1) ist, hat sie Vorrang vor der allgemeinen Zulassungsregel (Regel 1).
  4. Die App wird daher von der Verarbeitung von https://xyz.com/foo ausgeschlossen, sodass das System auf den Browser zurückgreift oder ein Dialogfeld zur Mehrdeutigkeitsauflösung anzeigt.