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

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

إثبات الملكية تلقائيًا

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

  1. يفحص النظام جميع فلاتر الأهداف التي تتضمّن أيًا مما يلي:
    • الإجراء: android.intent.action.VIEW
    • الفئات: android.intent.category.BROWSABLE وandroid.intent.category.DEFAULT
    • مخطط البيانات: http أو https
  2. لكل اسم مضيف فريد يتم العثور عليه في فلاتر الأهداف، يرسل Android طلبات بحث إلى المواقع الإلكترونية المقابلة للحصول على ملف روابط التنقل إلى مواد العرض الرقمية على الرابط https://hostname/.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"

تأكيد النطاق يدويًا

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

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

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

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

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

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

adb shell am compat enable 175408749 PACKAGE_NAME

إعادة ضبط حالة Android App Links على جهاز معيّن

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

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

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

استدعاء عملية إثبات ملكية النطاق

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

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

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

تقديم سياق للطلب

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

تقديم الطلب

بعد أن يفهم المستخدم ما يطلبه تطبيقك منه، يمكنك تقديم الطلب. لإجراء ذلك، يمكنك استدعاء intent يتضمّن إجراء intent‏ ACTION_APP_OPEN_BY_DEFAULT_SETTINGS وسلسلة بيانات تتطابق مع 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 من واجهة برمجة التطبيقات) والإصدارات الأحدث: يعيد النظام التحقّق من النطاقات بشكل دوري في الخلفية. قد يستغرق نشر التغييرات على جميع أجهزة المستخدمين النهائيين مدة تصل إلى سبعة أيام بسبب التخزين المؤقت للنظام وإعادة التحقّق المُجدوَلة.
  • الإصدار Android 14 (المستوى 34 من واجهة برمجة التطبيقات) والإصدارات الأقدم: لا يُجري النظام عملية إعادة التحقّق في الخلفية بشكل دوري. لا يتم عادةً رصد التعديلات على الملف إلا عند تثبيت التطبيق أو تحديثه.

تحديثات الاختبار

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