التحقّق من روابط التطبيقات

عندما تكون السمة android:autoVerify="true" متوفّرة في فلتر واحد على الأقل من فلاتر الأهداف في تطبيقك، يؤدي تثبيت تطبيقك على جهاز يعمل بالإصدار 6.0 من نظام التشغيل Android (مستوى واجهة برمجة التطبيقات 23) أو الإصدارات الأحدث إلى أن يتحقّق النظام تلقائيًا من المضيفين المرتبطين بعناوين URL في فلاتر الأهداف في تطبيقك. على نظام التشغيل Android 12 والإصدارات الأحدث، يمكنك أيضًا بدء عملية التحقّق يدويًا لاختبار منطق التحقّق.

التحقّق التلقائي

تتضمّن عملية التحقّق التلقائي من النظام ما يلي:

  1. يفحص النظام جميع فلاتر الأهداف التي تتضمّن أيًا مما يلي:
    • الإجراء: android.intent.action.VIEW
    • الفئات: android.intent.category.BROWSABLE وandroid.intent.category.DEFAULT
    • مخطط البيانات: http أو https
  2. بالنسبة إلى كل اسم مضيف فريد تم العثور عليه في intent filter أعلاه، يطلب نظام التشغيل Android ملف روابط تنقل إلى مواد عرض رقمية من المواقع الإلكترونية المقابلة على https:///.well-known/assetlinks.json.

بعد تأكيد قائمة المواقع الإلكترونية التي تريد ربطها بتطبيقك، وبعد التأكّد من أنّ ملف JSON المستضاف صالح، ثبِّت التطبيق على جهازك. انتظِر لمدة 20 ثانية على الأقل كي تكتمل عملية إثبات الهوية غير المتزامنة. استخدِم الأمر التالي للتحقّق مما إذا كان النظام قد تحقّق من تطبيقك وضبط سياسات معالجة الروابط الصحيحة:

adb shell am start -a android.intent.action.VIEW \
    -c android.intent.category.BROWSABLE \
    -d "http://domain.name:optional_port"

التأكيد يدويًا

بدءًا من Android 12، يمكنك تفعيل عملية إثبات ملكية النطاق يدويًا لتطبيق مثبَّت على جهاز. يمكنك تنفيذ هذه العملية بغض النظر عمّا إذا كان تطبيقك يستهدف الإصدار 12 من نظام التشغيل Android.

الاتصال بالإنترنت

لإجراء عملية إثبات ملكية النطاق، يجب أن يكون جهاز الاختبار متصلاً بالإنترنت.

إتاحة عملية إثبات ملكية النطاق المعدَّلة

إذا كان تطبيقك يستهدف الإصدار 12 من نظام التشغيل Android أو الإصدارات الأحدث، سيستخدم النظام تلقائيًا عملية إثبات ملكية النطاق المعدَّلة.

ويمكنك بدلاً من ذلك تفعيل عملية التأكيد المعدَّلة يدويًا. لإجراء ذلك، نفِّذ الأمر التالي في نافذة الوحدة الطرفية:

adb shell am compat enable 175408749 PACKAGE_NAME

إعادة ضبط حالة "روابط تطبيقات Android" على جهاز

قبل تفعيل عملية تأكيد النطاق يدويًا على أحد الأجهزة، يجب إعادة ضبط حالة "روابط تطبيقات Android" على جهاز الاختبار. لإجراء ذلك، نفِّذ الأمر التالي في نافذة الوحدة الطرفية:

adb shell pm set-app-links --package PACKAGE_NAME 0 all

يضع هذا الأمر الجهاز في الحالة نفسها التي كان عليها قبل أن يختار المستخدم التطبيقات التلقائية لأي نطاقات.

استدعاء عملية تأكيد النطاق

بعد إعادة ضبط حالة "روابط تطبيقات Android" على أحد الأجهزة، يمكنك إجراء عملية التحقّق نفسها. لإجراء ذلك، نفِّذ الأمر التالي في نافذة الوحدة الطرفية:

adb shell pm verify-app-links --re-verify PACKAGE_NAME

مراجعة نتائج عملية التحقّق

بعد السماح لوكيل التحقّق بإنهاء طلباته، راجِع نتائج التحقّق. لإجراء ذلك، شغِّل الأمر التالي:

adb shell pm get-app-links PACKAGE_NAME

يكون ناتج هذا الأمر مشابهًا لما يلي:

com.example.pkg:
    ID: 01234567-89ab-cdef-0123-456789abcdef
    Signatures: [***]
    Domain verification state:
      example.com: verified
      sub.example.com: legacy_failure
      example.net: verified
      example.org: 1026

النطاقات التي تجتاز عملية إثبات الملكية بنجاح يكون لها حالة إثبات ملكية نطاق verified. تشير أي حالة أخرى إلى أنّه تعذّر إثبات ملكية النطاق. على وجه الخصوص، تشير الحالة none إلى أنّ وكيل التحقّق ربما لم يكمل عملية التحقّق بعد.

تعرض القائمة التالية قيم العائد المحتملة التي يمكن أن تعرضها عملية إثبات ملكية النطاق لنطاق معيّن:

none
لم يتم تسجيل أي شيء لهذا النطاق. انتظِر بضع دقائق إضافية إلى أن ينتهي وكيل التأكيد من الطلبات المتعلقة بتأكيد النطاق، ثم ابدأ عملية تأكيد النطاق مرة أخرى.
verified
تم إثبات ملكية النطاق بنجاح للتطبيق المعلِن.
approved
تمت الموافقة على النطاق بشكل إلزامي، وعادةً ما يتم ذلك من خلال تنفيذ أمر shell.
denied
تم رفض النطاق بشكل إجباري، وعادةً ما يتم ذلك من خلال تنفيذ أمر shell.
migrated
احتفظ النظام بنتيجة عملية سابقة استخدمت طريقة قديمة لإثبات ملكية النطاق.
restored
تمت الموافقة على النطاق بعد أن نفّذ المستخدم عملية استعادة البيانات. يُفترض أنّه تم إثبات ملكية النطاق من قبل.
legacy_failure
رفضت أداة التحقّق القديمة النطاق. سبب تعذّر النقل غير معروف.
system_configured
تمت الموافقة على النطاق تلقائيًا من خلال إعدادات الجهاز.
رمز الخطأ 1024 أو أكبر

رمز خطأ مخصّص خاص بأداة التحقّق من الجهاز.

يُرجى التأكّد من إنشاء اتصال بالشبكة وبدء عملية إثبات ملكية النطاق مرة أخرى.

أن تطلب من المستخدم ربط تطبيقك بنطاق

هناك طريقة أخرى للموافقة على تطبيقك لاستخدام نطاق معيّن، وهي أن تطلب من المستخدم ربط تطبيقك بهذا النطاق.

التحقّق مما إذا تمت الموافقة على تطبيقك من قبل للنطاق

قبل أن تطلب من المستخدم ذلك، تحقَّق مما إذا كان تطبيقك هو المعالج التلقائي للنطاقات التي تحدّدها في عناصر <intent-filter>. يمكنك طلب حالة الموافقة باستخدام إحدى الطرق التالية:

DomainVerificationManager

يوضّح مقتطف الرمز التالي كيفية استخدام واجهة برمجة التطبيقات DomainVerificationManager:

Kotlin

val context: Context = TODO("Your activity or fragment's Context")
val manager = context.getSystemService(DomainVerificationManager::class.java)
val userState = manager.getDomainVerificationUserState(context.packageName)

// Domains that have passed Android App Links verification.
val verifiedDomains = userState?.hostToStateMap
    ?.filterValues { it == DomainVerificationUserState.DOMAIN_STATE_VERIFIED }

// Domains that haven't passed Android App Links verification but that the user
// has associated with an app.
val selectedDomains = userState?.hostToStateMap
    ?.filterValues { it == DomainVerificationUserState.DOMAIN_STATE_SELECTED }

// All other domains.
val unapprovedDomains = userState?.hostToStateMap
    ?.filterValues { it == DomainVerificationUserState.DOMAIN_STATE_NONE }

Java

Context context = TODO("Your activity or fragment's Context");
DomainVerificationManager manager =
        context.getSystemService(DomainVerificationManager.class);
DomainVerificationUserState userState =
        manager.getDomainVerificationUserState(context.getPackageName());

Map<String, Integer> hostToStateMap = userState.getHostToStateMap();
List<String> verifiedDomains = new ArrayList<>();
List<String> selectedDomains = new ArrayList<>();
List<String> unapprovedDomains = new ArrayList<>();
for (String key : hostToStateMap.keySet()) {
    Integer stateValue = hostToStateMap.get(key);
    if (stateValue == DomainVerificationUserState.DOMAIN_STATE_VERIFIED) {
        // Domain has passed Android App Links verification.
        verifiedDomains.add(key);
    } else if (stateValue == DomainVerificationUserState.DOMAIN_STATE_SELECTED) {
        // Domain hasn't passed Android App Links verification, but the user has
        // associated it with an app.
        selectedDomains.add(key);
    } else {
        // All other domains.
        unapprovedDomains.add(key);
    }
}

برنامج سطر الأوامر

عند اختبار تطبيقك أثناء عملية التطوير، يمكنك تنفيذ الأمر التالي للاستعلام عن حالة التحقّق من النطاقات التي تملكها مؤسستك:

adb shell pm get-app-links --user cur PACKAGE_NAME

في المثال التالي، على الرغم من تعذُّر إثبات ملكية التطبيق للنطاق "example.org"، وافق المستخدم 0 يدويًا على التطبيق في إعدادات النظام، ولم يتم إثبات ملكية أي حزمة أخرى لهذا النطاق.

com.example.pkg:
ID: ***
Signatures: [***]
Domain verification state:
  example.com: verified
  example.net: verified
  example.org: 1026
User 0:
  Verification link handling allowed: true
  Selection state:
    Enabled:
      example.org
    Disabled:
      example.com
      example.net

يمكنك أيضًا استخدام أوامر shell لمحاكاة العملية التي يختار فيها المستخدم التطبيق المرتبط بنطاق معيّن. يمكنك الاطّلاع على شرح كامل لهذه الأوامر من خلال ناتج adb shell pm.

توفير سياق للطلب

قبل تقديم طلب الموافقة على النطاق، قدِّم بعض المعلومات الأساسية للمستخدم. على سبيل المثال، يمكنك عرض شاشة البداية أو مربّع حوار أو عنصر في واجهة المستخدم يشرح للمستخدم سبب وجوب أن يكون تطبيقك هو المعالج التلقائي لنطاق معيّن.

تقديم الطلب

بعد أن يفهم المستخدم ما يطلبه منه تطبيقك، قدِّم الطلب. لإجراء ذلك، استدعِ intent تتضمّن ACTION_APP_OPEN_BY_DEFAULT_SETTINGS intent action وسلسلة بيانات تطابق package:com.example.pkg للتطبيق المستهدف، كما هو موضّح في مقتطف الرمز التالي:

Kotlin

val context: Context = TODO("Your activity or fragment's Context")
val intent = Intent(Settings.ACTION_APP_OPEN_BY_DEFAULT_SETTINGS,
    Uri.parse("package:${context.packageName}"))
context.startActivity(intent)

Java

Context context = TODO("Your activity or fragment's Context");
Intent intent = new Intent(Settings.ACTION_APP_OPEN_BY_DEFAULT_SETTINGS,
    Uri.parse("package:" + context.getPackageName()));
context.startActivity(intent);

عندما يتم استدعاء الغرض، تظهر للمستخدمين شاشة إعدادات باسم الفتح تلقائيًا. تحتوي هذه الشاشة على زر اختيار باسم فتح الروابط المتوافقة، كما هو موضّح في الشكل 1.

عندما يفعّل المستخدم خيار فتح الروابط المتوافقة، تظهر مجموعة من مربّعات الاختيار ضمن قسم باسم الروابط التي سيتم فتحها في هذا التطبيق. ومن هنا، يمكن للمستخدمين اختيار النطاقات التي يريدون ربطها بتطبيقك. ويمكنهم أيضًا النقر على إضافة رابط لإضافة نطاقات، كما هو موضّح في الشكل 2. وعندما يختار المستخدمون لاحقًا أي رابط ضمن النطاقات التي يضيفونها، سيتم فتح الرابط في تطبيقك تلقائيًا.

عند تفعيل زر الاختيار، سيظهر قسم بالقرب من أسفل الصفحة يتضمّن مربّعات اختيار بالإضافة إلى زر باسم &quot;إضافة رابط&quot;.
الشكل 1. شاشة إعدادات النظام التي يمكن للمستخدمين من خلالها اختيار الروابط التي يتم فتحها في تطبيقك تلقائيًا
يمثّل كل مربّع اختيار نطاقًا يمكنك إضافته. يحتوي مربّع الحوار على الزرَّين &quot;إلغاء&quot; و&quot;إضافة&quot;.
الشكل 2. مربّع حوار يمكن للمستخدمين من خلاله اختيار نطاقات إضافية لربطها بتطبيقك.

نطاقات مفتوحة في تطبيقك لا يمكن لتطبيقك التحقّق منها

قد تكون الوظيفة الرئيسية لتطبيقك هي فتح الروابط كجهة خارجية بدون إمكانية التحقّق من النطاقات التي يتعامل معها. في هذه الحالة، عليك توضيح للمستخدمين أنّه عند النقر على رابط ويب، لن يتمكّنوا من الاختيار بين تطبيق تابع للجهة الأولى وتطبيقك (التابع لجهة خارجية)، بل عليهم ربط النطاقات بتطبيقك التابع لجهة خارجية يدويًا.

بالإضافة إلى ذلك، ننصحك بعرض مربّع حوار أو نشاط "القفز" يتيح للمستخدم فتح الرابط في تطبيق الطرف الأول إذا كان يفضّل ذلك، ما يجعله يعمل كخادم وكيل. قبل إعداد مربّع حوار أو نشاط ترامبولين، عليك إعداد تطبيقك لكي يتمتّع بإذن الوصول إلى حزمة تطبيقات الطرف الأول التي تتطابق مع فلتر الأهداف على الويب في تطبيقك.

مدة تأخُّر تحديث روابط التنقل إلى مواد العرض الرقمية

عند تعديل ملف assetlinks.json على خادم الويب، يعتمد الوقت الذي يستغرقه ظهور هذه التغييرات على أجهزة المستخدمين النهائيين على إصدار نظام التشغيل:

  • ‫Android 15 (المستوى 35 لواجهة برمجة التطبيقات) والإصدارات الأحدث: يتحقّق النظام بشكل دوري من صحة النطاقات في الخلفية. قد يستغرق نشر التغييرات لجميع أجهزة المستخدمين النهائيين ما يصل إلى سبعة أيام بسبب التخزين المؤقت وإعادة التحقّق المجدوَلة في النظام.
  • الإصدار 14 من نظام التشغيل Android (المستوى 34 لواجهة برمجة التطبيقات) والإصدارات الأقدم: لا يجري النظام عملية إعادة تحقّق دورية في الخلفية. لا يتم عادةً رصد التعديلات التي يتم إجراؤها على الملف إلا عند تثبيت التطبيق أو تحديثه.

آخر الأخبار حول الاختبارات

لفرض إعادة التحقّق على جهاز معيّن أثناء الاختبار، يمكنك إلغاء تثبيت التطبيق وإعادة تثبيته. ومع ذلك، يُرجى العِلم أنّ ذاكرات التخزين المؤقت من جهة الخادم قد تؤخّر وصول ملف assetlinks.json المعدَّل إلى الجهاز، حتى بعد إعادة التثبيت. بما أنّ ذاكرة التخزين المؤقت تستند إلى الوقت، يتم عادةً حل التأخير تلقائيًا إذا أعدت المحاولة بعد بضع ساعات.