בדיקת קישורי אפליקציות

כשמטמיעים את תכונת הקישור לאפליקציה, צריך לבדוק את פונקציונליות הקישור כדי לוודא שהמערכת יכולה לשייך את האפליקציה לאתרים שלכם ולטפל בבקשות לכתובות URL כצפוי.

כדי לבדוק קובץ תמונת מצב קיים, אתם יכולים להשתמש בכלי Statement List Generator and Tester.

בקטעים הבאים מוסבר איך לבדוק באופן ידני את האימות של קישורי העומק לאפליקציה. אם אתם מעדיפים, אתם יכולים לבדוק את האימות באמצעות הכלי "קישורי עומק" ב-Play או באמצעות App Links Assistant ב-Android Studio.

מאשרים את רשימת המארחים שרוצים לאמת.

במהלך הבדיקה, צריך לאשר את רשימת המארחים המשויכים שהמערכת צריכה לאמת בשביל האפליקציה. צריך להכין רשימה של כל כתובות ה-URL שמסנני ה-Intent התואמים שלהן כוללים את המאפיינים והרכיבים הבאים:

  • המאפיין android:scheme עם הערך http או https
  • המאפיין android:host עם תבנית URL של דומיין
  • רכיב פעולה אחד (android.intent.action.VIEW)
  • רכיב קטגוריה אחד (android.intent.category.BROWSABLE)

אתם יכולים להשתמש ברשימה הזו כדי לבדוק שקובץ JSON של Digital Asset Links מופיע בכל מארח ודומיין משנה שצוינו.

אישור קובצי Digital Asset Links

לכל אתר, משתמשים ב-Digital Asset Links API כדי לוודא שקובץ ה-JSON של Digital Asset Links מתארח ומוגדר בצורה תקינה:

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

בקישורים דינמיים לאפליקציות, אפשר גם לבדוק את תוספי הקשרים.

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

כחלק מתהליך הבדיקה, אתם יכולים לבדוק את הגדרות המערכת הנוכחיות לטיפול בקישורים. כדי לקבל רשימה של כללי המדיניות הקיימים לטיפול בקישורים בכל האפליקציות במכשיר המחובר, משתמשים בפקודה הבאה:

adb shell dumpsys package domain-preferred-apps

הפקודה הבאה עושה את אותו הדבר:

adb shell dumpsys package d

הפקודה מחזירה רשימה של כל משתמש או פרופיל שמוגדר במכשיר, ולפניה כותרת בפורמט הבא:

App linkages for user 0:

אחרי הכותרת הזו, הפלט משתמש בפורמט הבא כדי להציג את הגדרות הטיפול בקישורים של אותו משתמש:

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

הרשימה הזו מציינת אילו אפליקציות משויכות לאילו דומיינים של אותו משתמש:

  • ‫Package – מזהה אפליקציה לפי שם החבילה שלה, כפי שהוצהר במניפסט שלה.
  • Domains – הצגת הרשימה המלאה של המארחים שהאפליקציה הזו מטפלת בקישורים שלהם לדפי אינטרנט אחרים, באמצעות רווחים כמפרידים.
  • Status – מציג את ההגדרה הנוכחית של הטיפול בקישורים באפליקציה הזו. באפליקציה שעברה אימות, ושקובץ המניפסט שלה מכיל את android:autoVerify="true", מוצג הסטטוס always. המספר ההקסדצימלי שמופיע אחרי הסטטוס הזה קשור לרשומה של מערכת Android לגבי העדפות המשתמש לקישור אפליקציות. הערך הזה לא מציין אם האימות הצליח.

דוגמה לבדיקה

כדי שאימות הקישורים לאפליקציה יצליח, המערכת צריכה להיות מסוגלת לאמת את האפליקציה עם כל אחד מהאתרים שציינתם במסנן Intent נתון שעומד בקריטריונים לקישורים לאפליקציה. הדוגמה הבאה מציגה הגדרת מניפסט עם כמה קישורים לאפליקציה:

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

רשימת המארחים שהפלטפורמה תנסה לאמת מהמניפסט הקודם היא:

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

רשימת המארחים שהפלטפורמה לא תנסה לאמת מהמניפסט הקודם היא:

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

מידע נוסף על רשימות הצהרות זמין במאמר יצירת רשימת הצהרות.

החל מ-Android 17, אתם יכולים להשתמש בדגל --debug-link עם הפקודה של מנהל הפעילות (am start) כדי לאבחן איך המערכת פותרת כתובת URL ספציפית. הכלי הזה מספק פירוט של האפליקציות המועמדות שתאמו ל-Intent, יחד עם הכללים הספציפיים מקובץ המניפסט של האפליקציה ומקובץ assetlinks.json (לקישורי עומק דינמיים לאפליקציה) שנבדקו במהלך הרזולוציה.

כדי לבדוק את פתרון הקישור של כתובת URL ספציפית, מריצים את הפקודה הבאה בחלון הטרמינל:

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

פלט האבחון מודפס מתחת לכותרת App Link Resolution Debug, והוא מכיל את הקטעים הבאים כדי לעזור לכם להבין את תהליך הפתרון:

  • פרטי היעד: מזהה כל אפליקציה מועמדת תואמת לפי שם החבילה והפעילות המטורגטת שלה.
  • התאמה למסנן Intent‏ (AndroidManifest.xml): מראה אילו מאפיינים סטטיים במסנן ה-Intent של המניפסט (כמו scheme,‏ host,‏ path,‏ pathPrefix או pathPattern) תאמו ל-URI.
  • אימות קישורי עומק לאפליקציה: מציג את מצב האימות הנוכחי של הדומיין (למשל STATE_SUCCESS).
  • קישורי עומק דינמיים לאפליקציה: אם האפליקציה משתמשת בכללי התאמה של קישורי עומק דינמיים לאפליקציה בקובץ assetlinks.json, בקטע הזה מפורטים כל הכללים שנבדקו מול ה-URI. כל כלל מציין את מסנני ה-URI התואמים (כמו תחיליות או תבניות של נתיבים) ושדה allow:
    • ‫allow = 0: כלל אישור/הכללה (allow: true). אם הכלל הזה תואם, האפליקציה יכולה לפתוח את ה-URI.
    • ‫allow = 1: כלל חסימה/החרגה (allow: false / exclude: true). אם הכלל הזה תואם, האפליקציה לא יכולה לפתוח את ה-URI.
    • הערה: מחרוזת מסנן ריקה (filter =) מציינת קידומת נתיב ריקה שתואמת לכל הנתיבים בדומיין (פועלת כתו כללי לחיפוש או כהתאמה לכל).

פלט לדוגמה של ניפוי באגים

נניח שיש אפליקציה (com.example.xyzapp) שמשויכת לדומיין https://xyz.com, ובקובץ assetlinks.json שלה מוגדרים כללים דינמיים שמחריגים את /foo* ומאפשרים את כל שאר הנתיבים:

[
  {
    "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},
          {"/": "*"}
        ]
      }
    }
  }
]

במהלך אבחון של כתובת ה-URL‏ https://xyz.com/foo באמצעות --debug-link:

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

פלט הפקודה מציג את פירוט האבחון הבא:

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

בדוגמה הזו, המערכת העריכה את שני הכללים של קישורי העומק הדינמיים לאפליקציה מ-assetlinks.json:

  • כלל 0 (allow = 1, filter = /foo): נוצר מ-{"/": "/foo*", "exclude": true}, זהו כלל החרגה (allow: false) שחוסם כתובות URL שמתחילות בתחילית הנתיב /foo.
  • כלל 1 (allow = 0, filter =): נוצר מ-{"/": "*"}, זהו כלל הכללה (allow: true) עם קידומת נתיב ריקה (filter =), שתואמת לכל הנתיבים ב-xyz.com (כולל הכול).

איך פותרים את הבעיה בתרחיש הזה:

  1. גם כלל 0 וגם כלל 1 תואמים לכתובת ה-URL‏ https://xyz.com/foo.
  2. הכללים של קישורי עומק דינמיים לאפליקציות נבדקים לפי הסדר מלמעלה למטה (הכלל התואם הראשון הוא זה שמופעל).
  3. בגלל שכלל 0 מופיע ראשון ברשימת ההצהרות והוא כלל החרגה (allow = 1), הוא מקבל עדיפות על פני כלל ההרשאה הכללי (כלל 1).
  4. לכן האפליקציה לא מטפלת ב-https://xyz.com/foo, והמערכת חוזרת לדפדפן או מציגה תיבת דו-שיח להפגת עמימות.