1. Einführung
Eingabehilfen sind eine Funktion des Android-Frameworks, das dem Nutzer im Namen von Apps, die auf Android-Geräten installiert sind, Feedback zur alternativen Navigation liefert. Eine Bedienungshilfe kann im Namen der Anwendung mit dem Nutzer kommunizieren, z. B. durch Umwandlung von Text in Sprache oder durch haptisches Feedback, wenn ein Nutzer den Mauszeiger auf einen wichtigen Bildschirmbereich bewegt. In diesem Codelab erfahren Sie, wie Sie eine sehr einfache Bedienungshilfe erstellen.
Was ist eine Bedienungshilfe?
Eine Bedienungshilfe unterstützt Nutzer mit Behinderungen bei der Verwendung von Android-Geräten und -Apps. Es handelt sich um einen privilegierten Dienst mit langer Laufzeit, der Nutzern hilft, Informationen auf dem Bildschirm zu verarbeiten und sinnvoll mit einem Gerät zu interagieren.
Beispiele für gängige Bedienungshilfen
- Schalterzugriff: Android-Nutzer mit Mobilitätseinschränkungen können Geräte über einen oder mehrere Schalter steuern.
- Voice Access (Beta): Android-Nutzer mit eingeschränkter Mobilität können ein Gerät per Sprachbefehl steuern.
- TalkBack: Ein Screenreader, der häufig von sehbehinderten oder blinden Nutzern verwendet wird.
Bedienungshilfen erstellen
Google bietet zwar Dienste wie Schalterzugriff, Voice Access und TalkBack für Android-Nutzer an, aber diese Dienste können unter Umständen nicht für alle Nutzer mit Behinderungen geeignet sein. Da viele Nutzer mit Behinderungen besondere Bedürfnisse haben, sind die Android-APIs zum Erstellen von Bedienungshilfen offen, sodass Entwickler Bedienungshilfen erstellen und über den Play Store vertreiben können.
Inhalt
In diesem Codelab entwickeln Sie einen einfachen Dienst, der mithilfe der Accessibility API einige nützliche Dinge erledigt. Wenn Sie eine einfache Android-App schreiben können, können Sie einen ähnlichen Dienst entwickeln.
Die Accessibility API ist leistungsstark: Der Code für den Dienst, den Sie erstellen werden, ist in nur vier Dateien enthalten und umfasst ca. 200 Zeilen Code.
Der Endnutzer
Sie erstellen einen Dienst für hypothetische Nutzer mit den folgenden Merkmalen:
- Der Nutzer hat Schwierigkeiten, die seitlichen Tasten eines Geräts zu erreichen.
- Der Nutzer hat Schwierigkeiten beim Scrollen oder Wischen.
Dienstdetails
Ihr Dienst blendet eine globale Aktionsleiste auf dem Bildschirm ein. Der Nutzer kann Schaltflächen auf dieser Leiste berühren, um folgende Aktionen auszuführen:
- Schalten Sie das Gerät aus, ohne die eigentliche Ein/Aus-Taste an der Seite des Smartphones zu erreichen.
- Passen Sie die Lautstärke an, ohne die Lautstärketasten an der Seite des Smartphones zu berühren.
- Scrollaktionen ausführen, ohne tatsächlich zu scrollen.
- Wischen Sie, ohne eine Wischgeste zu verwenden.
Voraussetzungen
In diesem Codelab wird davon ausgegangen, dass Sie Folgendes verwenden:
- Einen Computer, auf dem Android Studio ausgeführt wird
- Ein Terminal zum Ausführen einfacher Shell-Befehle.
- Ein Gerät mit Android 7.0 (Nougat), das mit dem Computer verbunden ist, den Sie für die Entwicklung verwenden.
Los gehts!
2. Einrichtung
Erstellen Sie über das Terminal ein Verzeichnis, in dem Sie arbeiten. Wechseln Sie in dieses Verzeichnis.
Code herunterladen
Sie können das Repository klonen, das den Code für dieses Codelab enthält:
git clone https://github.com/android/codelab-android-accessibility.git
Das Repository enthält mehrere Android Studio-Projekte. Öffnen Sie in Android Studio GlobalActionBarService.
Starten Sie Android Studio, indem Sie auf das Studio-Symbol klicken:
Wählen Sie die Option Projekt importieren (Eclipse ADT, Gradle usw.) aus:
Gehen Sie zu dem Speicherort, an dem Sie die Quelle geklont haben, und wählen Sie GlobalActionBarService aus.
Wechseln Sie dann über ein Terminal in das Stammverzeichnis.
3. Startcode verstehen
Sehen Sie sich das geöffnete Projekt an.
Das grundlegende Layout der Bedienungshilfe wurde bereits für Sie entwickelt. Der gesamte Code, den Sie in diesem Codelab schreiben, ist auf die folgenden vier Dateien beschränkt:
- app/src/main/AndroidManifest.xml
- app/src/main/res/layout/action_bar.xml
- app/src/main/res/xml/global_action_bar_service.xml
- app/src/main/java/com/example/android/globalactionbarservice/GlobalActionBarService.java
Im Folgenden finden Sie eine Schritt-für-Schritt-Anleitung für den Inhalt der einzelnen Dateien.
AndroidManifest.xml
Informationen zur Bedienungshilfe sind im Manifest deklariert:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.android.globalactionbarservice">
<application>
<service
android:name=".GlobalActionBarService"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
android:exported="true">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
<meta-data
android:name="android.accessibilityservice"
android:resource="@xml/global_action_bar_service" />
</service>
</application>
</manifest>
Die folgenden drei erforderlichen Elemente werden in der Datei AndroidManifest.xml deklariert:
- Berechtigung zum Binden an eine Bedienungshilfe:
<service
...
android:permission = "android.permission.BIND_ACCESSIBILITY_SERVICE">
...
</service>
- Der AccessibilityService-Intent:
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
- Speicherort der Datei, die die Metadaten für den Dienst enthält, den Sie erstellen:
<meta-data
...
android:resource="@xml/global_action_bar_service" />
</service>
global_action_bar_service.xml
Diese Datei enthält die Metadaten für den Dienst.
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityFeedbackType="feedbackGeneric"
android:accessibilityFlags="flagDefault"
android:canPerformGestures="true"
android:canRetrieveWindowContent="true" />
Mit dem Element <accessibility-service> wurden die folgenden Metadaten definiert:
- Der Feedbacktyp für diesen Dienst. In diesem Codelab wird feedbackGeneric verwendet. Dies ist eine gute Standardeinstellung.
- Die Bedienungshilfen-Flags für den Dienst (in diesem Codelab werden Standard-Flags verwendet).
- Für den Dienst erforderliche Funktionen:
- Damit das Wischen möglich ist, muss android:canPerformGestures auf android:canPerformGestures festgelegt sein.
- Damit Fensterinhalte abgerufen werden können, ist android:canRetrieveWindowContent auf true gesetzt.
GlobalActionBarService.java
Der größte Teil des Codes für den Bedienungshilfendienst befindet sich in GlobalActionBarService.java. Anfangs enthält die Datei den absoluten Mindestwert von Code für eine Bedienungshilfe:
- Klasse, die AccessibilityService erweitert.
- Einige erforderliche überschriebene Methoden (in diesem Codelab leer).
public class GlobalActionBarService extends AccessibilityService {
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
}
@Override
public void onInterrupt() {
}
}
Sie fügen dieser Datei während des Codelab Code hinzu.
action_bar.xml
Der Dienst stellt eine Benutzeroberfläche mit vier Schaltflächen zur Verfügung und die Layoutdatei action_bar.xml enthält das Markup für die Anzeige dieser Schaltflächen:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</LinearLayout>
Diese Datei enthält vorerst ein leeres LinearLayout. Im Codelab wirst du Markup für die Schaltflächen hinzufügen.
Anwendung starten
Vergewissern Sie sich, dass ein Gerät mit Ihrem Computer verbunden ist. Tippen Sie in der Menüleiste oben auf dem Bildschirm auf das grüne Wiedergabesymbol . Dadurch sollte die App gestartet werden, an der Sie gerade arbeiten.
Gehen Sie zu Einstellungen > Bedienungshilfen: Der Global Action Bar Service ist auf Ihrem Gerät installiert.
Klicken Sie auf Global Action Bar Service und aktivieren Sie ihn. Das folgende Berechtigungsdialogfeld sollte angezeigt werden:
Die Bedienungshilfe fordert die Berechtigung an, Nutzeraktionen zu beobachten, Fensterinhalte abzurufen und Gesten im Namen des Nutzers auszuführen. Wenn Sie Bedienungshilfen von Drittanbietern nutzen, sollten Sie der Quelle wirklich vertrauen.
Die Ausführung des Dienstes bewirkt nicht viel, da wir noch keine Funktion hinzugefügt haben. Fangen wir damit an.
4. Erstellen der Schaltflächen
Öffnen Sie action_bar.xml in res/layout. Fügen Sie das Markup in das derzeit leere LinearLayout ein:
<LinearLayout ...>
<Button
android:id="@+id/power"
android:text="@string/power"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/volume_up"
android:text="@string/volume"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/scroll"
android:text="@string/scroll"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/swipe"
android:text="@string/swipe"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
Dadurch werden Schaltflächen erstellt, über die Nutzer Aktionen auf dem Gerät auslösen können.
Öffnen Sie GlobalActionBarService.java und fügen Sie eine Variable zum Speichern des Layouts der Aktionsleiste hinzu:
public class GlobalActionBarService extends AccessibilityService {
FrameLayout mLayout;
...
}
Fügen Sie nun eine onServiceStarted()-Methode hinzu:
public class GlobalActionBarService extends AccessibilityService {
FrameLayout mLayout;
@Override
protected void onServiceConnected() {
// Create an overlay and display the action bar
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
mLayout = new FrameLayout(this);
WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
lp.type = WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
lp.format = PixelFormat.TRANSLUCENT;
lp.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
lp.gravity = Gravity.TOP;
LayoutInflater inflater = LayoutInflater.from(this);
inflater.inflate(R.layout.action_bar, mLayout);
wm.addView(mLayout, lp);
}
}
Durch den Code wird das Layout maximiert und die Aktionsleiste wird in Richtung des oberen Bildschirmrands hinzugefügt.
Die Methode onServiceConnected() wird ausgeführt, wenn der Dienst verbunden ist. Derzeit verfügt die Bedienungshilfe über alle Berechtigungen, die sie zum Funktionieren benötigt. Die hier verwendete Schlüsselberechtigung ist die Berechtigung WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY. Mit dieser Berechtigung können Sie direkt auf dem Bildschirm über vorhandenen Inhalten zeichnen, ohne einen komplizierten Berechtigungsvorgang durchlaufen zu müssen.
Lebenszyklus des Bedienungshilfen-Dienstes
Der Lebenszyklus eines Bedienungshilfendiensts wird ausschließlich vom System verwaltet und folgt dem festgelegten Lebenszyklus.
- Eine Bedienungshilfe wird gestartet, wenn der Nutzer den Dienst in den Geräteeinstellungen explizit aktiviert.
- Nach der Bindung an einen Dienst ruft das System onServiceConnected() auf. Diese Methode kann von Diensten überschrieben werden, die eine Einrichtung nach der Bindung vornehmen möchten.
- Eine Bedienungshilfe wird entweder beendet, wenn der Nutzer sie in den Geräteeinstellungen deaktiviert oder wenn sie disableSelf() aufruft.
Dienst ausführen
Bevor Sie den Dienst über Android Studio starten können, müssen Sie prüfen, ob die Ausführungseinstellungen richtig konfiguriert sind.
Bearbeiten Sie die Ausführungskonfiguration. Klicken Sie dazu im Menü oben auf „Run“ (Ausführen) und gehen Sie zu „Edit Configurations“ (Konfigurationen bearbeiten). Ändern Sie dann im Drop-down-Menü die Startoption von „Standardaktivität“ in „Nothing“.
Sie sollten den Dienst jetzt mit Android Studio starten können.
Tippen Sie in der Menüleiste oben auf dem Bildschirm auf das grüne Wiedergabesymbol . Rufen Sie dann Einstellungen > Bedienungshilfen und aktivieren Sie Global Action Bar Service.
Die vier Schaltflächen, aus denen die Benutzeroberfläche des Dienstes besteht, sollten über den auf dem Bildschirm angezeigten Inhalt gelegt werden.
Jetzt fügen Sie den vier Schaltflächen Funktionen hinzu, damit Nutzende sie berühren können, um nützliche Aktionen auszuführen.
5. Ein/Aus-Taste konfigurieren
Fügen Sie die Methode configurePowerButton() zu configurePowerButton() hinzu:
private void configurePowerButton() {
Button powerButton = (Button) mLayout.findViewById(R.id.power);
powerButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
performGlobalAction(GLOBAL_ACTION_POWER_DIALOG);
}
});
}
Für den Zugriff auf das Ein/Aus-Menü verwendet configurePowerButton() die Methode performGlobalAction(), die von AccessibilityService bereitgestellt wird. Der soeben hinzugefügte Code ist ganz einfach: Wenn Sie auf die Schaltfläche klicken, wird ein onClickListener() ausgelöst. Dadurch wird performGlobalAction(GLOBAL_ACTION_POWER_DIALOG) aufgerufen und der Nutzer sieht das Ein/Aus-Dialogfeld.
Globale Aktionen sind nicht mit Datenansichten verknüpft. Weitere Beispiele für globale Aktionen sind das Drücken der Zurück-Taste, der Home-Taste und der Recents-Tasten.
Fügen Sie nun configurePowerButton() am Ende der Methode onServiceConnected() hinzu:
@Override
protected void onServiceConnected() {
...
configurePowerButton();
}
Tippen Sie in der Menüleiste oben auf dem Bildschirm auf das grüne Wiedergabesymbol . Rufen Sie dann Einstellungen > Bedienungshilfen und starten Sie den Global Action Bar Service.
Drücken Sie die Ein/Aus-Taste, um das Ein/Aus-Dialogfeld aufzurufen.
6. Konfigurieren der Lautstärketaste
Fügen Sie die Methode configureVolumeButton() zu configureVolumeButton() hinzu:
private void configureVolumeButton() {
Button volumeUpButton = (Button) mLayout.findViewById(R.id.volume_up);
volumeUpButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
AudioManager audioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
audioManager.adjustStreamVolume(AudioManager.STREAM_MUSIC,
AudioManager.ADJUST_RAISE, AudioManager.FLAG_SHOW_UI);
}
});
}
Mit der Methode configureVolumeButton() wird eine onClickListener() hinzugefügt, die ausgelöst wird, wenn der Nutzer die Lautstärketaste drückt. In diesem Listener verwendet configureVolumeButton() einen AudioManager, um die Stream-Lautstärke anzupassen.
Beachten Sie, dass jeder die Lautstärke regeln kann. Sie müssen dazu keine Bedienungshilfe sein.
Fügen Sie nun configureVolumeButton() am Ende der onServiceConnected()-Methode hinzu:
@Override
protected void onServiceConnected() {
...
configureVolumeButton();
}
Tippen Sie in der Menüleiste oben auf dem Bildschirm auf das grüne Wiedergabesymbol . Rufen Sie dann „Einstellungen“ > Bedienungshilfen und starten Sie den Global Action Bar Service.
Drücken Sie die Lautstärketaste, um die Lautstärke zu ändern.
Der hypothetische Nutzer, der keinen Zugriff auf die Lautstärkeregler an der Seite des Geräts hat, kann jetzt mit Global Action Bar Service die Lautstärke ändern (erhöhen).
7. Konfigurieren der Scroll-Schaltfläche
In diesem Abschnitt werden zwei Methoden codiert. Die erste Methode findet einen scrollbaren Knoten, und die zweite Methode führt die Scrollaktion im Namen des Nutzers aus.
Fügen Sie die Methode findScrollableNode zu findScrollableNode hinzu:
private AccessibilityNodeInfo findScrollableNode(AccessibilityNodeInfo root) {
Deque<AccessibilityNodeInfo> deque = new ArrayDeque<>();
deque.add(root);
while (!deque.isEmpty()) {
AccessibilityNodeInfo node = deque.removeFirst();
if (node.getActionList().contains(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_FORWARD)) {
return node;
}
for (int i = 0; i < node.getChildCount(); i++) {
deque.addLast(node.getChild(i));
}
}
return null;
}
Eine Bedienungshilfe hat keinen Zugriff auf die tatsächlichen Ansichten auf dem Bildschirm. Stattdessen wird das, was auf dem Bildschirm zu sehen ist, in Form eines Baums aus AccessibilityNodeInfo-Objekten reflektiert. Diese Objekte enthalten Informationen über die von ihnen dargestellte Ansicht, z. B. den Standort der Ansicht, mit der Ansicht verknüpfter Text, Metadaten, die für Barrierefreiheit hinzugefügt wurden, die von der Ansicht unterstützten Aktionen usw. Die Methode findScrollableNode() führt einen breiten Durchlauf dieses Baums aus, beginnend am Stammknoten. Wenn ein scrollbarer Knoten gefunden wird (d. h. ein Knoten, der die AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_FORWARD-Aktion)
unterstützt), wird der Knoten zurückgegeben.Andernfalls wird null zurückgegeben.
Fügen Sie jetzt die Methode configureScrollButton() zu configureScrollButton() hinzu:
private void configureScrollButton() {
Button scrollButton = (Button) mLayout.findViewById(R.id.scroll);
scrollButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
AccessibilityNodeInfo scrollable = findScrollableNode(getRootInActiveWindow());
if (scrollable != null) {
scrollable.performAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_FORWARD.getId());
}
}
});
}
Mit dieser Methode wird ein onClickListener() erstellt, das ausgelöst wird, wenn auf die Scroll-Schaltfläche geklickt wird. Es wird versucht, einen scrollbaren Knoten zu finden. Ist dies erfolgreich, wird die Scroll-Aktion ausgeführt.
Fügen Sie nun configureScrollButton() zu onServiceConnected() hinzu:
@Override
protected void onServiceConnected() {
...
configureScrollButton();
}
Tippen Sie in der Menüleiste oben auf dem Bildschirm auf das grüne Wiedergabesymbol . Rufen Sie dann „Einstellungen“ > Bedienungshilfen und starten Sie den Global Action Bar Service.
Drücke die Zurück-Taste, um zu Einstellungen > Bedienungshilfen Die Elemente in den Einstellungen für Bedienungshilfen sind scrollbar. Wenn Sie auf die Schaltfläche „Scrollen“ tippen, wird eine Scrollaktion ausgeführt. Unser hypothetischer Nutzer, der Scrollaktionen nicht einfach durchführen kann, kann nun mit der Scroll-Schaltfläche durch eine Liste von Elementen scrollen.
8. Konfigurieren der Wischtaste
Fügen Sie die Methode configureSwipeButton() zu configureSwipeButton() hinzu:
private void configureSwipeButton() {
Button swipeButton = (Button) mLayout.findViewById(R.id.swipe);
swipeButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Path swipePath = new Path();
swipePath.moveTo(1000, 1000);
swipePath.lineTo(100, 1000);
GestureDescription.Builder gestureBuilder = new GestureDescription.Builder();
gestureBuilder.addStroke(new GestureDescription.StrokeDescription(swipePath, 0, 500));
dispatchGesture(gestureBuilder.build(), null, null);
}
});
}
Die Methode configureSwipeButton() hat eine neue API, die in N hinzugefügt wurde und Gesten im Namen des Nutzers ausführt. Der Code verwendet ein GestureDescription-Objekt, um den Pfad für die auszuführende Geste anzugeben. In diesem Codelab werden hartcodierte Werte verwendet. Anschließend wird die Wischgeste im Namen des Nutzers über die Methode AccessibilityService dispatchGesture() ausgeführt.
Fügen Sie nun configureSwipeButton() zu onServiceConnected() hinzu:
@Override
protected void onServiceConnected() {
...
configureSwipeButton();
}
Tippen Sie in der Menüleiste oben auf dem Bildschirm auf das grüne Wiedergabesymbol . Rufen Sie dann „Einstellungen“ > Bedienungshilfen und starten Sie den Global Action Bar Service.
Am einfachsten testen Sie die Wischfunktion, indem Sie die auf Ihrem Smartphone installierte Maps App öffnen. Sobald die Karte geladen ist, wird der Bildschirm durch Tippen auf die Schaltfläche "Wischen" nach rechts gewischt.
9. Zusammenfassung
Glückwunsch! Sie haben eine einfache, funktionale Bedienungshilfe entwickelt.
Sie können diesen Dienst auf verschiedene Arten erweitern. Beispiel:
- Machen Sie die Aktionsleiste beweglich (sie befindet sich vorerst nur auf dem Bildschirm).
- Dem Nutzer erlauben, die Lautstärke zu erhöhen oder zu verringern.
- Erlaube dem Nutzer, sowohl nach links als auch nach rechts zu wischen.
- Unterstützung für zusätzliche Touch-Gesten, auf die die Aktionsleiste reagieren kann
Dieses Codelab deckt nur einen kleinen Teil der Funktionen der Accessibility APIs ab. Die API deckt außerdem Folgendes ab (Teilliste):
- Unterstützung für mehrere Fenster.
- Unterstützung für AccessibilityEvent-Ereignisse. Wenn sich die Benutzeroberfläche ändert, werden Bedienungshilfen mithilfe von AccessibilityEvent-Objekten über diese Änderungen informiert. Der Dienst kann dann entsprechend auf Änderungen der Benutzeroberfläche reagieren.
- Möglichkeit, die Vergrößerung zu steuern.
In diesem Codelab lernen Sie, wie Sie eine Bedienungshilfe schreiben. Wenn Sie einen Nutzer mit bestimmten Problemen mit der Barrierefreiheit kennen, die Sie ansprechen möchten, können Sie jetzt einen Dienst erstellen, der diesem Nutzer hilft.