تحسين تطبيقك للتوافق مع ميزة "الملء التلقائي"

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

إعداد بيئة الملء التلقائي

يوضِّح هذا القسم كيفية إعداد الوظائف الأساسية للملء التلقائي لتطبيقك.

إعداد خدمة الملء التلقائي

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

بعد تثبيت خدمة الملء التلقائي للاختبار من نموذج التطبيق، يمكنك تفعيل خدمة الملء التلقائي من خلال الانتقال إلى الإعدادات > النظام > اللغات والإدخال > إعدادات متقدمة > المساعدة بشأن الإدخال > خدمة الملء التلقائي.

لمزيد من المعلومات حول ضبط المحاكي لاختبار ميزة "الملء التلقائي"، يمكنك الاطّلاع على اختبار تطبيقك باستخدام ميزة الملء التلقائي.

تقديم تلميحات للملء التلقائي

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

يمكنك ضبط تلميحات الملء التلقائي باستخدام السمة android:autofillHints. يوضّح المثال التالي تلميح "password" بشأن السمة EditText:

<EditText
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:autofillHints="password" />

يمكنك أيضًا ضبط التلميحات آليًا باستخدام طريقة setAutofillHints() على النحو الموضّح في المثال التالي:

Kotlin

val password = findViewById<EditText>(R.id.password)
password.setAutofillHints(View.AUTOFILL_HINT_PASSWORD)

Java

EditText password = findViewById(R.id.password);
password.setAutofillHints(View.AUTOFILL_HINT_PASSWORD);

تضمين ثوابت التلميح المحدّدة مسبقًا

لا يتحقق إطار الملء التلقائي من صحة التلميحات، بل يتم تمريرها بدون تغيير أو التحقق إلى خدمة الملء التلقائي. وعلى الرغم من أنّه يمكنك استخدام أي قيمة، تحتوي فئتَي View وAndroidX HintConstants على قوائم بثوابت التلميح المعتمَدة رسميًا.

باستخدام مجموعة من هذه الثوابت، يمكنك إنشاء تخطيطات لسيناريوهات الملء التلقائي الشائعة:

بيانات اعتماد الحساب

في نموذج تسجيل الدخول، يمكنك تضمين تلميحات حول بيانات اعتماد الحساب، مثل AUTOFILL_HINT_USERNAME وAUTOFILL_HINT_PASSWORD.

لإنشاء حساب جديد أو عندما يغيّر المستخدمون اسم المستخدم وكلمة المرور، يمكنك استخدام AUTOFILL_HINT_NEW_USERNAME وAUTOFILL_HINT_NEW_PASSWORD.

إنشاء معلومات بطاقة الائتمان

عند طلب معلومات بطاقة ائتمان، يمكنك استخدام تلميحات مثل AUTOFILL_HINT_CREDIT_CARD_NUMBER و AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE.

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

العنوان الجغرافي

بالنسبة إلى حقول نموذج العنوان الفعلي، يمكنك استخدام تلميحات مثل ما يلي:

أسماء الأشخاص

عند طلب أسماء الأشخاص، يمكنك استخدام تلميحات مثل ما يلي:

أرقام الهواتف

بالنسبة إلى أرقام الهواتف، يمكنك استخدام ما يلي:

كلمة المرور لمرة واحدة (OTP)

للحصول على كلمة مرور لمرّة واحدة في عرض واحد، يمكنك استخدام AUTOFILL_HINT_SMS_OTP.

بالنسبة إلى طرق العرض المتعددة حيث يتم ربط كل ملف شخصي برقم واحد من كلمة المرور لمرة واحدة، يمكنك استخدام طريقة generateSmsOtpHintForCharacterPosition() لإنشاء تلميحات لكل حرف.

وضع علامة على الحقول بأنّها مهمّة للملء التلقائي

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

ومع ذلك، هناك حالات لا تكون فيها طريقة العرض أو بنية طريقة العرض أو النشاط بأكمله مهمة للملء التلقائي:

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

يمكنك ضبط مدى أهمية طريقة العرض لميزة الملء التلقائي باستخدام السمة android:importantForAutofill على النحو التالي:

<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:importantForAutofill="no" />

يمكن أن تكون قيمة importantForAutofill أيًا مما يلي:

auto
يمكنك السماح لنظام Android باستخدام استدلاله لتحديد ما إذا كانت زاوية الرؤية مهمة للملء التلقائي.
no
لا يُعتبر هذا العرض مهمًا للملء التلقائي.
noExcludeDescendants
هذه طريقة العرض وعناصرها الفرعية غير مهمة للملء التلقائي.
yes
طريقة العرض هذه مهمة للملء التلقائي.
yesExcludeDescendants
وهذه طريقة العرض مهمة للملء التلقائي، ولكن عناصرها الثانوية غير مهمة للملء التلقائي.

يمكنك أيضًا استخدام الطريقة setImportantForAutofill():

Kotlin

val captcha = findViewById<TextView>(R.id.captcha)
captcha.setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO)

Java

TextView captcha = findViewById(R.id.captcha);
captcha.setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_NO);

يمكنك إعلان الأمثلة السابقة لحالات الاستخدام غير المهمة للملء التلقائي على النحو التالي:

  • الحقل CAPTCHA في نشاط تسجيل الدخول: استخدِم android:importantForAutofill="no" أو IMPORTANT_FOR_AUTOFILL_NO لوضع علامة على طريقة العرض هذه كغير مهمة.
  • طريقة عرض ينشئ فيها المستخدم المحتوى:استخدِم android:importantForAutofill="noExcludeDescendants" أو IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS لوضع علامة على بنية العرض بأكملها بأنّها غير مهمة.
  • المشاهدات في بعض الأنشطة ضمن الألعاب: استخدِم android:importantForAutofill="noExcludeDescendants" أو IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS لوضع علامة على بنية العرض بأكملها بأنّها غير مهمة.

ربط بيانات الموقع الإلكتروني والتطبيقات المتوافقة مع الأجهزة الجوّالة

يمكن لخدمات الملء التلقائي، مثل "الملء التلقائي" مع Google، مشاركة بيانات تسجيل دخول المستخدم بين المتصفحات وأجهزة Android بعد ربط التطبيق والموقع الإلكتروني. عندما يختار المستخدم خدمة الملء التلقائي نفسها على المنصتَين، يؤدي تسجيل الدخول إلى تطبيق الويب إلى إتاحة بيانات اعتماد تسجيل الدخول لملء البيانات تلقائيًا عند تسجيل الدخول إلى تطبيق Android المقابل.

لربط تطبيق Android بموقعك الإلكتروني، يمكنك استضافة رابط إلى مواد العرض الرقمية مع علاقة delegate_permission/common.get_login_creds في موقعك الإلكتروني. بعد ذلك، عليك الإفصاح عن عملية الربط في ملف AndroidManifest.xml الخاص بتطبيقك. للحصول على تعليمات تفصيلية حول كيفية ربط موقعك الإلكتروني بتطبيق Android، يُرجى الاطّلاع على تفعيل تسجيل الدخول التلقائي على جميع التطبيقات والمواقع الإلكترونية.

إكمال سير عمل الملء التلقائي

يصف هذا القسم سيناريوهات محددة يمكنك من خلالها اتخاذ خطوات لتحسين وظيفة الملء التلقائي لمستخدمي تطبيقك.

تحديد ما إذا كانت ميزة "الملء التلقائي" مفعَّلة

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

على سبيل المثال، تعرض العلامة TextView إدخالاً للملء التلقائي في القائمة الكاملة في حال تفعيل ميزة الملء التلقائي للمستخدم. للتحقّق ممّا إذا تم تفعيل ميزة الملء التلقائي للمستخدم، استدعِ الطريقة isEnabled() للكائن AutofillManager.

لضمان تحسين تجربة الاشتراك وتسجيل الدخول للمستخدمين الذين لا يستخدمون ميزة الملء التلقائي، ننصحك بتنفيذ ميزة تسجيل الدخول بنقرة واحدة.

فرض طلب ملء تلقائي

تحتاج في بعض الأحيان إلى فرض طلب الملء التلقائي استجابةً لإجراء مستخدم. على سبيل المثال، تقدّم TextView عنصر قائمة للملء التلقائي عندما يضغط المستخدم مع الاستمرار على العرض. يوضّح مثال الرمز التالي كيفية فرض طلب الملء التلقائي:

Kotlin

fun eventHandler(view: View) {
    val afm = requireContext().getSystemService(AutofillManager::class.java)
    afm?.requestAutofill(view)
}

Java

public void eventHandler(View view) {
    AutofillManager afm = context.getSystemService(AutofillManager.class);
    if (afm != null) {
        afm.requestAutofill(view);
    }
}

يمكنك أيضًا استخدام طريقة cancel() لإلغاء سياق الملء التلقائي الحالي. ويمكن أن يكون هذا مفيدًا إذا كان لديك زر يمحو الحقول في صفحة تسجيل الدخول.

استخدام نوع الملء التلقائي الصحيح للبيانات في عناصر تحكُّم أداة الاختيار

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

يتوقع عنصر EditText في الأصل بيانات الملء التلقائي من النوع AUTOFILL_TYPE_TEXT. إذا كنت تستخدم نوعًا مختلفًا من البيانات، يمكنك إنشاء ملف شخصي مخصّص يكتسب من EditText وينفذ الطرق المطلوبة للتعامل مع النوع المقابل من البيانات. على سبيل المثال، إذا كان لديك حقل تاريخ، نفِّذ الطرق ذات المنطق الذي يعالج قيم النوع AUTOFILL_TYPE_DATE بشكل صحيح.

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

إنهاء سياق الملء التلقائي

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

دعم طرق العرض المخصّصة

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

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

  • يوفر العرض المخصّص بنية عرض عادية أو بنية تلقائية للعرض.
  • يحتوي العرض المخصّص على بنية افتراضية أو بنية عرض غير متاحة لإطار عمل الملء التلقائي.

طرق العرض المخصّصة مع بنية طرق العرض العادية

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

  • تعامل مع قيمة الملء التلقائي التي يرسلها إطار العمل إلى تطبيقك.
  • أدخِل نوع الملء التلقائي وقيمته لإطار العمل.

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

يجب أن تحدِّد طريقة العرض نوع الملء التلقائي وقيمته من خلال إلغاء الطريقتَين getAutofillType() وgetAutofillValue() على التوالي.

أخيرًا، يجب ألا تملأ ميزة الملء التلقائي طريقة العرض إذا لم يتمكّن المستخدم من توفير قيمة لطريقة العرض في حالتها الحالية، على سبيل المثال، إذا كانت طريقة العرض غير مفعّلة. في هذه الحالات، يجب أن تعرض getAutofillType() السمة AUTOFILL_TYPE_NONE، ويجب أن تعرض getAutofillValue() القيمة null، ويجب ألا يتّخذ autofill() أي إجراء.

تتطلب الحالات التالية خطوات إضافية للعمل بشكل صحيح ضمن إطار العمل:

  • طريقة العرض المخصّصة قابلة للتعديل.
  • تحتوي طريقة العرض المخصّصة على بيانات حساسة.

طريقة العرض المخصّصة قابلة للتعديل

إذا كان العرض قابلاً للتعديل، يُرجى إشعار إطار عمل الملء التلقائي بشأن التغييرات من خلال طلب notifyValueChanged() على الكائن AutofillManager.

يحتوي العرض المخصّص على بيانات حساسة

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

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

يفترض إطار عمل الملء التلقائي أن جميع البيانات حساسة بشكل تلقائي. يمكنك وضع علامة على البيانات غير الحسّاسة.

لتحديد ما إذا كان الملف الشخصي يتضمّن بيانات حسّاسة، نفِّذ onProvideAutofillStructure() واستدعِ setDataIsSensitive() على الكائن ViewStructure.

يوضّح مثال الرمز التالي كيفية وضع علامة على البيانات في بنية طريقة العرض باعتبارها غير حساسة:

Kotlin

override fun onProvideAutofillStructure(structure: ViewStructure, flags: Int) {
    super.onProvideAutofillStructure(structure, flags)

    structure.setDataIsSensitive(false)
}

Java

@Override
public void onProvideAutofillStructure(ViewStructure structure, int flags) {
    super.onProvideAutofillStructure(structure, flags);

    structure.setDataIsSensitive(false);
}

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

تُعدّ الملفات الشخصية التي تستخدم محوّلاً، مثل Spinner، حالة مماثلة. على سبيل المثال، يمكن استخدام طريقة getAutofillOptions() لواجهة Adapter لتقديم قائمة بالسنوات، وذلك من خلال مؤشر سريان العمل الذي يقدِّم السنوات التي تم إنشاؤها ديناميكيًا، استنادًا إلى السنة الحالية، لاستخدامها في حقول انتهاء صلاحية بطاقة الائتمان.

ويمكن أن تقدّم الملفات الشخصية التي تستخدم ArrayAdapter قوائم بالقيم أيضًا. يضبط ArrayAdapter خيارات الملء التلقائي للموارد الثابتة تلقائيًا. في حال تقديم القيم بشكل ديناميكي، يمكنك إلغاء السمة getAutofillOptions().

طرق العرض المخصّصة ببنية افتراضية

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

  • يستخدم التطبيق محرك عرض منخفض المستوى، مثل OpenGL، لعرض واجهة المستخدم.
  • يستخدم التطبيق مثيل Canvas لرسم واجهة المستخدم.

في هذه الحالات، يمكنك تحديد بنية عرض من خلال تطبيق onProvideAutofillVirtualStructure() واتّباع الخطوات التالية:

  1. يمكنك زيادة عدد العناصر الثانوية في بنية المشاهدات من خلال طلب الرمز addChildCount().
  2. يمكنك إضافة طفل من خلال الاتصال على newChild().
  3. يمكنك ضبط رقم تعريف الملء التلقائي للطفل من خلال الاتصال على setAutofillId().
  4. حدِّد السمات ذات الصلة، مثل قيمة الملء التلقائي ونوعه.
  5. إذا كانت بيانات العنصر الثانوي الافتراضي حسّاسة، عليك تمرير true إلى setDataIsSensitive()، وإلا عليك ضبط false.

يعرض مقتطف الرمز التالي كيفية إنشاء عنصر ثانوي جديد في البنية الافتراضية:

Kotlin

override fun onProvideAutofillVirtualStructure(structure: ViewStructure, flags: Int) {

    super.onProvideAutofillVirtualStructure(structure, flags)

    // Create a new child in the virtual structure.
    structure.addChildCount(1)
    val child = structure.newChild(childIndex)

    // Set the autofill ID for the child.
    child.setAutofillId(structure.autofillId!!, childVirtualId)

    // Populate the child by providing properties such as value and type.
    child.setAutofillValue(childAutofillValue)
    child.setAutofillType(childAutofillType)

    // Some children can provide a list of values, such as when the child is
    // a spinner.
    val childAutofillOptions = arrayOf<CharSequence>("option1", "option2")
    child.setAutofillOptions(childAutofillOptions)

    // Just like other types of views, mark the data as sensitive when
    // appropriate.
    val sensitive = !contentIsSetFromResources()
    child.setDataIsSensitive(sensitive)
}

Java

@Override
public void onProvideAutofillVirtualStructure(ViewStructure structure, int flags) {

    super.onProvideAutofillVirtualStructure(structure, flags);

    // Create a new child in the virtual structure.
    structure.addChildCount(1);
    ViewStructure child =
            structure.newChild(childIndex);

    // Set the autofill ID for the child.
    child.setAutofillId(structure.getAutofillId(), childVirtualId);

    // Populate the child by providing properties such as value and type.
    child.setAutofillValue(childAutofillValue);
    child.setAutofillType(childAutofillType);

    // Some children can provide a list of values, such as when the child is
    // a spinner.
    CharSequence childAutofillOptions[] = { "option1", "option2" };
    child.setAutofillOptions(childAutofillOptions);

    // Just like other types of views, mark the data as sensitive when
    // appropriate.
    boolean sensitive = !contentIsSetFromResources();
    child.setDataIsSensitive(sensitive);
}

عندما تتغير عناصر في بنية افتراضية، قم بإعلام إطار العمل عن طريق إجراء المهام التالية:

  • إذا تغيّر التركيز داخل العناصر الثانوية، يمكنك استدعاء notifyViewEntered() وnotifyViewExited() على الكائن AutofillManager.
  • إذا تغيّرت قيمة العنصر الفرعي، يمكنك استدعاء notifyValueChanged() على كائن AutofillManager.
  • إذا لم يعُد العرض الهرمي لطريقة العرض متاحًا لأنّ المستخدم أكمل خطوة في سير العمل، مثل تسجيل الدخول باستخدام نموذج تسجيل دخول، عليك استدعاء commit() على الكائن AutofillManager.
  • إذا كان العرض الهرمي لطريقة العرض غير صالح لأنّ المستخدم ألغى خطوة في سير العمل، مثلاً عندما ينقر المستخدم على زر لمحو نموذج تسجيل الدخول، عليك استدعاء cancel() على الكائن AutofillManager.

استخدام عمليات معاودة الاتصال لأحداث الملء التلقائي

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

توفّر هذه الفئة الطريقة onAutofillEvent(View, int) التي يستدعيها التطبيق بعد تغيير حالة الملء التلقائي المرتبطة بطريقة العرض. وهناك أيضًا نسخة من هذه الطريقة محمَّلة بشكلٍ زائد والتي تتضمّن مَعلمة childId يمكن لتطبيقك استخدامها مع الملفات الشخصية الافتراضية. ويتم تعريف الحالات المتاحة على أنّها ثابتة في معاودة الاتصال.

يمكنك تسجيل معاودة الاتصال باستخدام طريقة registerCallback() من الفئة AutofillManager. يعرض مثال الرمز التالي كيفية الإعلان عن معاودة الاتصال لأحداث الملء التلقائي:

Kotlin

val afm = context.getSystemService(AutofillManager::class.java)

afm?.registerCallback(object : AutofillManager.AutofillCallback() {
    // For virtual structures, override
    // onAutofillEvent(View view, int childId, int event) instead.
    override fun onAutofillEvent(view: View, event: Int) {
        super.onAutofillEvent(view, event)
        when (event) {
            EVENT_INPUT_HIDDEN -> {
                // The autofill affordance associated with the view was hidden.
            }
            EVENT_INPUT_SHOWN -> {
                // The autofill affordance associated with the view was shown.
            }
            EVENT_INPUT_UNAVAILABLE -> {
                // Autofill isn't available.
            }
        }

    }
})

Java

AutofillManager afm = getContext().getSystemService(AutofillManager.class);

afm.registerCallback(new AutofillManager.AutofillCallback() {
    // For virtual structures, override
    // onAutofillEvent(View view, int childId, int event) instead.
    @Override
    public void onAutofillEvent(@NonNull View view, int event) {
        super.onAutofillEvent(view, event);
        switch (event) {
            case EVENT_INPUT_HIDDEN:
                // The autofill affordance associated with the view was hidden.
                break;
            case EVENT_INPUT_SHOWN:
                // The autofill affordance associated with the view was shown.
                break;
            case EVENT_INPUT_UNAVAILABLE:
                // Autofill isn't available.
                break;
        }
    }
});

عندما يحين وقت إزالة معاودة الاتصال، استخدِم الإجراء unregisterCallback().

تخصيص الملء التلقائي القابل للرسم

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

res/values/styles.xml

<resources>
    <style name="MyAutofilledHighlight" parent="...">
        <item name="android:autofilledHighlight">@drawable/my_drawable</item>
    </style>
</resources>

res/drawable/my_drawable.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="#4DFF0000" />
</shape>

ملف AndroidManifest.xml

<application ...
    android:theme="@style/MyAutofilledHighlight">
<!-- or -->
<activity ...
    android:theme="@style/MyAutofilledHighlight">

المصادقة للملء التلقائي

يمكن لخدمة الملء التلقائي أن تطلب من المستخدم المصادقة قبل أن تتمكّن الخدمة من إكمال الحقول في تطبيقك، وفي هذه الحالة يشغِّل نظام Android نشاط مصادقة الخدمة كجزء من حزمة نشاطك.

لست بحاجة إلى تحديث تطبيقك لإتاحة المصادقة، لأنّ عملية المصادقة تتم داخل الخدمة. في المقابل، يجب التأكّد من الحفاظ على بنية عرض النشاط عند إعادة تشغيل النشاط، مثلاً من خلال إنشاء بنية طريقة العرض في onCreate()، وليس في onStart() أو onResume().

يمكنك التحقّق من سلوك تطبيقك عندما تتطلب خدمة الملء التلقائي المصادقة، وذلك باستخدام HeuristicsService من نموذج AutofillFramework وإعدادها لطلب مصادقة استجابة التعبئة. يمكنك أيضًا استخدام نموذج BadViewRemoveCreationSignInActivity لمحاكاة هذه المشكلة.

تحديد أرقام تعريف الملء التلقائي للملفات الشخصية المُعاد تدويرها

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

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

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

  • تحصل الطريقة getNextAutofillId() على معرّف ملء تلقائي جديد يكون فريدًا للنشاط.
  • تحدد الطريقة setAutofillId() معرّف الملء التلقائي الفريد والمنطقي لهذا الملف الشخصي في النشاط.

معالجة المشاكل المعروفة

يقدّم هذا القسم حلولاً للمشاكل المعروفة ضمن إطار عمل الملء التلقائي.

تتسبب ميزة "الملء التلقائي" في تعطُّل التطبيقات على نظامَي التشغيل Android 8.0 و8.1.

في نظامي التشغيل Android 8.0 (المستوى 26 لواجهة برمجة التطبيقات) و8.1 (المستوى 27 من واجهة برمجة التطبيقات)، يمكن أن تتسبب ميزة الملء التلقائي في تعطّل تطبيقك في سيناريوهات معيّنة. لحلّ المشاكل المحتملة، ضَع علامة على أيّ طرق عرض لا يتم ملؤها تلقائيًا باستخدام importantForAutofill=no. يمكنك أيضًا الإشارة إلى النشاط بأكمله باستخدام importantForAutofill=noExcludeDescendants.

لا يتم أخذ الملء التلقائي في الاعتبار في مربّعات الحوار التي تم تغيير حجمها.

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

لحلّ هذه المشكلة، استخدِم السمة token الخاصة بالنشاط الذي ينشئ مربّع الحوار بدلاً من السمة token لمَعلمات نافذة مربّع الحوار. بعد التحقق من تفعيل ميزة الملء التلقائي، احفظ مَعلمات النوافذ في طريقة onWindowAttributesChanged() للفئة التي يتم اكتسابها من السمة Dialog. بعد ذلك، استبدِل السمة token للمعلَمات المحفوظة بالسمة token للنشاط الرئيسي في طريقة onAttachedToWindow().

يعرض مقتطف الرمز التالي فئة تنفّذ هذا الحل البديل:

Kotlin

class MyDialog(context: Context) : Dialog(context) {

    // Used to store the dialog window parameters.
    private var token: IBinder? = null

    private val isDialogResizedWorkaroundRequired: Boolean
        get() {
            if (Build.VERSION.SDK_INT != Build.VERSION_CODES.O || Build.VERSION.SDK_INT != Build.VERSION_CODES.O_MR1) {
                return false
            }
            val autofillManager = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                context.getSystemService(AutofillManager::class.java)
            } else {
                null
            }
            return autofillManager?.isEnabled ?: false
        }

    override fun onWindowAttributesChanged(params: WindowManager.LayoutParams) {
        if (params.token == null && token != null) {
            params.token = token
        }

        super.onWindowAttributesChanged(params)
    }

    override fun onAttachedToWindow() {
        if (isDialogResizedWorkaroundRequired) {
            token = ownerActivity!!.window.attributes.token
        }

        super.onAttachedToWindow()
    }

}

Java

public class MyDialog extends Dialog {

    public MyDialog(Context context) {
        super(context);
    }

    // Used to store the dialog window parameters.
    private IBinder token;

    @Override
    public void onWindowAttributesChanged(WindowManager.LayoutParams params) {
        if (params.token == null && token != null) {
            params.token = token;
        }

        super.onWindowAttributesChanged(params);
    }

    @Override
    public void onAttachedToWindow() {
        if (isDialogResizedWorkaroundRequired()) {
            token = getOwnerActivity().getWindow().getAttributes().token;
        }

        super.onAttachedToWindow();
    }

    private boolean isDialogResizedWorkaroundRequired() {
        if (Build.VERSION.SDK_INT != Build.VERSION_CODES.O
                || Build.VERSION.SDK_INT != Build.VERSION_CODES.O_MR1) {
            return false;
        }
        AutofillManager autofillManager =
                null;
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
            autofillManager = getContext().getSystemService(AutofillManager.class);
        }
        return autofillManager != null && autofillManager.isEnabled();
    }

}

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

Kotlin

// AutofillExtensions.kt

fun Context.isDialogResizedWorkaroundRequired(): Boolean {
    // After the issue is resolved on Android, check whether the
    // workaround is still required for the current device.
    return isAutofillAvailable()
}

fun Context.isAutofillAvailable(): Boolean {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
        // The autofill framework is available on Android 8.0
        // or higher.
        return false
    }

    val afm = getSystemService(AutofillManager::class.java)
    // Return true if autofill is supported by the device and enabled
    // for the current user.
    return afm != null && afm.isEnabled
}

Java

public class AutofillHelper {

    public static boolean isDialogResizedWorkaroundRequired(Context context) {
        // After the issue is resolved on Android, check whether the
        // workaround is still required for the current device.
        return isAutofillAvailable(context);
    }

    public static boolean isAutofillAvailable(Context context) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
            // The autofill framework is available on Android 8.0
            // or higher.
            return false;
        }

        AutofillManager afm = context.getSystemService(AutofillManager.class);
        // Return true if autofill is supported by the device and enabled
        // for the current user.
        return afm != null && afm.isEnabled();
    }
}

اختبار تطبيقك باستخدام ميزة "الملء التلقائي"

بعد تحسين تطبيقك للتوافق مع خدمات الملء التلقائي، اختبِر ما إذا كان يعمل على النحو المطلوب مع خدمات الملء التلقائي.

استخدام محاكي أو جهاز مادي يعمل بنظام التشغيل Android 8.0 (المستوى 26 من واجهة برمجة التطبيقات) أو إصدار أحدث لاختبار تطبيقك. لمزيد من المعلومات حول كيفية إنشاء محاكي، يُرجى مراجعة إنشاء الأجهزة الافتراضية وإدارتها.

تثبيت خدمة الملء التلقائي

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

يمكنك استخدام نموذج إطار عمل الملء التلقائي على Android في Java لاختبار تطبيقك باستخدام خدمات الملء التلقائي. يوفّر نموذج التطبيق خدمة الملء التلقائي وفئات Activity للعميل يمكنك استخدامها لاختبار سير العمل قبل استخدامه مع تطبيقك. تشير هذه الصفحة إلى نموذج تطبيق android-AutofillFramework.

بعد تثبيت التطبيق، فعِّل خدمة الملء التلقائي في إعدادات نظام المحاكي من خلال الانتقال إلى الإعدادات > النظام > اللغات والإدخال > الإعدادات المتقدّمة > المساعدة بشأن الإدخال > خدمة الملء التلقائي.

تحليل متطلبات البيانات

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

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

إجراء الاختبار

بعد تحليل متطلبات البيانات، يمكنك إجراء الاختبار، بما في ذلك حفظ بيانات الاختبار في خدمة الملء التلقائي وتشغيل ميزة الملء التلقائي في تطبيقك.

حفظ البيانات في الخدمة

لحفظ البيانات في خدمة الملء التلقائي النشطة حاليًا، يمكنك إجراء ما يلي:

  1. افتح تطبيقًا يحتوي على ملف شخصي تتوقّع نوع البيانات التي تريد استخدامها أثناء الاختبار. يزوِّد نموذج التطبيق android-AutofillFramework واجهة المستخدم بطرق العرض التي تتوقع أنواعًا متعددة من البيانات، مثل أرقام بطاقات الائتمان وأسماء المستخدمين.
  2. انقر على طريقة العرض التي تحتفظ بنوع البيانات التي تحتاج إليها.
  3. أدخِل قيمة في العرض.
  4. انقر على زر التأكيد، مثل تسجيل الدخول أو إرسال. يتعين عليك عادةً إرسال النموذج قبل أن تحفظ الخدمة البيانات.
  5. تحقَّق من طلب الإذن من مربع حوار النظام. يعرض مربع حوار النظام اسم الخدمة النشطة حاليًا ويسأل عما إذا كانت هذه هي الخدمة التي تريد استخدامها في الاختبار. إذا كنت تريد استخدام الخدمة، انقر على حفظ.

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

تشغيل ميزة الملء التلقائي في تطبيقك

لتشغيل ميزة الملء التلقائي في تطبيقك، عليك اتّباع الخطوات التالية:

  1. افتح تطبيقك وانتقِل إلى النشاط الذي يتضمّن المشاهدات التي تريد اختبارها.
  2. انقر على العرض الذي يجب ملؤه.
  3. يعرض النظام واجهة مستخدم الملء التلقائي، والتي تحتوي على مجموعات البيانات التي يمكن أن تملأ العرض، كما هو موضح في الشكل 1.
  4. انقر فوق مجموعة البيانات التي تحتوي على البيانات التي تريد استخدامها. يُظهر العرض البيانات التي تم تخزينها في السابق في الخدمة.
واجهة مستخدم للملء التلقائي تعرض "dataset-2" كمجموعة بيانات متاحة
الشكل 1. ميزة "الملء التلقائي" لواجهة المستخدم تعرض مجموعات البيانات المتاحة

إذا لم يعرض Android واجهة مستخدم الملء التلقائي، يمكنك تجربة خيارات تحديد المشاكل وحلّها التالية:

  • تأكّد من أنّ المشاهدات في تطبيقك تستخدم القيمة الصحيحة في سمة android:autofillHints. للحصول على قائمة بالقيم المحتملة للسمة، راجِع الثوابت البادئة بـ AUTOFILL_HINT في الفئة View.
  • تأكَّد من ضبط السمة android:importantForAutofill على قيمة أخرى غير no في العرض المطلوب ملؤها، أو اضبط السمة على قيمة أخرى غير noExcludeDescendants في طريقة العرض أو أحد عناصرها الرئيسية.