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

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

لإثبات ملكيتك لكلّ من عناوين URL لتطبيقك ولموقعك الإلكتروني، أكمِل الخطوات التالية:

  1. أضِف فلاتر الأهداف التي تحتوي على السمة autoVerify. وتُرسِل هذه السمة إشارة إلى النظام بأنّه يجب أن يتحقّق مما إذا كان تطبيقك ينتمي إلى نطاقات عناوين URL المستخدَمة في فلاتر الأهداف.

  2. وضِّح الرابط بين موقعك الإلكتروني وفلاتر الأهداف من خلال استضافة ملف روابط التنقل إلى مواد العرض الرقمية بتنسيق JSON في المكان التالي:

    https://domain.name/.well-known/assetlinks.json

يمكنك الاطّلاع على المعلومات ذات الصلة في المراجع التالية:

إضافة فلاتر الأهداف للتحقّق من روابط التطبيقات

لتفعيل ميزة التحقّق من معالجة الروابط في تطبيقك، أضِف فلاتر أهداف تتطابق مع التنسيق التالي:

<!-- Make sure you explicitly set android:autoVerify to "true". -->
<intent-filter android:autoVerify="true">
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.DEFAULT" />
    <category android:name="android.intent.category.BROWSABLE" />

    <!-- If a user clicks on a shared link that uses the "http" scheme, your
         app should be able to delegate that traffic to "https". -->
    <data android:scheme="http" />
    <data android:scheme="https" />

    <!-- Include one or more domains that should be verified. -->
    <data android:host="..." />
</intent-filter>

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

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

إتاحة ربط التطبيقات لمضيفين متعددين

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

ملاحظة: في نظام التشغيل Android 11 (المستوى 30 لواجهة برمجة التطبيقات) والإصدارات الأقدم، لا يتحقّق النظام من تطبيقك كمعالج تلقائي ما لم يعثر على ملف "روابط إلى مواد عرض رقمية" مطابق لجميع المضيفين الذين تحدّدهم في البيان.

على سبيل المثال، لن يجتاز تطبيق يتضمّن فلاتر الأهداف التالية عملية التحقّق إلا لـ https://www.example.com فقط إذا تم العثور على ملف assetlinks.json على https://www.example.com/.well-known/assetlinks.json وليس على https://www.example.net/.well-known/assetlinks.json:

<application>

  <activity android:name=”MainActivity”>
    <intent-filter android:autoVerify="true">
      <action android:name="android.intent.action.VIEW" />
      <category android:name="android.intent.category.DEFAULT" />
      <category android:name="android.intent.category.BROWSABLE" />
      <data android:scheme="http" />
      <data android:scheme="https" />
      <data android:host="www.example.com" />
    </intent-filter>
  </activity>
  <activity android:name=”SecondActivity”>
    <intent-filter>
      <action android:name="android.intent.action.VIEW" />
      <category android:name="android.intent.category.DEFAULT" />
      <category android:name="android.intent.category.BROWSABLE" />
      <data android:scheme="https" />
     <data android:host="www.example.net" />
    </intent-filter>
  </activity>

</application>

ملاحظة: يتم دمج كل عناصر <data> في فلتر الأهداف نفسه معًا لاحتساب جميع صيغ سماتها المجمّعة. على سبيل المثال، يتضمّن فلتر الأهداف الأول أعلاه عنصر <data> الذي يعلن عن مخطط HTTPS فقط. ويتم دمجه مع العنصر <data> الآخر كي يتيح فلتر الأهداف استخدام السمتَين http://www.example.com وhttps://www.example.com. وعلى هذا النحو، يجب إنشاء فلاتر أهداف منفصلة عندما تريد تحديد مجموعات معيّنة من مخططات ونطاقات معرف الموارد المنتظم (URI).

إتاحة ربط التطبيقات لنطاقات فرعية متعددة

يتعامل بروتوكول "روابط مواد العرض الرقمية" مع النطاقات الفرعية في فلاتر الأهداف على أنّها مضيفات فريدة ومنفصلة. وبالتالي، إذا كان فلتر الأهداف يسرد عدة مضيفين لديهم نطاقات فرعية مختلفة، عليك نشر سمة assetlinks.json صالحة في كل نطاق. على سبيل المثال، يتضمّن فلتر الأهداف التالي www.example.com وmobile.example.com كمضيفين لعناوين URL حسب النية بالشراء. وبالتالي، يجب نشر سمة assetlinks.json صالحة على كلّ من https://www.example.com/.well-known/assetlinks.json وhttps://mobile.example.com/.well-known/assetlinks.json.

<application>
  <activity android:name=”MainActivity”>
    <intent-filter android:autoVerify="true">
      <action android:name="android.intent.action.VIEW" />
      <category android:name="android.intent.category.DEFAULT" />
      <category android:name="android.intent.category.BROWSABLE" />
      <data android:scheme="https" />
      <data android:scheme="https" />
      <data android:host="www.example.com" />
      <data android:host="mobile.example.com" />
    </intent-filter>
  </activity>
</application>

وبدلاً من ذلك، إذا أعلنت عن اسم المضيف باستخدام حرف بدل (مثل *.example.com)، عليك نشر ملف assetlinks.json على اسم المضيف الجذر (example.com). على سبيل المثال، سيجتاز تطبيق يتضمّن فلتر الأهداف التالي عملية إثبات الهوية لأي اسم فرعي من example.com (مثل foo.example.com) طالما تم نشر ملف assetlinks.json على https://example.com/.well-known/assetlinks.json:

<application>
  <activity android:name=”MainActivity”>
    <intent-filter android:autoVerify="true">
      <action android:name="android.intent.action.VIEW" />
      <category android:name="android.intent.category.DEFAULT" />
      <category android:name="android.intent.category.BROWSABLE" />
      <data android:scheme="https" />
      <data android:host="*.example.com" />
    </intent-filter>
  </activity>
</application>

التحقُّق من وجود تطبيقات متعددة مرتبطة بالنطاق نفسه

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

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

الإعلان عن عمليات ربط المواقع الإلكترونية

يجب نشر ملف روابط التنقل إلى مواد العرض الرقمية بتنسيق JSON على موقعك الإلكتروني للإشارة إلى تطبيقات Android المرتبطة بالموقع الإلكتروني والتحقّق من أهداف عناوين URL للتطبيق. يستخدم ملف JSON الحقول التالية لتحديد التطبيقات المرتبطة:

  • package_name: رقم تعريف التطبيق الوارد في ملف build.gradle الخاص بالتطبيق
  • sha256_cert_fingerprints: الملفات المرجعية لشهادة SHA256 لشهادة توقيع تطبيقك. يمكنك استخدام الأمر التالي لإنشاء بصمة الإصبع من خلال أداة مفاتيح Java:
    keytool -list -v -keystore my-release-key.keystore
    
    يتيح هذا الحقل استخدام بصمات أصابع متعددة يمكن استخدامها في التوافق مع إصدارات مختلفة من تطبيقك، مثل إصدارات تصحيح الأخطاء والإنتاج.

    إذا كنت تستخدم ميزة توقيع التطبيق من Play لتطبيقك، لن تتطابق عادةً الملف المرجعي للشهادة الذي تم إنشاؤه عن طريق تشغيل keytool محليًا مع الملف المرجعي على أجهزة المستخدمين. يمكنك التأكد ممّا إذا كنت تستخدم ميزة "توقيع التطبيق" من Play لتطبيقك من خلال حساب المطوّر على Play Console ضمن Release > Setup > App signing. وفي حال إجراء ذلك، يمكنك أيضًا العثور على مقتطف JSON الصحيح لتطبيقك على الصفحة نفسها.

يمنح المثال التالي ملف assetlinks.json حقوق فتح الروابط لتطبيق com.example المتوافق مع Android:

[{
  "relation": ["delegate_permission/common.handle_all_urls"],
  "target": {
    "namespace": "android_app",
    "package_name": "com.example",
    "sha256_cert_fingerprints":
    ["14:6D:E9:83:C5:73:06:50:D8:EE:B9:95:2F:34:FC:64:16:A0:83:42:E6:1D:BE:A8:8A:04:96:B2:3F:CF:44:E5"]
  }
}]

ربط موقع ويب بتطبيقات متعددة

يمكن للموقع الإلكتروني الإعلان عن عمليات ربط بتطبيقات متعددة ضمن ملف assetlinks.json نفسه. تعرض بطاقة بيانات الملف التالية مثالاً على ملف بيان يُعلن عن ربطه بتطبيقَين، بشكل منفصل، ويوجد في https://www.example.com/.well-known/assetlinks.json:

[{
  "relation": ["delegate_permission/common.handle_all_urls"],
  "target": {
    "namespace": "android_app",
    "package_name": "com.example.puppies.app",
    "sha256_cert_fingerprints":
    ["14:6D:E9:83:C5:73:06:50:D8:EE:B9:95:2F:34:FC:64:16:A0:83:42:E6:1D:BE:A8:8A:04:96:B2:3F:CF:44:E5"]
  }
  },
  {
  "relation": ["delegate_permission/common.handle_all_urls"],
  "target": {
    "namespace": "android_app",
    "package_name": "com.example.monkeys.app",
    "sha256_cert_fingerprints":
    ["14:6D:E9:83:C5:73:06:50:D8:EE:B9:95:2F:34:FC:64:16:A0:83:42:E6:1D:BE:A8:8A:04:96:B2:3F:CF:44:E5"]
  }
}]

قد تتعامل التطبيقات المختلفة مع الروابط الخاصة بموارد مختلفة ضمن مضيف الويب نفسه. على سبيل المثال، قد يذكر التطبيق 1 فلتر أهداف للسمة https://example.com/articles، في حين قد يذكر التطبيق 2 فلتر أهداف للسمة https://example.com/videos.

ملاحظة:قد يتم توقيع التطبيقات المتعددة المرتبطة بنطاق معيّن باستخدام الشهادات نفسها أو شهادات مختلفة.

ربط عدة مواقع إلكترونية بتطبيق واحد

يمكن للمواقع الإلكترونية المتعددة أن تذكر عمليات ربط بالتطبيق نفسه في ملفات assetlinks.json الخاصة بها. تعرض بطاقات بيانات الملفات التالية مثالاً على كيفية الإعلان عن ربط example.com وexample.net مع app1. تعرض بطاقة البيانات الأولى عملية ربط example.com بالتطبيق 1:

https://www.example.com/.well-known/assetlinks.json

[{
  "relation": ["delegate_permission/common.handle_all_urls"],
  "target": {
    "namespace": "android_app",
    "package_name": "com.mycompany.app1",
    "sha256_cert_fingerprints":
    ["14:6D:E9:83:C5:73:06:50:D8:EE:B9:95:2F:34:FC:64:16:A0:83:42:E6:1D:BE:A8:8A:04:96:B2:3F:CF:44:E5"]
  }
}]

تعرض القائمة التالية ارتباط example.net مع app1. لا يختلف سوى الموقع الذي تتم فيه استضافة هذه الملفات (.com و.net):

https://www.example.net/.well-known/assetlinks.json

[{
  "relation": ["delegate_permission/common.handle_all_urls"],
  "target": {
    "namespace": "android_app",
    "package_name": "com.mycompany.app1",
    "sha256_cert_fingerprints":
    ["14:6D:E9:83:C5:73:06:50:D8:EE:B9:95:2F:34:FC:64:16:A0:83:42:E6:1D:BE:A8:8A:04:96:B2:3F:CF:44:E5"]
  }
}]

نشر ملف التحقق بتنسيق JSON

يجب نشر ملف إثبات الملكية بتنسيق JSON في الموقع التالي:

https://domain.name/.well-known/assetlinks.json

تأكد مما يلي:

  • يتم عرض ملف assetlinks.json مع application/json من نوع المحتوى.
  • يجب أن تتوفّر إمكانية الوصول إلى ملف assetlinks.json من خلال اتصال HTTPS، بغض النظر عمّا إذا كانت فلاتر الأهداف في تطبيقك تحدِّد HTTPS كمخطط للبيانات.
  • يجب أن يكون الوصول إلى ملف assetlinks.json متاحًا بدون أي عمليات إعادة توجيه (لا يمكن إعادة توجيه 301 أو 302).
  • إذا كانت روابط تطبيقك تتيح استخدام عدة نطاقات مضيف، يجب نشر ملف assetlinks.json على كل نطاق. راجع دعم ربط التطبيقات للمضيفين المتعددين.
  • يجب عدم نشر التطبيق مع تضمين عناوين URL لمطوّري أو اختبار في ملف البيان لا يمكن للجميع الوصول إليها (مثل أي عناوين URL لا يمكن الوصول إليها إلا باستخدام شبكة VPN). كحلّ بديل في مثل هذه الحالات، وهو ضبط صِيغ الإصدار لإنشاء ملف بيان مختلف لإصدارات مطوّري البرامج.

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

عندما يتوفّر 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"

إثبات الملكية اليدوي

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

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

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

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

إذا كان تطبيقك يستهدف الإصدار 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
تمت الموافقة على النطاق من المؤسسة، وعادةً ما يتم ذلك من خلال تنفيذ أمر واجهة أوامر.
denied
تم فرض رفض النطاق، ويتم ذلك عادةً من خلال تنفيذ أمر واجهة أوامر.
migrated
احتفظ النظام بنتيجة عملية سابقة استخدمت فيها عملية إثبات ملكية النطاق القديم.
restored
تمت الموافقة على النطاق بعد أن أجرى المستخدم استعادة للبيانات. كان من المفترض أن يكون النطاق قد سبق إثبات ملكيته.
legacy_failure
تم رفض النطاق من قِبل أداة قديمة لإثبات الملكية. السبب المحدد للفشل غير معروف.
system_configured
تمت الموافقة على النطاق تلقائيًا من خلال إعداد الجهاز.
رمز الخطأ 1024 أو أعلى

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

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

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

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

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

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

  • واجهة برمجة التطبيقات DomainVerificationManager (في وقت التشغيل).
  • برنامج سطر الأوامر (أثناء الاختبار).

إدارة إثبات ملكية النطاق

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

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.

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

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

تقديم الطلب

بعد أن يفهم المستخدم ما يطلب منه تطبيقك، يمكنك تقديم الطلب. ولإجراء ذلك، عليك استدعاء غرض يتضمّن إجراء الهدف 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. مربّع حوار يمكن للمستخدمين من خلاله اختيار نطاقات إضافية لربطها بتطبيقك.

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

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

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

اختبار روابط التطبيقات

عند تنفيذ ميزة ربط التطبيقات، يجب اختبار وظيفة الربط للتأكد من أن النظام يمكنه ربط تطبيقك بمواقعك الإلكترونية، ومن إمكانية التعامل مع طلبات عناوين URL على النحو المتوقَّع.

لاختبار ملف كشف حالي، يمكنك استخدام أداة منشئ وأداة اختبار قوائم العبارات.

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

عند إجراء الاختبار، عليك تأكيد قائمة المضيفات المرتبطة التي يجب أن يتحقّق منها النظام لتطبيقك. ويمكنك إنشاء قائمة بجميع عناوين URL التي تتضمّن فلاتر الأهداف المقابلة لها السمات والعناصر التالية:

  • السمة android:scheme مع القيمة http أو https
  • السمة android:host مع نمط عنوان URL للنطاق
  • عنصر العمل android.intent.action.VIEW
  • عنصر الفئة android.intent.category.BROWSABLE

استخدِم هذه القائمة للتحقق من توفير ملف روابط التنقل إلى مواد العرض الرقمية بتنسيق JSON على كل مضيف واسم نطاق فرعي مُسمّى.

تأكيد ملفات روابط التنقل إلى مواد العرض الرقمية

بالنسبة إلى كل موقع إلكتروني، استخدِم واجهة برمجة التطبيقات Digital Asset Links API للتأكّد من أنّ ملف الروابط التي تنقل إلى مواد العرض الرقمية بتنسيق JSON تتم استضافته وتحديده بشكل سليم:

https://digitalassetlinks.googleapis.com/v1/statements:list?
   source.web.site=https://domain.name:optional_port&
   relation=delegate_permission/common.handle_all_urls

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

adb shell dumpsys package domain-preferred-apps

أو ما يلي يحدث الشيء نفسه:

adb shell dumpsys package d

ملاحظة: يجب الانتظار لمدة 20 ثانية على الأقل بعد تثبيت تطبيقك للسماح للنظام بإكمال عملية إثبات الملكية.

يعرض الأمر قائمة بكل مستخدم أو ملف شخصي تم تحديده على الجهاز، مسبوقًا بعنوان بالتنسيق التالي:

App linkages for user 0:

بعد هذا العنوان، تستخدم النتيجة التنسيق التالي لعرض إعدادات التعامل مع الروابط الخاصة بهذا المستخدم:

Package: com.android.vending
Domains: play.google.com market.android.com
Status: always : 200000002

توضّح بطاقة بيانات المتجر هذه التطبيقات المرتبطة بالنطاقات الخاصة بهذا المستخدم:

  • Package - يحدّد التطبيق من خلال اسم الحزمة، كما هو موضّح في البيان.
  • Domains: يعرض القائمة الكاملة للمضيفين الذين يتعامل معهم هذا التطبيق من خلال روابط الويب، مع استخدام المساحات الفارغة كمحددات.
  • Status: يعرض الإعداد الحالي لمعالجة الروابط لهذا التطبيق. التطبيق الذي اجتاز عملية التحقق ويحتوي على android:autoVerify="true" في بيانه، يعرض حالة always. يرتبط الرقم السداسي العشري بعد هذه الحالة بسجلّ نظام Android للإعدادات المفضّلة لدى المستخدم لربط التطبيقات. لا تشير هذه القيمة إلى ما إذا كانت عملية إثبات الملكية قد تمّت بنجاح.

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

مثال للاختبار

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

<application>

    <activity android:name=”MainActivity”>
        <intent-filter android:autoVerify="true">
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:scheme="https" />
            <data android:scheme="https" />
            <data android:host="www.example.com" />
            <data android:host="mobile.example.com" />
        </intent-filter>
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:scheme="https" />
            <data android:host="www.example2.com" />
        </intent-filter>
    </activity>

    <activity android:name=”SecondActivity”>
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:scheme="https" />
            <data android:host="account.example.com" />
        </intent-filter>
    </activity>

      <activity android:name=”ThirdActivity”>
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.DEFAULT" />
            <data android:scheme="https" />
            <data android:host="map.example.com" />
        </intent-filter>
        <intent-filter>
            <action android:name="android.intent.action.VIEW" />
            <category android:name="android.intent.category.BROWSABLE" />
            <data android:scheme="market" />
            <data android:host="example.com" />
        </intent-filter>
      </activity>

</application>

قائمة المضيفين التي سيحاول النظام الأساسي التحقق منها من خلال البيان أعلاه هي:

www.example.com
mobile.example.com
www.example2.com
account.example.com

قائمة الأجهزة المضيفة التي لن يحاول النظام الأساسي التحقق منها من خلال ملف البيان أعلاه هي:

map.example.com (it does not have android.intent.category.BROWSABLE)
market://example.com (it does not have either an "http" or "https" scheme)

لمزيد من المعلومات حول قوائم العبارات، راجِع إنشاء قائمة كشوفات الحساب.

تصحيح أخطاء التنفيذ الشائعة

إذا لم تتمكن من التحقّق من "روابط تطبيقات Android"، ابحث عن الأخطاء الشائعة التالية. يستخدم هذا القسم example.com كاسم نطاق نائب، وعند إجراء عمليات التحقّق هذه، استبدِل example.com باسم النطاق الفعلي للخادم.

إعداد فلتر أهداف غير صحيح
تحقَّق ممّا إذا كان تطبيقك يتضمّن عنوان URL لا يملكه تطبيقك في عنصر <intent-filter>.
إعدادات الخادم غير صحيحة

تحقق من تهيئة JSON لخادمك، وتأكد من صحة قيمة SHA.

تأكَّد أيضًا من أنّ السمة example.com. (مع الفترة اللاحقة) تعرض المحتوى نفسه الذي يعرضه example.com.

عمليات إعادة التوجيه من جهة الخادم

لا يتحقّق النظام من أي روابط تطبيقات Android لتطبيقك في حال إعداد عملية إعادة توجيه، مثل ما يلي:

  • من ‎http://example.com إلى ‎https://example.com
  • من ‎example.com إلى ‎www.example.com

يحمي هذا السلوك أمان تطبيقك.

متانة الخادم

تحقق مما إذا كان بإمكان الخادم الاتصال بتطبيقات العميل أم لا.

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

لأغراض الاختبار، يمكنك إضافة روابط عن قصد لا يمكن التحقّق منها. يُرجى العِلم أنّ هذه الروابط في نظام التشغيل Android 11 والإصدارات الأقدم تؤدي إلى عدم تحقّق النظام من جميع روابط تطبيقات Android لتطبيقك.

توقيع غير صحيح في assetlinks.json

يُرجى التحقّق من صحة توقيعك ومطابقته مع التوقيع المستخدَم لتوقيع تطبيقك. وتشمل الأخطاء الشائعة ما يلي:

  • توقيع التطبيق باستخدام شهادة تصحيح الأخطاء والحصول على توقيع الإصدار فقط في assetlinks.json.
  • وجود توقيع بأحرف صغيرة في assetlinks.json. يجب أن يكون التوقيع بأحرف كبيرة.
  • إذا كنت تستخدم ميزة "توقيع التطبيق" من Play، يُرجى التأكّد من استخدام التوقيع الذي تستخدمه Google لتوقيع كل إصدار من إصداراتك. يمكنك التحقق من هذه التفاصيل، بما في ذلك مقتطف JSON كامل، من خلال اتّباع التعليمات حول الإعلان عن ارتباطات المواقع الإلكترونية.