Eine Bedienungshilfe ist eine App, die die Benutzeroberfläche verbessert, Nutzende mit Beeinträchtigungen oder Personen, die vorübergehend nicht in der Lage sind, mit einem Gerät. Zum Beispiel Nutzer, die Auto fahren, sich um ein Kleinkind kümmern, oder die Teilnahme an einer sehr lauten Party Feedback geben.
Android bietet standardmäßige Bedienungshilfen wie TalkBack und Entwickler können ihre eigenen Dienste erstellen und vertreiben. Dieses Dokument werden die Grundlagen der Erstellung einer Bedienungshilfe erläutert.
Eine Bedienungshilfe kann mit einer normalen App gebündelt oder als ein eigenständiges Android-Projekt erstellen. Die Schritte zum Erstellen des Dienstes sind dieselben in beiden Situationen.
Bedienungshilfe erstellen
Erstellen Sie innerhalb Ihres Projekts eine Klasse, die
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() { } ... }
Sie erstellen ein neues Projekt für Service
und möchten keine App haben
verknüpft sind, können Sie die Starter-Klasse Activity
aus Ihrem
Quelle.
Manifestdeklarationen und Berechtigungen
Für Apps, die Bedienungshilfen anbieten, müssen bestimmte Erklärungen in ihre App-Manifeste so zu definieren, dass sie vom Android-Team als Bedienungshilfe behandelt werden. System. In diesem Abschnitt werden die erforderlichen und optionalen Einstellungen für Bedienungshilfen.
Erklärung zu Bedienungshilfen
Damit deine App als Bedienungshilfe behandelt werden kann, musst du einen service
hinzufügen.
statt des activity
-Elements innerhalb von application
.
-Element in Ihrem Manifest. Fügen Sie außerdem im service
-Element ein
Intent-Filter für Bedienungshilfen. Das Manifest muss auch den Dienst schützen
indem Sie den Parameter
BIND_ACCESSIBILITY_SERVICE
damit nur das System eine Bindung
daran vornehmen kann. Beispiel:
<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>
Konfiguration der Bedienungshilfen
Bedienungshilfen müssen eine Konfiguration bereitstellen, in der die Arten von
Bedienungshilfen, die der Dienst verarbeitet, und zusätzliche Informationen zu
für den Dienst. Die Konfiguration einer Bedienungshilfe ist in der
AccessibilityServiceInfo
. Ihr Dienst kann eine Konfiguration mithilfe einer Instanz dieses
Klasse und
setServiceInfo()
während der Laufzeit. Allerdings sind damit nicht alle Konfigurationsoptionen verfügbar.
.
Du kannst in dein Manifest ein <meta-data>
-Element mit einem Verweis auf ein
Konfigurationsdatei, mit der Sie alle Optionen für Ihre
Bedienungshilfe wie im folgenden Beispiel gezeigt:
<service android:name=".MyAccessibilityService"> ... <meta-data android:name="android.accessibilityservice" android:resource="@xml/accessibility_service_config" /> </service>
Dieses <meta-data>
-Element verweist auf eine XML-Datei, die du in deinem
im Ressourcenverzeichnis der Anwendung ein:
<project_dir>/res/xml/accessibility_service_config.xml>
. Der folgende Code
zeigt ein Beispiel für den Inhalt der Dienstkonfigurationsdatei:
<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" />
Weitere Informationen zu den XML-Attributen, die in der Konfigurationsdatei für Bedienungshilfen-Dienst (siehe folgende Referenz) Dokumentation:
android:description
android:packageNames
android:accessibilityEventTypes
android:accessibilityFlags
android:accessibilityFeedbackType
android:notificationTimeout
android:canRetrieveWindowContent
android:settingsActivity
Weitere Informationen dazu, welche Konfigurationseinstellungen dynamisch festgelegt werden können
sehen Sie sich die
AccessibilityServiceInfo
in der Referenzdokumentation.
Bedienungshilfe konfigurieren
Beachten Sie beim Festlegen der Konfigurationsvariablen für Ihre Bedienungshilfe, um dem System mitzuteilen, wie und wann es ausgeführt werden soll:
- Auf welche Ereignistypen soll die Funktion reagieren?
- Muss der Dienst für alle Apps oder nur für ein bestimmtes Paket aktiv sein Namen?
- Welche verschiedenen Feedbacktypen werden verwendet?
Sie haben zwei Möglichkeiten, diese Variablen festzulegen. Die abwärtskompatible Option
im Code festlegen, indem Sie
setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)
Dazu überschreiben Sie
onServiceConnected()
und konfigurieren Sie dort Ihren Dienst, wie im folgenden Beispiel gezeigt:
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); }
Die zweite Möglichkeit besteht darin, den Dienst mithilfe einer XML-Datei zu konfigurieren. Bestimmte
Konfigurationsoptionen wie
canRetrieveWindowContent
,
sind nur verfügbar, wenn Sie Ihren Dienst mit XML konfigurieren. Die Konfiguration
Die Optionen aus dem vorherigen Beispiel sehen wie folgt aus, wenn sie mit XML definiert wurden:
<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" />
Wenn Sie XML verwenden, verweisen Sie in Ihrem Manifest darauf, indem Sie ein
<meta-data>
-Tag zu Ihrem
Service-Deklaration, die auf die XML-Datei verweist. Wenn Sie Ihre XML-Datei in
res/xml/serviceconfig.xml
, sieht das neue Tag so aus:
<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>
Methoden für Bedienungshilfen
Eine Bedienungshilfe muss die AccessibilityService
-Klasse und
die folgenden Methoden dieser Klasse überschreiben. Diese Methoden werden in
Die Reihenfolge, in der sie vom Android-System aufgerufen werden: ab dem Start des Dienstes
(onServiceConnected()
) bis während der Ausführung
(onAccessibilityEvent()
,
onInterrupt()
)
bis zum Herunterfahren
(onUnbind()
)
onServiceConnected()
(optional): Das System ruft diese Methode auf, wenn sie eine Verbindung zu Ihrer Bedienungshilfe herstellen. Diese Methode für eine einmalige Einrichtung verwenden Schritte für Ihren Dienst, einschließlich der Verbindung mit dem Nutzerfeedbacksystem z. B. den Audio-Manager oder die Vibrator-App. Wenn Sie Konfiguration Ihres Dienstes während der Laufzeit oder nehmen Sie einmalige Anpassungen vor, Hier kannst dusetServiceInfo()
anrufen.onAccessibilityEvent()
(erforderlich): Das System ruft diese Methode zurück, wenn wird ein Fehler erkannt,AccessibilityEvent
die den Parametern für die Ereignisfilterung entspricht, die Sie über die Bedienungshilfen festgelegt haben z. B. wenn Nutzende auf eine Schaltfläche tippen oder sich auf eine Benutzeroberfläche konzentrieren in einer App, für die Ihre Bedienungshilfe Feedback gibt. Wann? ruft das System diese Methode auf, übergibt es die zugehörigeAccessibilityEvent
, die der Dienst dann interpretieren und verwenden kann, um dem Nutzer. Diese Methode kann während des Lebenszyklus Ihrer .onInterrupt()
(erforderlich): Das System ruft diese Methode auf, wenn das System möchte das Feedback, das Ihr Dienst bereitstellt, unterbrechen. Dies geschieht normalerweise in Reaktion auf eine Nutzeraktion, z. B. das Verschieben des Fokus auf ein anderes Steuerelement Dieses kann im Lebenszyklus Ihres Dienstes mehrmals aufgerufen werden.onUnbind()
(optional): Diese Methode wird aufgerufen, wenn das System die Bedienungshilfe beenden wird. Mit dieser Methode können Sie einmaliges Herunterfahren, einschließlich Aufheben der Zuweisung von Nutzerfeedbacksystem z. B. den Audio-Manager oder die Vibrator-App.
Diese Callback-Methoden bieten die Grundstruktur für Bedienungshilfen
. Sie können entscheiden, wie die vom Android-System bereitgestellten Daten verarbeitet werden.
in Form von AccessibilityEvent
-Objekten erstellen und dem Nutzer Feedback geben. Für
Weitere Informationen zum Abrufen von Informationen aus Bedienungshilfen-Ereignissen finden Sie unter Getränke
.
Für Veranstaltungen zur Barrierefreiheit registrieren
Eine der wichtigsten Funktionen der Konfiguration der Bedienungshilfen können Sie angeben, welche Arten von Bedienungshilfen-Ereignissen Ihr Dienst die Sie bewältigen können. Wenn Sie diese Informationen angeben, können Bedienungshilfen und können flexibel auf bestimmte Ereignisse aus bestimmten Apps. Das Filtern von Ereignissen kann Folgendes umfassen: Kriterien:
Paketnamen:Geben Sie die Paketnamen von Apps an, deren Bedienungshilfen Ereignisse, die Ihr Dienst verarbeiten soll. Falls Sie diesen Parameter nicht angeben, Bedienungshilfen gelten für jede App. Sie können diesen Parameter in der Bedienungshilfe Konfigurationsdateien mit dem Attribut
android:packageNames
als kommagetrennte Liste eingeben oder die MethodeAccessibilityServiceInfo.packageNames
Mitglied.Ereignistypen:Geben Sie die Arten von Bedienungshilfen-Ereignissen an, die Ihre zu verwalten. Sie können diesen Parameter in der Bedienungshilfe Konfigurationsdateien mit dem Attribut
android:accessibilityEventTypes
als Eine Liste, die durch das Zeichen|
getrennt ist, z. B.accessibilityEventTypes="typeViewClicked|typeViewFocused"
Sie können auch mithilfe derAccessibilityServiceInfo.eventTypes
Mitglied.
Überlegen Sie sich bei der Einrichtung Ihrer Bedienungshilfe genau, welche Ereignisse diese Ereignisse verarbeiten und nur registrieren können. Da Nutzer mehrere Bedienungshilfen gleichzeitig nutzen, darf Ihr Dienst keine die es nicht verarbeiten kann. Denken Sie daran, dass andere Dienste um die User Experience zu verbessern.
Lautstärke der Bedienungshilfen
Für Geräte mit Android 8.0 (API-Level 26) und höher ist die
STREAM_ACCESSIBILITY
Lautstärke, mit der Sie die Lautstärke Ihrer Bedienungshilfen
Audioausgabe des Dienstes unabhängig von anderen Tönen auf dem Gerät.
Bedienungshilfen können diesen Streamtyp verwenden, indem sie die
FLAG_ENABLE_ACCESSIBILITY_VOLUME
Option. Anschließend kannst du die Audiolautstärke des Geräts für Bedienungshilfen ändern, indem du
die
adjustStreamVolume()
auf der Geräteinstanz
AudioManager
Das folgende Code-Snippet zeigt, wie eine Bedienungshilfe den Code
STREAM_ACCESSIBILITY
Volumenkategorie:
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); } } }
Weitere Informationen finden Sie im Video zu den Neuerungen bei der Android-Barrierefreiheit im Internet von der Google I/O 2017, das unter 06:35.
Kurzbefehl für Bedienungshilfen
Auf Geräten mit Android 8.0 (API-Level 26) und höher können Nutzer die bevorzugte Bedienungshilfe durch Drücken und und halten Sie beide Lautstärketasten gleichzeitig gedrückt. Obwohl diese Tastenkombination standardmäßig TalkBack deaktiviert, können Nutzer die Schaltfläche so konfigurieren, alle auf dem Gerät installierten Dienste zu deaktivieren.
Damit Nutzende über die Bedienungshilfen muss der Dienst die Funktion zur Laufzeit anfordern.
Weitere Informationen finden Sie im Video zu den Neuerungen bei der Android-Barrierefreiheit im Internet von der Google I/O 2017, das unter 13:25.
Schaltfläche „Bedienungshilfen“
Auf Geräten mit einem von Software gerenderten Navigationsbereich und Android 8.0 (API-Ebene 26) oder höher enthält, befindet sich auf der rechten Seite der Navigationsleiste Schaltfläche „Bedienungshilfen“. Wenn Nutzer auf diese Schaltfläche klicken, können sie eine der folgenden Aktionen aufrufen: Bedienungshilfen und -Dienste aktiviert haben, je nach Inhalt die aktuell auf dem Bildschirm angezeigt werden.
Damit Nutzer eine bestimmte Bedienungshilfe mithilfe der
muss der Dienst den Parameter
FLAG_REQUEST_ACCESSIBILITY_BUTTON
Flag im android:accessibilityFlags
eines AccessibilityServiceInfo
-Objekts.
. Der Dienst kann dann Callbacks mithilfe von
registerAccessibilityButtonCallback()
Im folgenden Code-Snippet sehen Sie, wie Sie Bedienungshilfen , um zu reagieren, wenn der Nutzer die Schaltfläche „Bedienungshilfen“ drückt:
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); } }
Weitere Informationen finden Sie im Video zu den Neuerungen bei der Android-Barrierefreiheit im Internet von der Google I/O 2017, das unter 16:28.
Touch-Gesten auf dem Fingerabdrucksensor
Bedienungshilfen auf Geräten mit Android 8.0 (API-Level 26) oder höher auf Wischbewegungen (nach oben, unten, links und rechts) entlang des Fingerabdrucksensor verwenden. So konfigurieren Sie einen Dienst für den Empfang von Callbacks zu diesen -Interaktionen, führen Sie die folgende Sequenz aus:
USE_BIOMETRIC
deklarieren und dieCAPABILITY_CAN_REQUEST_FINGERPRINT_GESTURES
- Legen Sie die
FLAG_REQUEST_FINGERPRINT_GESTURES
fest. im Attributandroid:accessibilityFlags
. - Registrieren Sie sich mit
registerFingerprintGestureCallback()
für Callbacks.
Denken Sie daran, dass nicht alle Geräte einen Fingerabdrucksensor haben. Zur Identifizierung
ob ein Gerät den Sensor unterstützt,
isHardwareDetected()
. Auch auf einem Gerät mit Fingerabdrucksensor kann Ihr Dienst
den Sensor zur Authentifizierung verwenden. Um zu ermitteln, wann
wenn der Sensor verfügbar ist, rufen Sie
isGestureDetectionAvailable()
und implementieren die
onGestureDetectionAvailabilityChanged()
Callback des Nutzers an.
Das folgende Code-Snippet zeigt ein Beispiel für die Verwendung von auf einem virtuellen Spielfeld navigieren:
// 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); } } }
Weitere Informationen finden Sie im Video zu den Neuerungen bei der Android-Barrierefreiheit im Internet von der Google I/O 2017, das unter 09:03.
Mehrsprachige Sprachausgabe
Ab Android 8.0 (API-Level 26) der Sprachausgabe-Dienst von Android
kann Sätze in mehreren Sprachen innerhalb eines einzigen Blocks von
Text. Um diese Funktion zum automatischen Sprachwechsel
in einer Bedienungshilfe zu aktivieren,
Service, packen Sie alle Zeichenfolgen in
LocaleSpan
-Objekte, wie gezeigt
im folgenden Code-Snippet einfügen:
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; }
Weitere Informationen finden Sie im Video zu den Neuerungen bei der Android-Barrierefreiheit im Internet von der Google I/O 2017, das unter 22:59.
Im Namen von Nutzern handeln
Seit 2011 dürfen Bedienungshilfen im Namen von Nutzern handeln, darunter Ändern des Eingabefokus und Auswählen (Aktivieren) von Elementen der Benutzeroberfläche In 2012 wurde der Umfang der Aktionen um Scroll-Listen und Interaktionen erweitert. mit Textfeldern. Bedienungshilfen können auch globale Maßnahmen ergreifen, z. B. zum Startbildschirm navigieren, die Zurück-Taste drücken und die Benachrichtigungen und die Liste der zuletzt verwendeten Apps. Seit 2012 umfasst Android Fokus für Bedienungshilfen, bei dem alle sichtbaren Elemente Bedienungshilfe.
Mit diesen Funktionen können Entwickler von Bedienungshilfen wie die Bedienung über Gesten und ermöglichen es Nutzern mit Beeinträchtigungen, ihre Android-Geräte besser steuern können.
Auf Gesten achten
Bedienungshilfen können bestimmte Gesten erkennen und reagieren,
im Namen eines Nutzers. Für diese Funktion muss Ihre Bedienungshilfeanfrage
Aktivierung der Funktion "Tippen & Entdecken". Ihr Dienst kann dies anfordern
aktivieren, indem Sie die
flags
Mitglied der Instanz AccessibilityServiceInfo
des Dienstes,
FLAG_REQUEST_TOUCH_EXPLORATION_MODE
,
wie im folgenden Beispiel gezeigt.
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; } ... }
Nachdem Ihr Dienst die Aktivierung von Tippen & Entdecken angefordert hat, muss der Nutzer
die Funktion aktiviert werden, falls sie noch nicht aktiv ist. Wenn diese Funktion
aktiviert ist, erhält Ihr Dienst über Touch-Gesten für Bedienungshilfen
Ihres Dienstes
onGesture()
und kann so antworten, indem er im Namen des Nutzers handelt.
Fortlaufende Touch-Gesten
Geräte mit Android 8.0 (API-Level 26) unterstützen fortlaufende Touch-Gesten oder
programmatische Gesten, die mehrere
Path
-Objekt.
Beim Festlegen einer Abfolge von Strichen können Sie festlegen, dass sie zum
programmatischer Geste durch Verwendung des letzten Arguments willContinue
im
GestureDescription.StrokeDescription
wie im folgenden Code-Snippet gezeigt:
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); }
Weitere Informationen finden Sie im Video zu den Neuerungen bei der Android-Barrierefreiheit im Internet von der Google I/O 2017, das unter 15:47.
Aktionen für Bedienungshilfen verwenden
Bedienungshilfen können im Namen von Nutzern agieren, um die Interaktion mit und produktiver sein können. Die Fähigkeit von Bedienungshilfen, 2011 wurde das Tool zum Ausführen von Aktionen eingeführt und 2012 erheblich erweitert.
Damit Sie im Namen von Nutzern handeln können, muss die Bedienungshilfe registriert sein.
um Ereignisse von Apps zu erhalten und die Berechtigung zum Ansehen der Inhalte anzufordern
der Apps, indem Sie android:canRetrieveWindowContent
auf true
setzen
Dienstkonfigurationsdatei. Wenn Ereignisse in Ihrem
kann er die Daten abrufen,
AccessibilityNodeInfo
aus dem Ereignis aus, indem Sie
getSource()
Mit dem AccessibilityNodeInfo
-Objekt kann Ihr Dienst dann die Ansicht erkunden
um zu bestimmen, welche Aktion ausgeführt werden soll.
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(); } ... }
Mit der Methode performAction()
kann Ihr Dienst Aktionen innerhalb eines
Wenn Ihr Dienst eine globale Aktion ausführen muss, z. B.
zum Startbildschirm navigieren, auf die Schaltfläche "Zurück" tippen oder die
auf dem Benachrichtigungsbildschirm oder in der Liste der zuletzt verwendeten Apps
performGlobalAction()
.
Fokustypen verwenden
2012 wurde bei Android der Fokus auf der Benutzeroberfläche mit dem Namen Schwerpunkt auf Barrierefreiheit eingeführt. Bedienungshilfen können mit diesem Fokus jede sichtbare Benutzeroberfläche auswählen und auf das Element reagieren. Dieser Fokustyp unterscheidet sich vom Eingabefokus, mit dem welches Benutzeroberflächenelement auf dem Bildschirm eine Eingabe empfängt, gibt Zeichen ein, drückt die Eingabetaste auf einer Tastatur oder drückt die Mitte auf einem Steuerkreuz.
Es ist möglich, dass ein Element in einer Benutzeroberfläche den Eingabefokus hat, während ein anderes Element im Fokus steht. Der Zweck des Fokus auf Barrierefreiheit um Bedienungshilfen eine Methode zur Interaktion mit sichtbaren Elemente auf einem Bildschirm sichtbar sind, unabhängig davon, ob das Element aus einer Systemperspektive. Um sicherzustellen, dass die Bedienungshilfe mit mit der App richtig -Eingabeelemente verwenden, befolgen Sie die Richtlinien zum Testen der Zugänglichkeit, um deinen Dienst zu testen während der Nutzung einer typischen App.
Eine Bedienungshilfe kann festlegen, welches Benutzeroberflächenelement Eingaben enthält.
oder Bedienungshilfen mithilfe der
AccessibilityNodeInfo.findFocus()
. Sie können auch nach Elementen suchen, die mit dem Eingabefokus ausgewählt werden können
mithilfe der
focusSearch()
. Schließlich kann Ihre Bedienungshilfe den Fokus auf Barrierefreiheit mithilfe
die
performAction(AccessibilityNodeInfo.ACTION_SET_ACCESSIBILITY_FOCUS)
.
Informationen sammeln
Bedienungshilfen haben Standardmethoden, um Schlüssel Einheiten mit von Nutzern bereitgestellten Informationen wie Ereignisdetails, Text und Zahlen
Details zu Fensteränderungen abrufen
Mit Android 9 (API-Level 28) und höher können Apps Fensterupdates nachverfolgen,
in einer App mehrere Fenster
gleichzeitig neu zeichnen. Wenn ein
TYPE_WINDOWS_CHANGED
Ereignis auftritt, verwenden Sie den
getWindowChanges()
API, um zu ermitteln, wie sich die Fenster ändern. Während eines Updates im Mehrfenstermodus wird jeder
generiert einen eigenen Satz von Ereignissen. Die Methode getSource()
gibt den Stamm zurück
Ansicht des mit jedem Ereignis verknüpften Fensters.
Wenn eine App den Bereich für Bedienungshilfen
für seine
View
-Objekten verwendet, kann Ihr Dienst erkennen,
wird die Benutzeroberfläche der App aktualisiert. Wenn ein
TYPE_WINDOW_STATE_CHANGED
Ereignis auftritt, verwenden Sie die vom
getContentChangeTypes()
um zu bestimmen, wie sich das Fenster ändert. Beispielsweise kann das Framework erkennen,
wenn ein Bereich einen neuen Titel hat oder wenn er ausgeblendet wird.
Termindetails abrufen
Android stellt Bedienungshilfen Informationen zur Benutzeroberfläche zur Verfügung.
über AccessibilityEvent
-Objekte interagieren. In früheren Android-Versionen
die bei einer Veranstaltung zur Barrierefreiheit verfügbar sind, und bieten gleichzeitig
Details zum von Nutzern ausgewählten Steuerelement auf der Benutzeroberfläche (eingeschränkt angeboten)
Kontextinformationen. In vielen Fällen können diese fehlenden Kontextinformationen
ist wichtig, um die Bedeutung
der ausgewählten Einstellung zu verstehen.
Ein Beispiel für eine Schnittstelle, bei der der Kontext entscheidend ist, ist ein Kalender oder ein Tag im Planer. Wenn der Nutzer ein Zeitfenster von 16:00 Uhr in einer Liste mit Tagen von Montag bis Freitag auswählt und die Bedienungshilfe „16 Uhr“ ankündigt, aber nicht den Wochentag. Name, Tag des Monats oder Monatsnamen, ist das resultierende Feedback verwirrend sein. In diesem Fall ist der Kontext eines UI-Steuerelements entscheidend, Nutzende, die eine Besprechung planen möchten.
Seit 2011 erweitert Android die Menge an Informationen, die ein Informationen zu Interaktionen auf der Benutzeroberfläche erhalten, basierend auf der Ansichtshierarchie. Eine Ansichtshierarchie ist ein Satz Komponenten der Benutzeroberfläche, die die Komponente (ihre übergeordneten Elemente) und den Nutzer enthalten Oberflächenelemente, die in dieser Komponente (untergeordnete Elemente) enthalten sein können. In So kann Android ausführlichere Informationen zu Bedienungshilfen-Ereignissen liefern, Bedienungshilfen bieten den Nutzenden nützlicheres Feedback.
Eine Bedienungshilfe ruft Informationen zu einem Benutzeroberflächenereignis über
eine AccessibilityEvent
, die vom System an die Methode
onAccessibilityEvent()
. Dieses Objekt liefert Details zum
Ereignis, einschließlich des Objekts, für das eine Aktion durchgeführt wird, seines Beschreibungstexts und
weitere Details.
AccessibilityEvent.getRecordCount()
undgetRecord(int)
: Mit diesen Methoden können SieAccessibilityRecord
-Objekte, die zurAccessibilityEvent
beitragen, die vom System. Diese Detailebene liefert mehr Kontext für das Ereignis, das die Bedienungshilfe auslöst.AccessibilityRecord.getSource()
: Diese Methode gibt einAccessibilityNodeInfo
-Objekt zurück. Mit diesem Objekt können Sie die Ansichtslayouthierarchie (über- und untergeordnete Elemente) der Komponente anfordern, das Bedienungshilfen-Ereignis. Mit dieser Funktion können Bedienungshilfen Dienst untersuchen den gesamten Kontext eines Ereignisses, einschließlich Inhalt und der einschließenden oder untergeordneten Ansichten angezeigt.
Auf der Android-Plattform kann ein AccessibilityService
Abfragen ausführen
Ansichtshierarchie. Dabei werden Informationen zur UI-Komponente erfasst, die
einem Ereignis sowie dessen über- und untergeordnete Elemente. Legen Sie dazu folgende Zeile fest:
in Ihrer XML-Konfiguration:
android:canRetrieveWindowContent="true"
Anschließend rufen Sie mit getSource()
ein AccessibilityNodeInfo
-Objekt ab.
Bei diesem Aufruf wird nur dann ein Objekt zurückgegeben, wenn das Fenster, von dem das Ereignis stammt,
immer noch das aktive Fenster ist. Wenn nicht, wird null zurückgegeben. Gehen Sie also entsprechend vor.
Im folgenden Beispiel führt der Code folgende Schritte aus, wenn ein Ereignis empfangen wird:
- Greift sofort auf das übergeordnete Element der Ansicht zu, aus der das Ereignis stammt.
- In dieser Ansicht wird als untergeordnete Ansicht nach einem Label und einem Kästchen gesucht.
- Wenn sie gefunden werden, wird eine Zeichenfolge erstellt, die an den Nutzer gemeldet wird, die den und ob es aktiviert wurde.
Wenn beim Durchlaufen der Ansichtshierarchie an irgendeinem Punkt ein Nullwert zurückgegeben wird, die Methode leise aufgibt.
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); }
Jetzt haben Sie eine vollständige, funktionierende Bedienungshilfe. Versuchen Sie, die Methode zu konfigurieren
Es interagiert mit dem Nutzer, indem es die Sprachausgabe-Funktion von Android
Suchmaschine
oder Vibrator
für eine haptische
Feedback geben.
Text verarbeiten
Geräte mit Android 8.0 (API-Level 26) und höher enthalten mehrere Textverarbeitungsfunktionen, die es Bedienungshilfen erleichtern, zur Identifizierung und Bearbeitung bestimmter Texteinheiten auf dem Bildschirm.
Kurzinfos
Android 9 (API-Level 28) bietet verschiedene Funktionen,
Kurzinfos auf der Benutzeroberfläche einer App angezeigt. Verwenden Sie
getTooltipText()
um den Text einer Kurzinfo zu lesen, und verwenden Sie
ACTION_SHOW_TOOLTIP
und
ACTION_HIDE_TOOLTIP
an, um Instanzen von View
anzuweisen, ihre Kurzinfos ein- oder auszublenden.
Hinweistext
Seit 2017 bietet Android mehrere Methoden zur Interaktion mit einem Hinweistext des textbasierten Objekts:
- Die
isShowingHintText()
undsetShowingHintText()
-Methoden angeben bzw. festlegen, ob der aktuelle Text des Knotens content steht für den Hinweistext des Knotens. getHintText()
Zugriff auf den Hinweistext selbst. Auch wenn ein Objekt nicht Hinweistext: Das Aufrufen vongetHintText()
ist erfolgreich.
Positionen von Bildschirmtextzeichen
Auf Geräten mit Android 8.0 (API-Level 26) und höher: Bedienungshilfen
kann die Bildschirmkoordinaten für den Begrenzungsrahmen jedes sichtbaren Zeichens bestimmen.
in einem TextView
-Widget Dienste
ermitteln Sie diese Koordinaten, indem Sie
refreshWithExtraData()
,
übergeben
EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY
als erstes Argument und ein Bundle
-Objekt
als zweites Argument ein. Bei Ausführung der Methode füllt das System
Argument Bundle
mit einem aparierbaren Array von
Rect
-Objekte. Jedes Rect
-Objekt
stellt den Begrenzungsrahmen eines bestimmten Zeichens dar.
Standardisierte einseitige Bereichswerte
Einige AccessibilityNodeInfo
-Objekte verwenden eine Instanz von
AccessibilityNodeInfo.RangeInfo
um anzuzeigen, dass ein UI-Element einen Wertebereich annehmen kann. Beim Erstellen einer
Bereich mithilfe von
RangeInfo.obtain()
,
oder wenn Sie die Extremwerte des Bereichs mit
getMin()
und
getMax()
,
Geräte mit Android 8.0 (API-Level 26) und höher
einseitige Bereiche standardisiert werden:
- Für Bereiche ohne Mindestwert:
Float.NEGATIVE_INFINITY
stellt den Mindestwert dar. - Für Bereiche ohne Höchstwert:
Float.POSITIVE_INFINITY
steht für den Maximalwert.
Auf Bedienungshilfen reagieren
Ihr Dienst ist nun für die Ausführung und das Warten auf Ereignisse eingerichtet. Schreiben Sie nun Code, damit er
weiß, was zu tun ist, wenn ein AccessibilityEvent
ankommt. Überschreiben Sie zunächst den
onAccessibilityEvent(AccessibilityEvent)
. Bei dieser Methode verwenden Sie
getEventType()
um die Art des Ereignisses und
getContentDescription()
, um jeden Labeltext zu extrahieren, der mit der Ansicht verknüpft ist, die das Ereignis auslöst:
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); ... }
Weitere Informationen
Weitere Informationen finden Sie in den folgenden Ressourcen: