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

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

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

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

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

يجب ضبط خدمة الملء التلقائي على جهازك حتى يتمكّن تطبيقك من استخدام إطار عمل الملء التلقائي. على الرغم من أنّ معظم الهواتف والأجهزة اللوحية التي تعمل بالإصدار 8.0 (المستوى 26 من واجهة برمجة التطبيقات) من نظام التشغيل Android والإصدارات الأحدث تتضمّن خدمة الملء التلقائي، ننصحك باستخدام خدمة اختبار عند اختبار تطبيقك، مثل خدمة الملء التلقائي في نموذج إطار عمل الملء التلقائي في 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() لإنشاء تلميحات لكل حرف.

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

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

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

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

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

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

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

على سبيل المثال، يعرض TextView إدخالاً للملء التلقائي في قائمة الخيارات الإضافية إذا كان الملء التلقائي مفعّلاً للمستخدم. للتحقّق مما إذا كانت ميزة &quot;الملء التلقائي&quot; مفعّلة للمستخدم، استدعِ طريقة 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() لإلغاء سياق الملء التلقائي الحالي. يمكن أن يكون ذلك مفيدًا إذا كان لديك زر يمحو الحقول في صفحة تسجيل الدخول.

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

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

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

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

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

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

إتاحة طرق العرض المخصّصة

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

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

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

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

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

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

عند تفعيل ميزة &quot;الملء التلقائي&quot;، يستدعي إطار عمل &quot;الملء التلقائي&quot; الدالة 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 وإعداده ليتطلّب مصادقة ردّ الملء. يمكنك أيضًا استخدام نموذج BadViewStructureCreationSignInActivity لمحاكاة هذه المشكلة.

تعيين أرقام تعريف الملء التلقائي للعناصر المعاد استخدامها

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

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

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

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

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

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

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

في نظامَي التشغيل Android 8.0 (المستوى 26 من واجهة برمجة التطبيقات) وAndroid 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();
    }

}

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

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();
    }
}

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

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

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

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

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

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

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

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

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

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

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

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

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

لحفظ البيانات في خدمة الملء التلقائي النشطة حاليًا، اتّبِع الخطوات التالية:

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

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

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

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

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

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

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