(Android/Navigation) Navigation Component — Deep Link 처리


1. Deep Link란?

앱의 특정 화면으로 바로 진입하게 해주는 링크입니다. 알림 클릭, 웹 링크, 다른 앱에서의 호출 등에서 사용합니다.

종류 설명 예시
Explicit 앱 내부에서 PendingIntent로 특정 화면 지정 알림 클릭
Implicit URI로 외부에서 진입 https://example.com/product/42

<fragment
    android:id="@+id/detailFragment"
    android:name="com.example.app.DetailFragment">

    <argument android:name="productId" app:argType="integer" />

    <!-- {productId}가 위 argument로 자동 매핑 -->
    <deepLink app:uri="https://example.com/product/{productId}" />
    <deepLink app:uri="myapp://product/{productId}" />
</fragment>

Manifest에서 해당 Activity가 NavGraph를 사용한다고 알려줍니다.

<activity android:name=".MainActivity" android:exported="true">
    <nav-graph android:value="@navigation/nav_graph" />
</activity>

<nav-graph>가 빌드 시 위 deepLink들을 intent-filter로 자동 확장합니다. 직접 작성하지 않아도 됩니다.


3. 인자 매핑 규칙

URI: https://example.com/product/42?source=push

{productId} → path 인자 (integer)
?source=    → 쿼리 파라미터는 같은 이름의 argument(선택)로 매핑
class DetailFragment : Fragment() {
    private val args: DetailFragmentArgs by navArgs()
    // 딥링크로 들어와도 일반 이동과 동일하게 args.productId 사용
}

val pendingIntent = NavDeepLinkBuilder(context)
    .setGraph(R.navigation.nav_graph)
    .setDestination(R.id.detailFragment)
    .setArguments(bundleOf("productId" to 42))
    .createPendingIntent()

val notification = NotificationCompat.Builder(context, CHANNEL_ID)
    .setContentTitle("할인 상품")
    .setContentIntent(pendingIntent)   // 클릭 시 상세 화면으로
    .setAutoCancel(true)
    .build()

NavDeepLinkBuilder는 시작 화면부터 대상까지의 백스택을 합성해, 뒤로 가기 시 홈을 거쳐 앱이 자연스럽게 동작합니다.


https 링크가 브라우저 선택 창 없이 바로 앱으로 열리게 하려면 도메인 검증이 필요합니다.

<!-- 그래프의 deepLink에 autoVerify를 위해 Manifest에서 설정 -->
<nav-graph android:value="@navigation/nav_graph" />
1. https://example.com/.well-known/assetlinks.json 에 앱 패키지와 서명 SHA256 등록
2. deepLink 의 scheme을 https, host를 해당 도메인으로 선언

6. 테스트

# 에뮬레이터/기기에서 딥링크 실행
adb shell am start -a android.intent.action.VIEW \
  -d "myapp://product/42" com.example.app
// Navigation 테스트
val navController = TestNavHostController(context)
navController.setGraph(R.navigation.nav_graph)
navController.navigate(Uri.parse("myapp://product/42"))
assertEquals(R.id.detailFragment, navController.currentDestination?.id)

7. 주의사항


8. 정리



Related Posts