یک پیوند عمیق برای یک مقصد ایجاد کنید

در اندروید، یک لینک عمیق (deep link) لینکی است که شما را مستقیماً به یک مقصد خاص در یک برنامه هدایت می‌کند.

شما می‌توانید از دو نوع مختلف لینک‌های عمیق در برنامه خود پشتیبانی کنید: صریح و ضمنی . نحوه پیاده‌سازی لینک‌های عمیق بسته به نوع نموداری که برنامه شما استفاده می‌کند XML or programmatic - متفاوت است.

یک لینک عمیق صریح ایجاد کنید

یک لینک عمیق صریح ، نمونه‌ای واحد از یک لینک عمیق است که از یک PendingIntent برای انتقال کاربران به یک مکان خاص در برنامه شما استفاده می‌کند. به عنوان مثال، می‌توانید یک لینک عمیق صریح را به عنوان بخشی از یک اعلان یا یک ویجت برنامه نمایش دهید.

وقتی کاربری برنامه شما را از طریق یک پیوند عمیق صریح باز می‌کند، پشته بازگشت وظیفه پاک شده و با مقصد پیوند عمیق جایگزین می‌شود. هنگام تودرتو کردن نمودارها ، مقصد شروع از هر سطح تودرتوسازی - یعنی مقصد شروع از هر عنصر <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 ، همانطور که در مثال زیر نشان داده شده است، استفاده کنید. توجه داشته باشید که اگر context ارائه شده یک Activity نباشد، سازنده از PackageManager.getLaunchIntentForPackage() به عنوان activity پیش‌فرض برای اجرا، در صورت وجود، استفاده می‌کند.

کاتلین

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

جاوا

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

به طور پیش‌فرض، NavDeepLinkBuilder لینک عمیق صریح شما را در Activity راه‌اندازی پیش‌فرض که در مانیفست برنامه شما اعلام شده است، راه‌اندازی می‌کند. اگر NavHost شما در فعالیت دیگری است، باید هنگام ایجاد سازنده لینک عمیق، نام کامپوننت آن را مشخص کنید:

کاتلین

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

جاوا

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

اگر یک ComponentName دارید، می‌توانید آن را مستقیماً به سازنده ارسال کنید:

کاتلین

val componentName = ...

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

جاوا

ComponentName componentName = ...;

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

اگر از قبل یک NavController دارید، می‌توانید با استفاده از NavController.createDeepLink() یک deep link ایجاد کنید.

ایجاد یک لینک عمیق ضمنی

یک لینک عمیق ضمنی به یک مقصد خاص در یک برنامه اشاره دارد. وقتی لینک عمیق فراخوانی می‌شود - مثلاً وقتی کاربر روی یک لینک کلیک می‌کند - اندروید می‌تواند برنامه شما را به مقصد مربوطه باز کند.

لینک‌های عمیق می‌توانند با URI، اقدامات هدفمند و انواع MIME مطابقت داده شوند. می‌توانید چندین نوع مطابقت را برای یک لینک عمیق مشخص کنید، اما توجه داشته باشید که تطبیق آرگومان URI ابتدا اولویت‌بندی می‌شود، پس از آن عمل و سپس نوع MIME.

نمودارهای برنامه‌ریزی‌شده

اگر گراف ناوبری خود را به صورت برنامه‌نویسی‌شده تعریف کنید (با استفاده از Navigation Compose یا Kotlin DSL)، لینک‌های عمیق را در کد تعریف می‌کنید.

نوشتن

در Navigation Compose، می‌توانید با استفاده از پارامتر deepLinks لینک‌های عمیق را به عنوان بخشی از سازنده مقصد composable() تعریف کنید. این سازنده لیستی از اشیاء 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)
}

کاتلین DSL

هنگام استفاده از Kotlin DSL، می‌توانید لینک‌های عمیق را با استفاده از تابع سازنده‌ی deepLink() در بلوک مقصد تعریف کنید:

@Serializable
data class Profile(val id: String)

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

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

فیلترهای هدف را برای نمودارهای برنامه نویسی اضافه کنید

از آنجا که گراف‌های ناوبری برنامه‌نویسی‌شده در زمان اجرا ساخته می‌شوند، کامپوننت ناوبری نمی‌تواند به‌طور خودکار عناصر <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 تعریف کنید یا از ویرایشگر ناوبری (Navigation Editor) استفاده کنید.

در اینجا یک مثال از لینک عمیق که شامل یک 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. در بخش Deep Links از پنل Attributes روی + کلیک کنید.
  3. در پنجره‌ی «افزودن پیوند عمیق» که ظاهر می‌شود، اطلاعات پیوند عمیق خود را وارد کنید.

    به موارد زیر توجه کنید:

    • آدرس‌های اینترنتی (URI) بدون طرحواره (schema) به عنوان http یا https در نظر گرفته می‌شوند. برای مثال، www.google.com با هر دو http://www.google.com و https://www.google.com مطابقت دارد.
    • متغیرهای پارامتر مسیر به شکل {placeholder_name} با یک یا چند کاراکتر مطابقت دارند. برای مثال، http://www.example.com/users/{id} با http://www.example.com/users/4 مطابقت دارد. کامپوننت Navigation تلاش می‌کند تا مقادیر متغیرهای ورودی را با تطبیق نام‌های متغیرهای ورودی با آرگومان‌های تعریف‌شده‌ای که برای مقصد لینک عمیق تعریف شده‌اند، به انواع مناسب تجزیه کند. اگر هیچ آرگومانی با نام یکسان تعریف نشده باشد، از نوع پیش‌فرض String برای مقدار آرگومان استفاده می‌شود. می‌توانید از کاراکتر .* برای مطابقت با 0 یا بیشتر کاراکتر استفاده کنید.
    • می‌توان از متغیرهای پارامتر پرس‌وجو به جای یا همراه با پارامترهای مسیر استفاده کرد. برای مثال، http://www.example.com/users/{id}?myarg={myarg} با http://www.example.com/users/4?myarg=28 مطابقت دارد.
    • لازم نیست متغیرهای تعریف‌شده با مقادیر پیش‌فرض یا nullable با متغیرهای جایگذاری‌شده در پارامتر کوئری مطابقت داشته باشند. برای مثال، 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 با الگوی بالا مطابقت ندارد زیرا پارامتر مسیر مورد نیاز ارائه نشده است.
    • پارامترهای پرس‌وجوی خارجی تاثیری بر تطبیق URL لینک عمیق ندارند. برای مثال، http://www.example.com/users/{id} با http://www.example.com/users/4?extraneousParam=7 مطابقت دارد، حتی اگر extraneousParam در الگوی URI تعریف نشده باشد.
  4. (اختیاری) برای اینکه گوگل از شما بخواهد مالک URI را تأیید کنید، گزینه تأیید خودکار (Auto Verify) را علامت بزنید. برای اطلاعات بیشتر، به بخش تأیید پیوندهای برنامه اندروید مراجعه کنید.

  5. روی افزودن کلیک کنید. یک نماد پیوند بالای مقصد انتخاب شده ظاهر می‌شود تا نشان دهد که آن مقصد یک پیوند عمیق دارد.

  6. برای نمایش XML روی تب Code کلیک کنید. یک عنصر <deepLink> تو در تو به مقصد اضافه شده است:

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

برای فعال کردن پیوند عمیق ضمنی برای نمودارهای مبتنی بر XML، باید موارد دیگری را نیز به فایل manifest.xml برنامه خود اضافه کنید. یک عنصر <nav-graph> را به یک activity اضافه کنید که به یک نمودار ناوبری موجود اشاره می‌کند، همانطور که در مثال زیر نشان داده شده است:

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

هنگام ساخت پروژه، کامپوننت Navigation عنصر <nav-graph> را با عناصر تولید شده <intent-filter> جایگزین می‌کند تا با تمام لینک‌های عمیق در گراف ناوبری مطابقت داشته باشد.

پیوندهای عمیق ضمنی و پشته پشتی

هنگام فعال‌سازی یک پیوند عمیق ضمنی، وضعیت پشته پشتی به این بستگی دارد که آیا Intent ضمنی با پرچم Intent.FLAG_ACTIVITY_NEW_TASK راه‌اندازی شده است یا خیر:

  • اگر این پرچم تنظیم شود، پشته بازگشت وظیفه پاک شده و با مقصد پیوند عمیق جایگزین می‌شود. همانند پیوند عمیق صریح ، هنگام تودرتو کردن نمودارها ، مقصد شروع از هر سطح تودرتو - یعنی مقصد شروع از هر عنصر <navigation> در سلسله مراتب - نیز به پشته اضافه می‌شود. این بدان معناست که وقتی کاربر دکمه بازگشت را از یک مقصد پیوند عمیق فشار می‌دهد، درست مانند زمانی که از نقطه ورود به برنامه شما وارد شده است، در پشته ناوبری به عقب برمی‌گردد.
  • اگر این پرچم تنظیم نشده باشد، شما در پشته وظایف برنامه قبلی که لینک عمیق ضمنی در آن فعال شده بود، باقی می‌مانید. در این حالت، دکمه بازگشت شما را به برنامه قبلی برمی‌گرداند، در حالی که دکمه بالا، وظیفه برنامه شما را در مقصد سلسله مراتبی والد در نمودار ناوبری شما آغاز می‌کند.

مدیریت لینک‌های عمیق

اکیداً توصیه می‌شود هنگام استفاده از Navigation، همیشه از launchMode پیش‌فرض standard استفاده کنید. هنگام استفاده از حالت راه‌اندازی standard ، Navigation به طور خودکار با فراخوانی handleDeepLink() پیوندهای عمیق را برای پردازش هرگونه پیوند عمیق صریح یا ضمنی درون Intent مدیریت می‌کند. با این حال، اگر Activity هنگام استفاده از launchMode جایگزین مانند singleTop دوباره استفاده شود، این اتفاق به طور خودکار رخ نمی‌دهد. در این حالت، لازم است handleDeepLink() به صورت دستی در onNewIntent() فراخوانی کنید، همانطور که در مثال زیر نشان داده شده است:

کاتلین

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

جاوا

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