ทดสอบ App Link

เมื่อใช้ฟีเจอร์การลิงก์แอป คุณควรทดสอบฟังก์ชันการลิงก์เพื่อให้แน่ใจว่าระบบสามารถเชื่อมโยงแอปกับเว็บไซต์ และจัดการคำขอ URL ได้ตามที่คุณคาดหวัง

หากต้องการทดสอบไฟล์คำสั่งที่มีอยู่ คุณสามารถใช้เครื่องมือเครื่องมือสร้างและทดสอบรายการคำสั่งได้

ส่วนต่อไปนี้จะอธิบายวิธีทดสอบการยืนยัน App Link ด้วยตนเอง หากต้องการ คุณสามารถทดสอบการยืนยันจากเครื่องมือ Deep Link ของ Play หรือผู้ช่วย App Link ของ 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

สำหรับ App Link แบบไดนามิก คุณยังตรวจสอบส่วนขยายความสัมพันธ์ได้ด้วย

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 - ระบุแอปตามชื่อแพ็กเกจตามที่ประกาศไว้ในไฟล์ Manifest
  • Domains - แสดงรายการโฮสต์ทั้งหมดที่แอปนี้จัดการเว็บลิงก์ โดยใช้ช่องว่างเป็นตัวคั่น
  • Status - แสดงการตั้งค่าการจัดการลิงก์ปัจจุบันสำหรับแอปนี้ แอปที่ผ่านการยืนยันและมีไฟล์ Manifest ที่มี android:autoVerify="true" จะแสดงสถานะเป็น always เลขฐาน 16 หลังสถานะนี้เกี่ยวข้องกับบันทึกของระบบ Android เกี่ยวกับค่ากำหนดการลิงก์แอปของผู้ใช้ ค่านี้ไม่ได้ระบุว่าการยืนยันสำเร็จหรือไม่

ตัวอย่างการทดสอบ

เพื่อให้การยืนยัน App Link สำเร็จ ระบบต้องยืนยันแอปของคุณกับแต่ละเว็บไซต์ที่คุณระบุในตัวกรอง Intent ที่กำหนดซึ่งเป็นไปตามเกณฑ์สำหรับ App Link ได้ ตัวอย่างต่อไปนี้แสดงการกำหนดค่าไฟล์ Manifest ที่มีการกำหนด App Link ไว้หลายรายการ

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

รายการโฮสต์ที่แพลตฟอร์มจะพยายามยืนยันจากไฟล์ Manifest ก่อนหน้ามีดังนี้

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

รายการโฮสต์ที่แพลตฟอร์มจะไม่พยายามยืนยันจากไฟล์ Manifest ก่อนหน้ามีดังนี้

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 พร้อมกับกฎเฉพาะจากไฟล์ Manifest ของแอปและไฟล์ assetlinks.json (สำหรับ App Link แบบไดนามิก) ที่ได้รับการประเมินระหว่างการแก้ไข

หากต้องการทดสอบการแปลงลิงก์สำหรับ URL ที่เฉพาะเจาะจง ให้เรียกใช้คำสั่งต่อไปนี้ในหน้าต่างเทอร์มินัล

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

ผลการวินิจฉัยจะแสดงอยู่ใต้ส่วนหัว App Link Resolution Debug และมีส่วนต่างๆ ต่อไปนี้เพื่อช่วยให้คุณเข้าใจกระบวนการแก้ปัญหา

  • รายละเอียดเป้าหมาย: ระบุแอปที่เป็นไปได้ที่ตรงกันแต่ละแอปตามชื่อแพ็กเกจและกิจกรรมเป้าหมาย
  • Intent Filter Match (AndroidManifest.xml): แสดงแอตทริบิวต์แบบคงที่ในตัวกรอง Intent ของไฟล์ Manifest (เช่น scheme, host, path, pathPrefix หรือ pathPattern) ที่ตรงกับ URI
  • การยืนยัน App Link: แสดงสถานะการยืนยันโดเมนปัจจุบัน (เช่น STATE_SUCCESS)
  • App Link แบบไดนามิก: หากแอปใช้กฎการจับคู่ App Link แบบไดนามิกในไฟล์ 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 }

ในตัวอย่างนี้ ระบบประเมินกฎ App Link แบบไดนามิก 2 ข้อจาก 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. ระบบจะประเมินกฎ App Link แบบไดนามิกตามลำดับจากบนลงล่าง (กฎที่ตรงกันข้อแรกจะชนะ)
  3. เนื่องจากกฎ 0 ปรากฏเป็นอันดับแรกในรายการคำสั่งและเป็นกฎการยกเว้น (allow = 1) จึงมีความสำคัญเหนือกว่ากฎการอนุญาตทั่วไป (กฎ 1)
  4. ดังนั้น แอปจึงไม่รวมอยู่ในการจัดการ https://xyz.com/foo ซึ่งทำให้ระบบเปลี่ยนกลับไปใช้เบราว์เซอร์หรือแสดงกล่องโต้ตอบเพื่อแก้ความกำกวม