יצירת קישור עומק ליעד

ב-Android, קישור עומק הוא קישור שמפנה אתכם ישירות ליעד ספציפי באפליקציה.

באפליקציה אפשר לתמוך בשני סוגים שונים של קישורי עומק: מפורשים ומשתמעים. אופן ההטמעה של קישורי עומק משתנה בהתאם לסוג הגרף – XML or programmatic – שבו האפליקציה משתמשת.

יצירת קישור עומק מפורש

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

כשמשתמש פותח את האפליקציה באמצעות קישור עומק מפורש, מקבץ הפעילויות הקודמות (back stack) נמחק ומוחלף ביעד של קישור העומק. כשמטמיעים תרשימים, יעד ההתחלה מכל רמת הטמעה – כלומר, יעד ההתחלה מכל רכיב <navigation> בהיררכיה – מתווסף גם הוא למחסנית. המשמעות היא שכאשר משתמש לוחץ על הכפתור "הקודם" מיעד של קישור עומק, הוא חוזר אחורה במערך הניווט בדיוק כמו שהוא נכנס לאפליקציה מנקודת הכניסה שלה.

תרשימים פרוגרמטיים

אם גרף הניווט מוגדר באופן פרוגרמטי (כמו ב-Navigation Compose או ב-Kotlin DSL), מומלץ להשתמש ב-TaskStackBuilder כדי ליצור את קישור העומק PendingIntent.

val id = "exampleId"
val context = LocalContext.current
val deepLinkIntent = Intent(
    Intent.ACTION_VIEW,
    "https://www.example.com/profile/$id".toUri(),
    context,
    MyActivity::class.java
)

val pendingIntent: PendingIntent? = TaskStackBuilder.create(context).run {
    addNextIntentWithParentStack(deepLinkIntent)
    getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT)
}

תרשימי XML

אפשר להשתמש במחלקה NavDeepLinkBuilder כדי ליצור PendingIntent, כמו בדוגמה שלמטה. הערה: אם ההקשר שסופק הוא לא Activity, ה-constructor משתמש ב-PackageManager.getLaunchIntentForPackage() כפעילות ברירת המחדל להפעלה, אם היא זמינה.

Kotlin

val pendingIntent = NavDeepLinkBuilder(context)
    .setGraph(R.navigation.nav_graph)
    .setDestination(R.id.android)
    .setArguments(args)
    .createPendingIntent()

Java

PendingIntent pendingIntent = new NavDeepLinkBuilder(context)
    .setGraph(R.navigation.nav_graph)
    .setDestination(R.id.android)
    .setArguments(args)
    .createPendingIntent();

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

Kotlin

val pendingIntent = NavDeepLinkBuilder(context)
    .setGraph(R.navigation.nav_graph)
    .setDestination(R.id.android)
    .setArguments(args)
    .setComponentName(DestinationActivity::class.java)
    .createPendingIntent()

Java

PendingIntent pendingIntent = new NavDeepLinkBuilder(context)
        .setGraph(R.navigation.nav_graph)
        .setDestination(R.id.android)
        .setArguments(args)
        .setComponentName(DestinationActivity.class)
        .createPendingIntent();

אם יש לכם ComponentName, אתם יכולים להעביר אותו ישירות אל הכלי ליצירת תוכניות.

Kotlin

val componentName = ...

val pendingIntent = NavDeepLinkBuilder(context)
    .setGraph(R.navigation.nav_graph)
    .setDestination(R.id.android)
    .setArguments(args)
    .setComponentName(componentName)
    .createPendingIntent()

Java

ComponentName componentName = ...;

PendingIntent pendingIntent = new NavDeepLinkBuilder(context)
        .setGraph(R.navigation.nav_graph)
        .setDestination(R.id.android)
        .setArguments(args)
        .setComponentName(componentName)
        .createPendingIntent();

אם יש לכם NavController קיים, אתם יכולים ליצור קישור עומק גם באמצעות NavController.createDeepLink().

יצירת קישור עומק מרומז

קישור עומק משתמע הוא קישור ליעד ספציפי באפליקציה. כשמפעילים את קישור העומק – למשל, כשמשתמש לוחץ על קישור – מערכת Android יכולה לפתוח את האפליקציה ביעד המתאים.

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

תרשימים פרוגרמטיים

אם מגדירים את תרשים הניווט באופן פרוגרמטי (באמצעות Navigation Compose או Kotlin DSL), מגדירים את קישורי העומק בקוד.

אימייל חדש

ב-Navigation Compose, אפשר להגדיר קישורי עומק כחלק מcomposable()הכלי ליצירת יעדים באמצעות הפרמטר deepLinks. הפונקציה מקבלת רשימה של אובייקטים מסוג NavDeepLink, שאפשר ליצור באמצעות הפונקציה navDeepLink():

@Serializable
data class Profile(val id: String)

val uri = "https://www.example.com"

composable<Profile>(
  deepLinks = listOf(
    navDeepLink<Profile>(basePath = "$uri/profile")
  )
) { backStackEntry ->
  val profile: Profile = backStackEntry.toRoute()
  ProfileScreen(id = profile.id)
}

Kotlin DSL

כשמשתמשים ב-Kotlin DSL, אפשר להגדיר קישורי עומק באמצעות פונקציית ה-builder‏ deepLink() בתוך בלוק היעד:

@Serializable
data class Profile(val id: String)

val uri = "https://www.example.com"

fragment<ProfileFragment, Profile> {
    deepLink<Profile>(basePath = "$uri/profile")
}

הוספת מסנני Intent לתרשימים פרוגרמטיים

תרשימי ניווט פרוגרמטיים נוצרים בזמן ריצה, ולכן רכיב הניווט לא יכול ליצור באופן אוטומטי את רכיבי <intent-filter> התואמים ב-AndroidManifest.xml. במקום זאת, צריך להוסיף באופן ידני את רכיבי <intent-filter> המתאימים.

כדי להפעיל את קישור העומק בדוגמאות הקודמות, מוסיפים את הקוד הבא בתוך האלמנט <activity> המתאים במניפסט:

<activity …>
  <intent-filter>
    ...
    <data android:scheme="https" android:host="www.example.com" />
  </intent-filter>
</activity>

תרשימי XML

כדי ליצור קישור עומק משתמע בתרשים מבוסס-XML, אפשר להגדיר את הרכיב <deepLink> ישירות ב-XML או להשתמש בכלי לעריכת ניווט.

דוגמה לקישור עומק שמכיל URI, פעולה וסוג MIME:

<fragment android:id="@+id/a"
          android:name="com.example.myapplication.FragmentA"
          tools:layout="@layout/a">
        <deepLink app:uri="www.example.com"
                app:action="android.intent.action.MY_ACTION"
                app:mimeType="type/subtype"/>
</fragment>

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

  1. בכרטיסייה Design (עיצוב) של כלי העריכה של הניווט, בוחרים את היעד של קישור העומק.
  2. בקטע קישורים עמוקים בחלונית מאפיינים, לוחצים על +.
  3. בתיבת הדו-שיח הוספת קישור עומק שמופיעה, מזינים את הפרטים של קישור העומק.

    שימו לב לנקודות הבאות:

    • אם לא מציינים סכימה במזהי ה-URI, המערכת מניחה שמדובר ב-http או ב-https. לדוגמה, www.google.com תואם גם ל-http://www.google.com וגם ל-https://www.google.com.
    • מערכי placeholder של פרמטרים של נתיב בצורה {placeholder_name} תואמים לתו אחד או יותר. לדוגמה, http://www.example.com/users/{id} תואם ל-http://www.example.com/users/4. רכיב הניווט מנסה לנתח את ערכי ה-placeholder לסוגים המתאימים על ידי התאמת שמות ה-placeholder לארגומנטים המוגדרים ליעד של קישור העומק. אם לא מוגדר ארגומנט עם אותו שם, נעשה שימוש בסוג ברירת מחדל String עבור ערך הארגומנט. אפשר להשתמש בתו הכללי לחיפוש .* כדי להתאים ל-0 או יותר תווים.
    • אפשר להשתמש במחזיקי מקום של פרמטרים של שאילתה במקום בפרמטרים של נתיב, או בנוסף להם. לדוגמה, http://www.example.com/users/{id}?myarg={myarg} תואם ל-http://www.example.com/users/4?myarg=28.
    • אין צורך שתהיה התאמה בין משתני placeholder של פרמטרים של שאילתה לבין משתנים שהוגדרו עם ערכי ברירת מחדל או ערכים שניתנים לביטול. לדוגמה, http://www.example.com/users/{id}?arg1={arg1}&arg2={arg2} תואם ל-http://www.example.com/users/4?arg2=28 או ל-http://www.example.com/users/4?arg1=7. זה לא המצב עם פרמטרים של נתיב. לדוגמה, http://www.example.com/users?arg1=7&arg2=28 לא תואם לתבנית שלמעלה כי לא צוין פרמטר הנתיב הנדרש.
    • פרמטרים מיותרים של שאילתות לא משפיעים על התאמה של URI של קישור עומק. לדוגמה, http://www.example.com/users/{id} תואם ל-http://www.example.com/users/4?extraneousParam=7, למרות ש-extraneousParam לא מוגדר בתבנית ה-URI.
  4. (אופציונלי) מסמנים את התיבה אימות אוטומטי כדי ש-Google תאמת שאתם הבעלים של ה-URI. מידע נוסף זמין במאמר בנושא אימות קישורים לאפליקציות ל-Android.

  5. לוחצים על הוספה. סמל של קישור מופיע מעל היעד שנבחר כדי לציין שיש ליעד הזה קישור עמוק.

  6. לוחצים על הכרטיסייה קוד כדי לעבור לתצוגת ה-XML. נוסף רכיב <deepLink> מקונן ליעד:

    <deepLink app:uri="https://www.google.com" />
    

כדי להפעיל קישורי עומק משתמעים לתרשימים מבוססי XML, צריך גם להוסיף לקובץ manifest.xml של האפליקציה. מוסיפים רכיב <nav-graph> יחיד לפעילות שמפנה לתרשים ניווט קיים, כמו בדוגמה הבאה:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapplication">

    <application ... >

        <activity name=".MainActivity" ...>
            ...

            <nav-graph android:value="@navigation/nav_graph" />

            ...

        </activity>
    </application>
</manifest>

כשיוצרים את הפרויקט, רכיב הניווט מחליף את הרכיב <nav-graph> באלמנטים שנוצרו <intent-filter> כדי להתאים לכל קישורי העומק בתרשים הניווט.

קישורי עומק מרומזים ומקבץ פעילויות קודמות (back stack)

כשמפעילים קישור עומק מרומז, המצב של מקבץ הפעילויות הקודמות (back stack) תלוי בשאלה אם הקישור המרומז Intent הופעל עם הדגל Intent.FLAG_ACTIVITY_NEW_TASK:

  • אם הדגל מוגדר, מקבץ הפעילויות הקודמות (back stack) של המשימה מנוקה ומוחלפת ביעד של קישור העומק. בדומה לקישורי עומק מפורשים, כשמטמיעים גרפים, יעד ההתחלה מכל רמת הטמעה – כלומר, יעד ההתחלה מכל רכיב <navigation> בהיררכיה – מתווסף גם למחסנית. כלומר, כשמשתמש לוחץ על הכפתור "הקודם" מיעד של קישור עומק, הוא חוזר אחורה במערך הניווט בדיוק כמו שהוא נכנס לאפליקציה מנקודת הכניסה שלה.
  • אם הדגל לא מוגדר, נשארים במצבור המשימות של האפליקציה הקודמת שבה הופעל קישור העומק המרומז. במקרה כזה, כפתור 'הקודם' מחזיר אתכם לאפליקציה הקודמת, וכפתור 'למעלה' מתחיל את המשימה של האפליקציה ביעד ההורה ההיררכי בגרף הניווט.

טיפול בקישורי עומק

מומלץ מאוד להשתמש תמיד בברירת המחדל launchMode של standard כשמשתמשים בניווט. כשמשתמשים בstandard מצב הפעלה, ‏ Navigation מטפל אוטומטית בקישורי עומק על ידי קריאה ל-handleDeepLink() כדי לעבד קישורי עומק מפורשים או מרומזים בתוך Intent. עם זאת, זה לא קורה באופן אוטומטי אם נעשה שימוש חוזר ב-Activity כשמשתמשים ב-launchMode חלופי כמו singleTop. במקרה כזה, צריך להתקשר ידנית אל handleDeepLink() ב-onNewIntent(), כמו שמוצג בדוגמה הבאה:

Kotlin

override fun onNewIntent(intent: Intent?) {
    super.onNewIntent(intent)
    navController.handleDeepLink(intent)
}

Java

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    navController.handleDeepLink(intent);
}