إنشاء خدمة تسهيل الاستخدام الخاصة بك

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

يوفّر Android خدمات عادية لتسهيل الاستخدام، بما في ذلك TalkBack ، ويمكن للمطوّرين إنشاء خدماتهم الخاصة وتوزيعها. هذا المستند يشرح أساسيات إنشاء خدمة لتسهيل الاستخدام.

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

إنشاء خدمة تسهيل الاستخدام

ضمن مشروعك، أنشئ فئة تمتد AccessibilityService:

Kotlin

package com.example.android.apis.accessibility

import android.accessibilityservice.AccessibilityService
import android.view.accessibility.AccessibilityEvent

class MyAccessibilityService : AccessibilityService() {
...
    override fun onInterrupt() {}

    override fun onAccessibilityEvent(event: AccessibilityEvent?) {}
...
}

Java

package com.example.android.apis.accessibility;

import android.accessibilityservice.AccessibilityService;
import android.view.accessibility.AccessibilityEvent;

public class MyAccessibilityService extends AccessibilityService {
...
    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
    }

    @Override
    public void onInterrupt() {
    }

...
}

في حال إنشاء مشروع جديد لهذا الجهاز "Service" ولا تريد الحصول على تطبيق المرتبطة به، يمكنك إزالة الصف Activity لإجراء التفعيل من المصدر.

بيانات البيان والأذونات

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

بيان خدمة تسهيل الاستخدام

لكي يتم التعامل مع تطبيقك كخدمة لتسهيل الاستخدام، يجب تضمين service. العنصر — بدلاً من العنصر activity — ضمن application العنصر في بيانك. بالإضافة إلى ذلك، ضمن العنصر service، ضمِّن فلتر الأهداف الخاصة بالخدمة لتسهيل الاستخدام يجب أن يحمي البيان الخدمة أيضًا. عن طريق إضافة BIND_ACCESSIBILITY_SERVICE للتأكد من أن النظام وحده هو من يمكنه الربط به. وفي ما يلي مثال لذلك:

  <application>
    <service android:name=".MyAccessibilityService"
        android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
        android:label="@string/accessibility_service_label">
      <intent-filter>
        <action android:name="android.accessibilityservice.AccessibilityService" />
      </intent-filter>
    </service>
  </application>

إعدادات خدمة تسهيل الاستخدام

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

يمكنك تضمين عنصر <meta-data> في البيان مع إشارة إلى الخاص بك، والذي يتيح لك تعيين مجموعة كاملة من الخيارات خدمة تسهيل الاستخدام، كما هو موضَّح في المثال التالي:

<service android:name=".MyAccessibilityService">
  ...
  <meta-data
    android:name="android.accessibilityservice"
    android:resource="@xml/accessibility_service_config" />
</service>

يشير عنصر <meta-data> هذا إلى ملف XML تنشئه في دليل موارد التطبيق: <project_dir>/res/xml/accessibility_service_config.xml> يُنشئ الكود التالي مثالاً على محتوى ملف إعداد الخدمة:

<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:description="@string/accessibility_service_description"
    android:packageNames="com.example.android.apis"
    android:accessibilityEventTypes="typeAllMask"
    android:accessibilityFlags="flagDefault"
    android:accessibilityFeedbackType="feedbackSpoken"
    android:notificationTimeout="100"
    android:canRetrieveWindowContent="true"
    android:settingsActivity="com.example.android.accessibility.ServiceSettingsActivity"
/>

لمزيد من المعلومات حول سمات XML التي يمكن استخدامها في ملف إعداد خدمة تسهيل الاستخدام، يُرجى الاطّلاع على المرجع التالي التوثيق:

لمزيد من المعلومات حول إعدادات الضبط التي يمكن ضبطها ديناميكيًا في وقت التشغيل، يمكنك مراجعة AccessibilityServiceInfo الوثائق المرجعية.

إعداد خدمة تسهيل الاستخدام

يجب مراعاة ما يلي عند تعيين متغيرات التهيئة خدمة تسهيل الاستخدام لإعلام النظام بكيفية ووقت التشغيل:

  • ما هي أنواع الأحداث التي تريد الاستجابة لها؟
  • هل يجب أن تكون الخدمة نشطة لجميع التطبيقات أم لحزمة معيّنة فقط؟ الأسماء؟
  • ما هي أنواع الملاحظات المختلفة التي يستخدمها؟

لديك خياران لإعداد هذه المتغيرات. خيار التوافق مع الأنظمة القديمة هو وضعها في التعليمات البرمجية، باستخدام setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo) ولإجراء ذلك، عليك إلغاء onServiceConnected() وإعداد خدمتك هناك، كما هو موضح في المثال التالي:

Kotlin

override fun onServiceConnected() {
    info.apply {
        // Set the type of events that this service wants to listen to. Others
        // aren't passed to this service.
        eventTypes = AccessibilityEvent.TYPE_VIEW_CLICKED or AccessibilityEvent.TYPE_VIEW_FOCUSED

        // If you only want this service to work with specific apps, set their
        // package names here. Otherwise, when the service is activated, it
        // listens to events from all apps.
        packageNames = arrayOf("com.example.android.myFirstApp", "com.example.android.mySecondApp")

        // Set the type of feedback your service provides.
        feedbackType = AccessibilityServiceInfo.FEEDBACK_SPOKEN

        // Default services are invoked only if no package-specific services are
        // present for the type of AccessibilityEvent generated. This service is
        // app-specific, so the flag isn't necessary. For a general-purpose
        // service, consider setting the DEFAULT flag.

        // flags = AccessibilityServiceInfo.DEFAULT;

        notificationTimeout = 100
    }

    this.serviceInfo = info

}

Java

@Override
public void onServiceConnected() {
    // Set the type of events that this service wants to listen to. Others
    // aren't passed to this service.
    info.eventTypes = AccessibilityEvent.TYPE_VIEW_CLICKED |
            AccessibilityEvent.TYPE_VIEW_FOCUSED;

    // If you only want this service to work with specific apps, set their
    // package names here. Otherwise, when the service is activated, it listens
    // to events from all apps.
    info.packageNames = new String[]
            {"com.example.android.myFirstApp", "com.example.android.mySecondApp"};

    // Set the type of feedback your service provides.
    info.feedbackType = AccessibilityServiceInfo.FEEDBACK_SPOKEN;

    // Default services are invoked only if no package-specific services are
    // present for the type of AccessibilityEvent generated. This service is
    // app-specific, so the flag isn't necessary. For a general-purpose service,
    // consider setting the DEFAULT flag.

    // info.flags = AccessibilityServiceInfo.DEFAULT;

    info.notificationTimeout = 100;

    this.setServiceInfo(info);

}

الخيار الثاني هو إعداد الخدمة باستخدام ملف XML. بالتأكيد خيارات التهيئة، مثل canRetrieveWindowContent، لا تتوفّر إلّا في حال إعداد خدمتك باستخدام XML. التكوين تبدو الخيارات من المثال السابق هكذا عند تحديدها باستخدام XML:

<accessibility-service
     android:accessibilityEventTypes="typeViewClicked|typeViewFocused"
     android:packageNames="com.example.android.myFirstApp, com.example.android.mySecondApp"
     android:accessibilityFeedbackType="feedbackSpoken"
     android:notificationTimeout="100"
     android:settingsActivity="com.example.android.apis.accessibility.TestBackActivity"
     android:canRetrieveWindowContent="true"
/>

إذا كنت تستخدم XML، يُرجى الإشارة إليه في ملف البيان عن طريق إضافة <meta-data> إلى بيان الخدمة الذي يشير إلى ملف XML. إذا خزّنت ملف XML في res/xml/serviceconfig.xml، ستظهر العلامة الجديدة على النحو التالي:

<service android:name=".MyAccessibilityService">
     <intent-filter>
         <action android:name="android.accessibilityservice.AccessibilityService" />
     </intent-filter>
     <meta-data android:name="android.accessibilityservice"
     android:resource="@xml/serviceconfig" />
</service>

طرق توفير الخدمات لتسهيل الاستخدام

يجب أن تعمل خدمة تسهيل الاستخدام على توسيع فئة AccessibilityService طرق إلغاء الطرق التالية من تلك الفئة. يتم تقديم هذه الطرق في الترتيب الذي يتّصل به نظام Android: من وقت بدء الخدمة (onServiceConnected())، إلى أثناء تشغيله (onAccessibilityEvent()، onInterrupt())، إلى متى يتم إيقاف تشغيله (onUnbind()).

  • onServiceConnected(): (اختياري) يستدعي النظام هذه الطريقة عند بالاتصال بخدمة إمكانية الوصول. استخدام هذه الطريقة لإجراء إعداد لمرة واحدة خطوات لخدمتك، بما في ذلك الاتصال بنظام ملاحظات المستخدمين مثل مدير الصوت أو هزاز الجهاز. إذا كنت تريد تعيين تهيئة الخدمة في وقت التشغيل أو إجراء تعديلات لمرة واحدة، هَذَا الْمَوْقِعُ الْجُغْرَافِي ملائمٌ لِلِاتِّصَالْ بِـ setServiceInfo().

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

  • onInterrupt(): (مطلوبة) يطلب النظام هذه الطريقة عندما يستدعي النظام تريد إيقاف الملاحظات التي تقدمها خدمتك، عادةً في الاستجابة لإجراء المستخدم مثل نقل التركيز إلى عنصر تحكم مختلف. هذا النمط طريقة عدة مرات على مدار دورة حياة الخدمة.

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

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

التسجيل في أحداث تسهيل الاستخدام

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

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

  • أنواع الأحداث: حدِّد أنواع أحداث تسهيل الاستخدام التي تريد ينبغي التعامل معها. يمكنك ضبط هذه المَعلمة في خدمة تسهيل الاستخدام. ملفات الإعداد التي تحتوي على السمة android:accessibilityEventTypes باعتبارها قائمة مفصولة بالحرف |، على سبيل المثال، accessibilityEventTypes="typeViewClicked|typeViewFocused" أو يمكنك تعيين باستخدام AccessibilityServiceInfo.eventTypes عضو.

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

مستوى صوت ميزة "تسهيل الاستخدام"

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

يمكن لخدمات تسهيل الاستخدام استخدام نوع البث هذا من خلال ضبط FLAG_ENABLE_ACCESSIBILITY_VOLUME الخيار. يمكنك بعد ذلك تغيير مستوى صوت تسهيل الاستخدام الخاص بالجهاز من خلال إجراء مكالمة الـ adjustStreamVolume() على مثيل الجهاز AudioManager

يوضح مقتطف الرمز التالي كيف يمكن لخدمة تسهيل الاستخدام استخدام فئة الصوت باللغة STREAM_ACCESSIBILITY:

Kotlin

import android.media.AudioManager.*

class MyAccessibilityService : AccessibilityService() {

    private val audioManager = getSystemService(AUDIO_SERVICE) as AudioManager

    override fun onAccessibilityEvent(accessibilityEvent: AccessibilityEvent) {
        if (accessibilityEvent.source.text == "Increase volume") {
            audioManager.adjustStreamVolume(AudioManager.STREAM_ACCESSIBILITY, ADJUST_RAISE, 0)
        }
    }
}

Java

import static android.media.AudioManager.*;

public class MyAccessibilityService extends AccessibilityService {
    private AudioManager audioManager =
            (AudioManager) getSystemService(AUDIO_SERVICE);

    @Override
    public void onAccessibilityEvent(AccessibilityEvent accessibilityEvent) {
        AccessibilityNodeInfo interactedNodeInfo =
                accessibilityEvent.getSource();
        if (interactedNodeInfo.getText().equals("Increase volume")) {
            audioManager.adjustStreamVolume(AudioManager.STREAM_ACCESSIBILITY,
                ADJUST_RAISE, 0);
        }
    }
}

للمزيد من المعلومات، يمكنك مشاهدة فيديو جلسة الميزات الجديدة في إمكانية الوصول إلى Android من مؤتمر Google I/O لعام 2017، بدءًا من 6:35.

اختصار زر أدوات تسهيل الاستخدام

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

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

للمزيد من المعلومات، يمكنك مشاهدة فيديو جلسة الميزات الجديدة في إمكانية الوصول إلى Android من مؤتمر Google I/O لعام 2017، بدءًا من 13:25.

زر أدوات تسهيل الاستخدام

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

للسماح للمستخدمين باستدعاء خدمة معيّنة لتسهيل الاستخدام من خلال إمكانية الوصول تحتاج الخدمة إلى إضافة FLAG_REQUEST_ACCESSIBILITY_BUTTON وضع علامة في السمة android:accessibilityFlags لكائن AccessibilityServiceInfo . ويمكن للخدمة بعد ذلك تسجيل معاودة الاتصال باستخدام registerAccessibilityButtonCallback()

يوضح مقتطف الرمز التالي كيفية ضبط إعدادات تسهيل الاستخدام. الخدمة للاستجابة للمستخدم الذي يضغط على زر أدوات تسهيل الاستخدام:

Kotlin

private var mAccessibilityButtonController: AccessibilityButtonController? = null
private var accessibilityButtonCallback:
        AccessibilityButtonController.AccessibilityButtonCallback? = null
private var mIsAccessibilityButtonAvailable: Boolean = false

override fun onServiceConnected() {
    mAccessibilityButtonController = accessibilityButtonController
    mIsAccessibilityButtonAvailable =
            mAccessibilityButtonController?.isAccessibilityButtonAvailable ?: false

    if (!mIsAccessibilityButtonAvailable) return

    serviceInfo = serviceInfo.apply {
        flags = flags or AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON
    }

    accessibilityButtonCallback =
        object : AccessibilityButtonController.AccessibilityButtonCallback() {
            override fun onClicked(controller: AccessibilityButtonController) {
                Log.d("MY_APP_TAG", "Accessibility button pressed!")

                // Add custom logic for a service to react to the
                // accessibility button being pressed.
            }

            override fun onAvailabilityChanged(
                    controller: AccessibilityButtonController,
                    available: Boolean
            ) {
                if (controller == mAccessibilityButtonController) {
                    mIsAccessibilityButtonAvailable = available
                }
            }
    }

    accessibilityButtonCallback?.also {
        mAccessibilityButtonController?.registerAccessibilityButtonCallback(it, null)
    }
}

Java

private AccessibilityButtonController accessibilityButtonController;
private AccessibilityButtonController
        .AccessibilityButtonCallback accessibilityButtonCallback;
private boolean mIsAccessibilityButtonAvailable;

@Override
protected void onServiceConnected() {
    accessibilityButtonController = getAccessibilityButtonController();
    mIsAccessibilityButtonAvailable =
            accessibilityButtonController.isAccessibilityButtonAvailable();

    if (!mIsAccessibilityButtonAvailable) {
        return;
    }

    AccessibilityServiceInfo serviceInfo = getServiceInfo();
    serviceInfo.flags
            |= AccessibilityServiceInfo.FLAG_REQUEST_ACCESSIBILITY_BUTTON;
    setServiceInfo(serviceInfo);

    accessibilityButtonCallback =
        new AccessibilityButtonController.AccessibilityButtonCallback() {
            @Override
            public void onClicked(AccessibilityButtonController controller) {
                Log.d("MY_APP_TAG", "Accessibility button pressed!");

                // Add custom logic for a service to react to the
                // accessibility button being pressed.
            }

            @Override
            public void onAvailabilityChanged(
              AccessibilityButtonController controller, boolean available) {
                if (controller.equals(accessibilityButtonController)) {
                    mIsAccessibilityButtonAvailable = available;
                }
            }
        };

    if (accessibilityButtonCallback != null) {
        accessibilityButtonController.registerAccessibilityButtonCallback(
                accessibilityButtonCallback, null);
    }
}

للمزيد من المعلومات، يمكنك مشاهدة فيديو جلسة الميزات الجديدة في إمكانية الوصول إلى Android من مؤتمر Google I/O لعام 2017، بدءًا من 16:28.

إيماءات بصمات الإصبع

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

  1. تعريف USE_BIOMETRIC الإذن و CAPABILITY_CAN_REQUEST_FINGERPRINT_GESTURES قدراتي.
  2. ضبط FLAG_REQUEST_FINGERPRINT_GESTURES ضمن سمة android:accessibilityFlags.
  3. يمكنك التسجيل لتلقّي معاودة الاتصال باستخدام registerFingerprintGestureCallback().

يُرجى العلم أنّ بعض الأجهزة لا تتضمّن أدوات استشعار بصمة الإصبع. لتحديد ما إذا كان الجهاز متوافقًا مع أداة الاستشعار، استخدِم isHardwareDetected() . حتى على جهاز يتضمّن أداة استشعار بصمة الإصبع، لا يمكن لخدمتك استخدام أداة الاستشعار عند استخدامها لأغراض المصادقة لتحديد متى أداة الاستشعار متاحة، عليك طلب isGestureDetectionAvailable() وننفذ onGestureDetectionAvailabilityChanged() معاودة الاتصال.

يوضح مقتطف الرمز التالي مثالاً على استخدام إيماءات بصمة الإصبع التنقل في لوحة ألعاب افتراضية:

// AndroidManifest.xml
<manifest ... >
    <uses-permission android:name="android.permission.USE_FINGERPRINT" />
    ...
    <application>
        <service android:name="com.example.MyFingerprintGestureService" ... >
            <meta-data
                android:name="android.accessibilityservice"
                android:resource="@xml/myfingerprintgestureservice" />
        </service>
    </application>
</manifest>
// myfingerprintgestureservice.xml
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
    ...
    android:accessibilityFlags=" ... |flagRequestFingerprintGestures"
    android:canRequestFingerprintGestures="true"
    ... />

Kotlin

// MyFingerprintGestureService.kt
import android.accessibilityservice.FingerprintGestureController.*

class MyFingerprintGestureService : AccessibilityService() {

    private var gestureController: FingerprintGestureController? = null
    private var fingerprintGestureCallback:
            FingerprintGestureController.FingerprintGestureCallback? = null
    private var mIsGestureDetectionAvailable: Boolean = false

    override fun onCreate() {
        gestureController = fingerprintGestureController
        mIsGestureDetectionAvailable = gestureController?.isGestureDetectionAvailable ?: false
    }

    override fun onServiceConnected() {
        if (mFingerprintGestureCallback != null || !mIsGestureDetectionAvailable) return

        fingerprintGestureCallback =
                object : FingerprintGestureController.FingerprintGestureCallback() {
                    override fun onGestureDetected(gesture: Int) {
                        when (gesture) {
                            FINGERPRINT_GESTURE_SWIPE_DOWN -> moveGameCursorDown()
                            FINGERPRINT_GESTURE_SWIPE_LEFT -> moveGameCursorLeft()
                            FINGERPRINT_GESTURE_SWIPE_RIGHT -> moveGameCursorRight()
                            FINGERPRINT_GESTURE_SWIPE_UP -> moveGameCursorUp()
                            else -> Log.e(MY_APP_TAG, "Error: Unknown gesture type detected!")
                        }
                    }

                    override fun onGestureDetectionAvailabilityChanged(available: Boolean) {
                        mIsGestureDetectionAvailable = available
                    }
                }

        fingerprintGestureCallback?.also {
            gestureController?.registerFingerprintGestureCallback(it, null)
        }
    }
}

Java

// MyFingerprintGestureService.java
import static android.accessibilityservice.FingerprintGestureController.*;

public class MyFingerprintGestureService extends AccessibilityService {
    private FingerprintGestureController gestureController;
    private FingerprintGestureController
            .FingerprintGestureCallback fingerprintGestureCallback;
    private boolean mIsGestureDetectionAvailable;

    @Override
    public void onCreate() {
        gestureController = getFingerprintGestureController();
        mIsGestureDetectionAvailable =
                gestureController.isGestureDetectionAvailable();
    }

    @Override
    protected void onServiceConnected() {
        if (fingerprintGestureCallback != null
                || !mIsGestureDetectionAvailable) {
            return;
        }

        fingerprintGestureCallback =
               new FingerprintGestureController.FingerprintGestureCallback() {
            @Override
            public void onGestureDetected(int gesture) {
                switch (gesture) {
                    case FINGERPRINT_GESTURE_SWIPE_DOWN:
                        moveGameCursorDown();
                        break;
                    case FINGERPRINT_GESTURE_SWIPE_LEFT:
                        moveGameCursorLeft();
                        break;
                    case FINGERPRINT_GESTURE_SWIPE_RIGHT:
                        moveGameCursorRight();
                        break;
                    case FINGERPRINT_GESTURE_SWIPE_UP:
                        moveGameCursorUp();
                        break;
                    default:
                        Log.e(MY_APP_TAG,
                                  "Error: Unknown gesture type detected!");
                        break;
                }
            }

            @Override
            public void onGestureDetectionAvailabilityChanged(boolean available) {
                mIsGestureDetectionAvailable = available;
            }
        };

        if (fingerprintGestureCallback != null) {
            gestureController.registerFingerprintGestureCallback(
                    fingerprintGestureCallback, null);
        }
    }
}

للمزيد من المعلومات، يمكنك مشاهدة فيديو جلسة الميزات الجديدة في إمكانية الوصول إلى Android من مؤتمر Google I/O لعام 2017، بدءًا من 9:03.

تحويل النص إلى كلام بعدّة لغات

بدءًا من إصدار Android 8.0 (المستوى 26 من واجهة برمجة التطبيقات)، ستكون خدمة "تحويل النص إلى كلام" (TTS) من Android يمكنهم التعرّف على العبارات ونطقها بلغات متعددة خلال مجموعة واحدة من النص. لتفعيل إمكانية التبديل التلقائي بين اللغات في إحدى خدمات تسهيل الاستخدام الخدمة، إحاطة كل السلاسل في LocaleSpan كائنات، كما هو موضح في مقتطف الرمز التالي:

Kotlin

val localeWrappedTextView = findViewById<TextView>(R.id.my_french_greeting_text).apply {
    text = wrapTextInLocaleSpan("Bonjour!", Locale.FRANCE)
}

private fun wrapTextInLocaleSpan(originalText: CharSequence, loc: Locale): SpannableStringBuilder {
    return SpannableStringBuilder(originalText).apply {
        setSpan(LocaleSpan(loc), 0, originalText.length - 1, 0)
    }
}

Java

TextView localeWrappedTextView = findViewById(R.id.my_french_greeting_text);
localeWrappedTextView.setText(wrapTextInLocaleSpan("Bonjour!", Locale.FRANCE));

private SpannableStringBuilder wrapTextInLocaleSpan(
        CharSequence originalText, Locale loc) {
    SpannableStringBuilder myLocaleBuilder =
            new SpannableStringBuilder(originalText);
    myLocaleBuilder.setSpan(new LocaleSpan(loc), 0,
            originalText.length() - 1, 0);
    return myLocaleBuilder;
}

للمزيد من المعلومات، يمكنك مشاهدة فيديو جلسة الميزات الجديدة في إمكانية الوصول إلى Android من مؤتمر Google I/O لعام 2017، بدءًا من 10:59.

التصرف نيابةً عن المستخدمين

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

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

الاستماع إلى الإيماءات

يمكن لخدمات تسهيل الاستخدام الاستماع إلى إيماءات محددة والاستجابة من خلال اتخاذ إجراءات نيابةً عن المستخدم. تتطلّب هذه الميزة تلبية طلبك لخدمة تسهيل الاستخدام. تفعيل ميزة "الاستكشاف باللمس" يمكن لخدمتك طلب هذا الإذن التنشيط من خلال تعيين flags عضو في مثيل AccessibilityServiceInfo للخدمة FLAG_REQUEST_TOUCH_EXPLORATION_MODE, كما هو موضح في المثال التالي.

Kotlin

class MyAccessibilityService : AccessibilityService() {

    override fun onCreate() {
        serviceInfo.flags = AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE
    }
    ...
}

Java

public class MyAccessibilityService extends AccessibilityService {
    @Override
    public void onCreate() {
        getServiceInfo().flags = AccessibilityServiceInfo.FLAG_REQUEST_TOUCH_EXPLORATION_MODE;
    }
    ...
}

بعد أن تطلب الخدمة تفعيل ميزة Explore by Touch، يجب أن يسمح المستخدم أن يتم تشغيل الميزة إذا لم تكن نشطة بالفعل. عندما تكون هذه الميزة نشطة، تتلقى خدمتك إشعارًا بإيماءات إمكانية الوصول من خلال الخاص بخدمتك onGesture() ويمكنها الرد من خلال التصرف نيابةً عن المستخدم.

الإيماءات المستمرة

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

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

Kotlin

// Simulates an L-shaped drag path: 200 pixels right, then 200 pixels down.
private fun doRightThenDownDrag() {
    val dragRightPath = Path().apply {
        moveTo(200f, 200f)
        lineTo(400f, 200f)
    }
    val dragRightDuration = 500L // 0.5 second

    // The starting point of the second path must match
    // the ending point of the first path.
    val dragDownPath = Path().apply {
        moveTo(400f, 200f)
        lineTo(400f, 400f)
    }
    val dragDownDuration = 500L
    val rightThenDownDrag = GestureDescription.StrokeDescription(
            dragRightPath,
            0L,
            dragRightDuration,
            true
    ).apply {
        continueStroke(dragDownPath, dragRightDuration, dragDownDuration, false)
    }
}

Java

// Simulates an L-shaped drag path: 200 pixels right, then 200 pixels down.
private void doRightThenDownDrag() {
    Path dragRightPath = new Path();
    dragRightPath.moveTo(200, 200);
    dragRightPath.lineTo(400, 200);
    long dragRightDuration = 500L; // 0.5 second

    // The starting point of the second path must match
    // the ending point of the first path.
    Path dragDownPath = new Path();
    dragDownPath.moveTo(400, 200);
    dragDownPath.lineTo(400, 400);
    long dragDownDuration = 500L;
    GestureDescription.StrokeDescription rightThenDownDrag =
            new GestureDescription.StrokeDescription(dragRightPath, 0L,
            dragRightDuration, true);
    rightThenDownDrag.continueStroke(dragDownPath, dragRightDuration,
            dragDownDuration, false);
}

للمزيد من المعلومات، يمكنك مشاهدة فيديو جلسة الميزات الجديدة في إمكانية الوصول إلى Android من مؤتمر Google I/O لعام 2017، بدءًا من 15:47.

استخدام إجراءات تسهيل الاستخدام

يمكن لخدمات تسهيل الاستخدام التصرف نيابةً عن المستخدمين لتسهيل التفاعل مع التطبيقات وزيادة إنتاجيتك. يمكن لخدمات سهولة الوصول لإضافة إجراءات جديدة عام 2011 ووسّعنا نطاق تنفيذ الإجراءات بشكلٍ كبير في عام 2012.

للتصرف نيابةً عن المستخدمين، يجب أن تسجّل خدمة تسهيل الاستخدام الخاصة بك. تلقّي أحداث من التطبيقات وطلب إذن للاطّلاع على المحتوى من التطبيقات عن طريق ضبط android:canRetrieveWindowContent على true في ملف إعداد الخدمة. عند استلام الأحداث من قِبل خدمة البيانات، فيمكنها حينئذٍ استرداد AccessibilityNodeInfo من الحدث باستخدام getSource() باستخدام الكائن AccessibilityNodeInfo، يمكن لخدمتك بعد ذلك استكشاف العرض. التسلسل الهرمي لتحديد الإجراء الذي يجب اتخاذه ثم التصرف للمستخدم باستخدام performAction()

Kotlin

class MyAccessibilityService : AccessibilityService() {

    override fun onAccessibilityEvent(event: AccessibilityEvent) {
        // Get the source node of the event.
        event.source?.apply {

            // Use the event and node information to determine what action to
            // take.

            // Act on behalf of the user.
            performAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD)

            // Recycle the nodeInfo object.
            recycle()
        }
    }
    ...
}

Java

public class MyAccessibilityService extends AccessibilityService {

    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        // Get the source node of the event.
        AccessibilityNodeInfo nodeInfo = event.getSource();

        // Use the event and node information to determine what action to take.

        // Act on behalf of the user.
        nodeInfo.performAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);

        // Recycle the nodeInfo object.
        nodeInfo.recycle();
    }
    ...
}

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

استخدام أنواع التركيز

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

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

يمكن لخدمة إمكانية الوصول تحديد عنصر واجهة المستخدم الذي يحتوي على إدخالات التركيز أو سهولة الوصول باستخدام AccessibilityNodeInfo.findFocus() . يمكنك أيضًا البحث عن العناصر التي يمكن اختيارها بالتركيز على الإدخال. باستخدام focusSearch() . وأخيرًا، يمكن لخدمة تسهيل الاستخدام ضبط تركيز إمكانية الوصول باستخدام الـ performAction(AccessibilityNodeInfo.ACTION_SET_ACCESSIBILITY_FOCUS) .

جمع المعلومات

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

الحصول على تفاصيل تغيير النافذة

يتيح الإصدار 9 (المستوى 28 من واجهة برمجة التطبيقات) والإصدارات الأحدث للتطبيقات إمكانية تتبُّع تحديثات النوافذ عند يعيد التطبيق رسم نوافذ متعددة في وقت واحد. عندما TYPE_WINDOWS_CHANGED وقوع الحدث، فاستخدم getWindowChanges() واجهة برمجة التطبيقات لتحديد كيفية تغيير النوافذ. أثناء التحديث عبر النوافذ المتعددة، يقابل كل تنتج نافذة مجموعة الأحداث الخاصة بها. تُرجع الطريقة getSource() الجذر لعرض النافذة المرتبطة بكل حدث.

إذا كان التطبيق يُعرِّف جزء إمكانية الوصول للمحتوى الخاص بها View، يمكن لخدمتك التعرّف على الوقت الذي يتم تحديث واجهة المستخدم الخاصة بالتطبيق. عندما TYPE_WINDOW_STATE_CHANGED وقوع الحدث، فاستخدم الأنواع التي تم إرجاعها بواسطة getContentChangeTypes() لتحديد كيفية تغير النافذة. على سبيل المثال، يمكن لإطار العمل اكتشاف متى جزء له عنوان جديد أو عندما يختفي جزء.

الحصول على تفاصيل الحدث

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

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

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

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

  • AccessibilityEvent.getRecordCount() أو getRecord(int): تتيح لك هذه الطرق استرداد مجموعة AccessibilityRecord الكائنات التي تساهم في AccessibilityEvent الذي يتم تمريره إليك من خلال . يوفر هذا المستوى من التفاصيل مزيدًا من السياق للحدث الذي يؤدي إلى تشغيل خدمة إمكانية الوصول لديك.

  • AccessibilityRecord.getSource(): تُنتج هذه الطريقة كائن AccessibilityNodeInfo. يتيح لك هذا الكائن طلب العرض الهرمي لتخطيط العرض (الأصل والفرعي) للمكون الذي يؤدي إلى حدث إمكانية الوصول. تتيح هذه الميزة إمكانية الوصول في السياق الكامل لحدث ما، بما في ذلك محتوى أي وجهات نظر شاملة أو وجهات نظر الأطفال.

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

android:canRetrieveWindowContent="true"

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

في المثال التالي، تنفِّذ الرمز الإجراءات التالية عند تلقّي حدث:

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

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

Kotlin

// Alternative onAccessibilityEvent that uses AccessibilityNodeInfo.

override fun onAccessibilityEvent(event: AccessibilityEvent) {

    val source: AccessibilityNodeInfo = event.source ?: return

    // Grab the parent of the view that fires the event.
    val rowNode: AccessibilityNodeInfo = getListItemNodeInfo(source) ?: return

    // Using this parent, get references to both child nodes, the label, and the
    // checkbox.
    val taskLabel: CharSequence = rowNode.getChild(0)?.text ?: run {
        rowNode.recycle()
        return
    }

    val isComplete: Boolean = rowNode.getChild(1)?.isChecked ?: run {
        rowNode.recycle()
        return
    }

    // Determine what the task is and whether it's complete based on the text
    // inside the label, and the state of the checkbox.
    if (rowNode.childCount < 2 || !rowNode.getChild(1).isCheckable) {
        rowNode.recycle()
        return
    }

    val completeStr: String = if (isComplete) {
        getString(R.string.checked)
    } else {
        getString(R.string.not_checked)
    }
    val reportStr = "$taskLabel$completeStr"
    speakToUser(reportStr)
}

Java

// Alternative onAccessibilityEvent that uses AccessibilityNodeInfo.

@Override
public void onAccessibilityEvent(AccessibilityEvent event) {

    AccessibilityNodeInfo source = event.getSource();
    if (source == null) {
        return;
    }

    // Grab the parent of the view that fires the event.
    AccessibilityNodeInfo rowNode = getListItemNodeInfo(source);
    if (rowNode == null) {
        return;
    }

    // Using this parent, get references to both child nodes, the label, and the
    // checkbox.
    AccessibilityNodeInfo labelNode = rowNode.getChild(0);
    if (labelNode == null) {
        rowNode.recycle();
        return;
    }

    AccessibilityNodeInfo completeNode = rowNode.getChild(1);
    if (completeNode == null) {
        rowNode.recycle();
        return;
    }

    // Determine what the task is and whether it's complete based on the text
    // inside the label, and the state of the checkbox.
    if (rowNode.getChildCount() < 2 || !rowNode.getChild(1).isCheckable()) {
        rowNode.recycle();
        return;
    }

    CharSequence taskLabel = labelNode.getText();
    final boolean isComplete = completeNode.isChecked();
    String completeStr = null;

    if (isComplete) {
        completeStr = getString(R.string.checked);
    } else {
        completeStr = getString(R.string.not_checked);
    }
    String reportStr = taskLabel + completeStr;
    speakToUser(reportStr);
}

الآن لديك خدمة إمكانية وصول كاملة وفعّالة. جرِّب ضبط كيفية إجراء ذلك. تتفاعل مع المستخدم من خلال إضافة ميزة تحويل النص إلى كلام في Android المحرّك أو استخدام Vibrator لتوفير اللمس الملاحظات.

نص العملية

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

التلميحات

يقدّم Android 9 (المستوى 28 من واجهة برمجة التطبيقات) العديد من الإمكانات التي تتيح لك الوصول إلى تلميحات في واجهة مستخدم التطبيق. استخدام getTooltipText() لقراءة نص التلميح، واستخدام ACTION_SHOW_TOOLTIP أو ACTION_HIDE_TOOLTIP لتوجيه أمثلة View إلى إظهار التلميحات الخاصة بها أو إخفائها.

نص التلميح

بدءًا من عام 2017، يتضمن نظام Android العديد من الطرق للتفاعل مع نص تلميح كائن قائم على النص:

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

مواقع أحرف النص التي تظهر على الشاشة

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

القيم الموحّدة لنطاق من جانب واحد

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

  • بالنسبة إلى النطاقات التي ليس لها حدّ أدنى، Float.NEGATIVE_INFINITY تمثل الحد الأدنى للقيمة.
  • بالنسبة إلى النطاقات التي ليس لها حدّ أقصى، Float.POSITIVE_INFINITY القيمة القصوى.

الاستجابة لأحداث تسهيل الاستخدام

والآن بعد أن تم إعداد الخدمة لتشغيل الأحداث والاستماع إليها، اكتب الرمز بحيث يعرف ما يجب فعله عند وصول AccessibilityEvent. ابدأ بتجاوز onAccessibilityEvent(AccessibilityEvent) . في هذه الطريقة، استخدم getEventType() لتحديد نوع الحدث getContentDescription() لاستخراج أي نص تصنيف مرتبط بالملف الشخصي الذي يؤدّي إلى تنشيط الحدث:

Kotlin

override fun onAccessibilityEvent(event: AccessibilityEvent) {
    var eventText: String = when (event.eventType) {
        AccessibilityEvent.TYPE_VIEW_CLICKED -> "Clicked: "
        AccessibilityEvent.TYPE_VIEW_FOCUSED -> "Focused: "
        else -> ""
    }

    eventText += event.contentDescription

    // Do something nifty with this text, like speak the composed string back to
    // the user.
    speakToUser(eventText)
    ...
}

Java

@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
    final int eventType = event.getEventType();
    String eventText = null;
    switch(eventType) {
        case AccessibilityEvent.TYPE_VIEW_CLICKED:
            eventText = "Clicked: ";
            break;
        case AccessibilityEvent.TYPE_VIEW_FOCUSED:
            eventText = "Focused: ";
            break;
    }

    eventText = eventText + event.getContentDescription();

    // Do something nifty with this text, like speak the composed string back to
    // the user.
    speakToUser(eventText);
    ...
}

مصادر إضافية

لمزيد من المعلومات، يمكنك الاطّلاع على المراجع التالية:

الأدلّة

الدروس التطبيقية حول الترميز