앱 링크 테스트

앱 링크 기능을 구현할 때는 링크 기능을 테스트하여 시스템에서 제대로 앱과 웹사이트를 연결하고 URL 요청을 처리할 수 있는지 확인해야 합니다.

기존 명령문 파일을 테스트하려면 명령문 목록 생성기 및 테스터 도구를 사용하면 됩니다.

다음 섹션에서는 앱 링크 인증을 수동으로 테스트하는 방법을 설명합니다. 원하는 경우 Play 딥 링크 도구 또는 Android 스튜디오 앱 링크 어시스턴트에서 인증을 테스트할 수 있습니다.

인증할 호스트 목록 확인하기

테스트할 때는 시스템이 앱에 관해 인증해야 하는 연결된 호스트 목록을 확인해야 합니다. 상응하는 인텐트 필터에 다음 속성과 요소가 포함된 모든 URL 목록을 작성하세요.

  • android:scheme 값이 있는 http 또는 https 속성
  • 도메인 URL 패턴이 있는 android:host 속성
  • android.intent.action.VIEW 작업 요소
  • android.intent.category.BROWSABLE 카테고리 요소

이 목록을 사용하여 디지털 애셋 링크 JSON 파일이 이름이 지정된 각 호스트와 하위 도메인에 제공되는지 확인합니다.

디지털 애셋 링크 파일 확인하기

각 웹사이트에서 Digital Asset Links API를 사용하여 디지털 애셋 링크 JSON 파일이 적절히 호스팅되고 정의되었는지 확인합니다.

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 상태를 보여줍니다. 이 상태 뒤에 나오는 16진수는 사용자의 앱 연결 환경설정에 관한 Android 시스템의 기록과 관련이 있습니다. 이 값은 인증이 성공했는지 여부를 나타내지 않습니다.

테스트 예시

앱 링크 인증이 성공하려면 시스템은 앱 링크의 기준을 충족하는 특정 인텐트 필터에서 지정된 각 웹사이트와 관련하여 앱을 인증할 수 있어야 합니다. 다음 예에서는 여러 앱 링크가 정의된 매니페스트 구성을 보여줍니다.

<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부터 활동 관리자 (am start) 명령어와 함께 --debug-link 플래그를 사용하여 시스템에서 특정 URL을 확인하는 방법을 진단할 수 있습니다. 이 도구는 확인 중에 평가된 앱 매니페스트 및 assetlinks.json 파일 (동적 앱 링크의 경우)의 특정 규칙과 함께 인텐트와 일치하는 후보 앱의 세부 분석을 제공합니다.

특정 URL의 링크 확인을 테스트하려면 터미널 창에서 다음 명령어를 실행합니다.

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

진단 출력은 App Link Resolution Debug 헤더 아래에 출력되며 확인 프로세스를 이해하는 데 도움이 되는 다음 섹션이 포함되어 있습니다.

  • 타겟 세부정보: 패키지 이름과 타겟 활동으로 일치하는 각 후보 앱을 식별합니다.
  • 인텐트 필터 일치 (AndroidManifest.xml): 매니페스트 인텐트 필터의 정적 속성 (예: 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 =)은 도메인 아래의 모든 경로와 일치하는 빈 경로 프리픽스를 나타냅니다 (와일드 카드 또는 캐치올 역할을 함).

디버그 출력 예

assetlinks.json 파일에서 동적 규칙을 정의하여 /foo*를 제외하는 동시에 다른 모든 경로를 허용하는 도메인 https://xyz.com과 연결된 앱 (com.example.xyzapp)을 고려해 보겠습니다.

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

--debug-link를 사용하여 URL https://xyz.com/foo를 진단할 때:

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}에서 생성된 이 규칙은 /foo 경로 프리픽스로 시작하는 URL을 차단하는 제외 규칙(allow: false)입니다.
  • 규칙 1 (allow = 0, filter =): {"/": "*"}에서 생성된 이 규칙은 빈 경로 프리픽스 (filter =)가 있는 포함 규칙 (allow: true)으로, xyz.com 아래의 모든 경로와 일치합니다 (캐치올).

이 시나리오에서 확인이 작동하는 방식:

  1. 규칙 0과 규칙 1 모두 URL https://xyz.com/foo와 일치합니다.
  2. 동적 앱 링크 규칙은 위에서 아래로 순서대로 평가됩니다(첫 번째 일치 규칙이 우선함).
  3. 규칙 0 은 명령문 목록에 먼저 표시되고 제외 규칙 (allow = 1)이므로 일반 허용 규칙 (규칙 1)보다 우선합니다.
  4. 따라서 앱은 https://xyz.com/foo 처리에 제외되어 시스템이 브라우저로 대체되거나 선택 대화상자를 표시합니다.