در Android، پیوند عمیق پیوندی است که شما را مستقیماً به مقصد خاصی در برنامه میبرد.
میتوانید از دو نوع مختلف پیوند عمیق در برنامهتان پشتیبانی کنید: صریح و
ضمنی. نحوه پیادهسازی پیوندهای عمیق بسته به نوع نموداری که برنامهتان استفاده میکند (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 استفاده کنید،
همانطور که در مثال زیر نشان داده شده است. توجه داشته باشید که اگر بافت ارائهشده
Activity نباشد، سازنده از
PackageManager.getLaunchIntentForPackage()
بهعنوان فعالیت پیشفرض برای راهاندازی استفاده میکند (درصورت دردسترس بودن).
کاتلین
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() پیوند عمیق هم ایجاد کنید.
ایجاد پیوند عمیق ضمنی
پیوند عمیق ضمنی به مقصد خاصی در برنامه اشاره دارد. وقتی پیوند عمیق فراخوانده میشود (مثلاً وقتی کاربر روی پیوندی کلیک میکند)، 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، میتوانید پیوندهای عمیق را بااستفاده از تابع سازنده
deepLink() در بلوک مقصد
تعریف کنید:
@Serializable
data class Profile(val id: String)
val uri = "https://www.example.com"
fragment<ProfileFragment, Profile> {
deepLink<Profile>(basePath = "$uri/profile")
}
افزودن فیلترهای قصد برای نمودارهای برنامهای
ازآنجاییکه نمودارهای ناوبری برنامهای در زمان اجرا ساخته میشوند، مؤلفه Navigation نمیتواند بهطور خودکار عناصر <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>
همچنین میتوانید از «ویرایشگر پیمایش» برای ایجاد پیوند عمیق ضمنی به مقصد بهصورت زیر استفاده کنید:
- در برگه طراحی در «ویرایشگر پیمایش»، مقصد پیوند عمیق را انتخاب کنید.
- روی + در بخش پیوندهای عمیق در پانل مشخصهها کلیک کنید.
در کادر گفتگوی افزودن پیوند عمیق که نشان داده میشود، اطلاعات مربوط به پیوند عمیق را وارد کنید.
به موارد زیر توجه کنید:
- شناسههای منبع یکسان بدون طرحواره بهعنوان
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برای مقدار متغیر مستقل استفاده میشود. میتوانید از نویسه عام .* برای مطابقت با ۰ نویسه یا بیشتر استفاده کنید. - جایبانهای پارامتر پُرسمان را میتوان بهجای پارامترهای مسیر یا همراه با آنها استفاده کرد. برای مثال،
http://www.example.com/users/{id}?myarg={myarg}باhttp://www.example.com/users/4?myarg=28مطابقت دارد. - جایبانهای پارامتر پُرسمان برای متغیرهای تعریفشده با مقادیر پیشفرض یا
مقادیر تهیپذیر لازم نیست مطابقت داشته باشند. برای مثال،
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 تعریف نشده باشد.
- شناسههای منبع یکسان بدون طرحواره بهعنوان
(اختیاری) درستیسنجی خودکار را علامت بزنید تا Google ملزم شود درستیسنجی کند که شما مالک URI هستید. برای اطلاعات بیشتر، به درستیسنجی کردن «پیوندهای برنامه Android» مراجعه کنید.
روی افزودن کلیک کنید. نماد پیوند
در بالای مقصد انتخابشده نشان داده میشود تا نشان دهد آن مقصد دارای
پیوند عمیق است.روی برگه کد کلیک کنید تا به نمای 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> تولیدشده جایگزین میکند تا با همه پیوندهای عمیق در نمودار پیمایش مطابقت داشته باشد.
پیوندهای عمیق ضمنی و پشته قبلیها
هنگام راهاندازی پیوند عمیق ضمنی، وضعیت پشته قبلیها به این بستگی دارد که آیا Intent ضمنی با پرچم Intent.FLAG_ACTIVITY_NEW_TASK راهاندازی شده است یا نه:
- اگر پرچم تنظیم شده باشد، پشته قبلیهای تکلیف پاک میشود و با مقصد پیوند عمیق جایگزین میشود. همانند پیوند عمیق صریح، هنگام
تودرتو کردن نمودارها،
مقصد شروع از هر سطح تودرتو—یعنی مقصد شروع
از هر عنصر
<navigation>در سلسلهمراتب—نیز به پشته اضافه میشود. این یعنی وقتی کاربر دکمه «برگشت» را از مقصد پیوند عمیق فشار میدهد، در پشته پیمایش به عقب پیمایش میکند، درست مثل اینکه از نقطه ورودی برنامه وارد آن شده باشد. - اگر پرچم تنظیم نشده باشد، در پشته تکلیف برنامه قبلی که پیوند عمیق ضمنی در آن راهاندازی شده است باقی میمانید. در این حالت، دکمه «برگشتن» شما را به برنامه قبلی برمیگرداند، درحالیکه دکمه «بالا» تکلیف برنامهتان را در مقصد سلسلهمراتبی والد در نمودار پیمایش شما شروع میکند.
مدیریت پیوندهای عمیق
اکیداً توصیه میشود که همیشه از پیشفرض
launchMode standard
هنگام استفاده از «ناوبری» استفاده کنید. هنگام استفاده از حالت راهاندازی standard، «پیمایش»
بهطور خودکار پیوندهای عمیق را با فراخوانی
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); }