Google is committed to advancing racial equity for Black communities. See how.

Advanced Android 06.2: Create accessible apps

This codelab is part of the Advanced Android Development training course, developed by the Google Developers Training team. You will get the most value out of this course if you work through the codelabs in sequence.

For complete details about the course, see the Advanced Android Development overview.

Introduction

Accessibility is a set of design, implementation, and testing techniques that enable your app to be usable by everyone, including people with disabilities.

Common disabilities that can affect a person's use of an Android device include blindness, low vision, color blindness, deafness or hearing loss, and restricted motor skills. When you develop your apps with accessibility in mind, you make the user experience better not only for users with these disabilities, but also for all of your other users.

Accessibility usually does not require a full overhaul of your app's design or code. Accessibility does require you to pay attention to details and test your app under the same conditions your users may encounter.

Android includes several accessibility-related features, to help you optimize your app's user interface (UI) for accessibility. In this lesson, you learn how to test your app and add features that enhance its accessibility.

What you should already know

You should be familiar with:

  • Creating, building, and running apps in Android Studio.
  • Creating views and layouts in both Android Studio's design editor and XML.

What you'll learn

  • Test your app for accessibility in a variety of ways.
  • Add attributes to your XML layouts that assist with making your app more accessible for your users.

What you'll do

  • Download and run a starter app.
  • Test the app with Google TalkBack (Android's screen reader) to identify possible accessibility issues. TalkBack gives spoken feedback so that you can use your device without looking at the screen.
  • Run Android Studio's code inspector to identify missing accessibility-related attributes.
  • Update the app to resolve the accessibility issues revealed in testing.

The SimpleAccessibility app demonstrates how to add accessible features to your app's UI. The app, when complete, looks like this:

efd98dd9e11b1c.png

None of the views have click handlers, so the app does not have any actual functionality. The focus for this app (and this codelab) is in the layout XML code and in the attributes that enable accessibility.

In this task, you run the starter app for SimpleAccessibility and explore it in TalkBack.

1.1 Download and open the sample app

  1. Download the SimpleAccessibility-start app and unzip the file.
  2. Open the app in Android Studio.
  3. Open res/layout/activity_main.xml.

The SimpleAccessibility app contains a number of views in a layout, including buttons ( Button and ImageButton views), checkboxes, and an image. All the accessibility functions you learn about in this practical are implemented in the layout.

8ec01ec0d5dfebf2.png

1.2 Test the app with TalkBack

TalkBack is Android's built-in screen reader. When TalkBack is on, the user can interact with their Android device without seeing the screen. Users with visual impairments may rely on TalkBack to use your app. In this task, you manually explore the app with TalkBack enabled, to expose possible accessibility problems.

Enable TalkBack:

  1. On a device, navigate to Settings > Accessibility > TalkBack.
  2. Tap the On/Off toggle button to turn on TalkBack.
  3. Tap OK to confirm permissions.

After TalkBack is on, you can navigate the Android UI in one of these ways:

  • Tap a UI element to hear the description for that element. Double-tap to select.
  • Swipe right or left to navigate through the elements in sequence. Double-tap anywhere to select.
  • Drag your finger over the screen to hear what's under your finger. Double-tap anywhere to select.

Now test your app with TalkBack enabled:

  1. Build and run your app in Android Studio.

When your app starts with TalkBack enabled, no item is initially focused. TalkBack reads the title of the app.

  1. Tap each element or swipe to hear the descriptions for the elements in sequence. Note the following:
  • The spoken feedback for the Compose button is the button title itself.
  • The feedback for the image button is "unlabelled button."
  • The feedback for a checkbox is the checkbox label and the current state of the checkbox (selected or cleared.)
  • No feedback is available for the partly cloudy image. The image is not even a focusable element.
  1. Swipe from left to right to navigate between focusable elements on the screen. Note that the focus moves from top to bottom. The partly cloudy image is not focusable.

Experimenting with TalkBack and the starter app in the previous task exposed problems in how the app's views are identified for vision-impaired users. In this task, you fix some of these problems.

2.1 Inspect and fix the code in Android Studio

Android Studio highlights places in your XML layout code that have potential accessibility problems, and makes suggestions for fixing those problems. For accessibility, Android Studio checks two things:

  • Missing content descriptions on ImageView and ImageButton objects. Because these views do not have text associated with them, the TalkBack screen reader can't describe them without an explicit description.
  • Missing label indicators (API 17 or higher). Text views are often used as labels for some other view in the layout, for example, as a label to indicate the content for an EditText. A label indicator specifies the other view that this view is a label for.

To inspect and fix your code for accessibility, use these steps:

  1. In Android Studio, open the res/layout/activity_main.xml file, if it's not already open. Switch to the Text tab.
  2. Note that the ImageButton and ImageView elements have yellow highlights on them. When you hover over the elements, the message reads, "Missing contentDescription attribute on image."
  3. Add an android:contentDescription attribute to the ImageButton view, with the value "Discard." Extract this string into a resource.
  4. Add an android:contentDescription attribute to the ImageView, with the value "Partly Cloudy." Extract this string into a resource.
  5. Build and run your app.
  6. Navigate your app with TalkBack turned on. The trash-can button now has a reasonable description, but you still can't focus on the partly cloudy image.

2.2 Add focus to views

In addition to readable descriptions, make sure that users can navigate your screen layouts using hardware or software-based directional controls such as D-pads, trackballs, keyboards, or on-screen gestures.

Most views are focusable by default, and the focus moves from view to view in your layout. The Android platform tries to figure out the most logical focus order based on each view's closest neighbor. Generally, views are focussed from left to right and top to bottom. In some cases, you want to make your views explicitly focusable or change the focus order to reflect how the user uses your app.

In the case of the SimpleAccessibility app, the partly cloudy image is not focusable, even with a content description added. Assuming that the partly cloudy image is there to show the current weather, you must add a focusable attribute to that image so that TalkBack can read the content description.

To make the partly cloudy image focusable, use these steps:

  1. Find the partly cloudy ImageView element in the XML layout.
  2. Add the android:focusable attribute to the ImageView:
android:focusable="true"
  1. Build and run the app. With TalkBack enabled, navigate to the partly cloudy image. TalkBack reads the image's content description.

In this task, you add an EditText view and an associated label (a TextView). EditText views and TextView labels are a special case for handling accessibility in your app.

3.1 Add views and test the app in TalkBack

  1. Add a TextView to the app's layout below the ImageView. Give it the android:text attribute of "Message." Extract that string into a resource.
  2. Add an EditText just below the TextView. Give it an ID of @+id/edittext_message, and the android:``hint attribute "Enter your message." Extract that string into a resource.
  3. Build and run the app and navigate to the new views. Experiment with entering text in TalkBack.

Note these things:

  • For text views, TalkBack reads the text that's in the android:text attribute. Here, the text is "Message." You do not need content descriptions for text views.
  • For EditText views, TalkBack reads the text that's in the android:hint attribute. Here, the text is "Enter your message." If android:hint does not exist, TalkBack reads the text that's in android:text instead.

In EditText views, it's better to use android:hint rather than android:text for the default text.

  • When the app starts, the first EditText has the initial focus.

3.2 Add explicit labels for EditText views (API 17 and higher)

If you target your app to Android 4.2 (API level 17) or higher, use the android:labelFor attribute when labeling views that serve as content labels for other views. For readable descriptions, TalkBack prefers explicit labels (using android:labelFor) over attributes such as android:text or android:hint.

Explicit labels are only available in API 17 or higher, and Android Studio can highlight missing labels for EditText views as part of code inspection. The SimpleAccessibility app uses the default minimum SDK of 15. In this task, you change the API level to enable explicit labels. Then you add the appropriate label attribute.

  1. Open the build.gradle (Module: app) file and change minSdkVersion from 15 to 17.
  2. Click Sync Now to rebuild the project.
  3. In the activity_main.xml layout file, delete the android:hint attribute from the EditText.

The EditText element is now highlighted in yellow. When you hover over the element, the message reads, "No label views point to this text field with an android:labelFor="@+id/edittext_message" attribute."

  1. Add the android:labelFor attribute to the TextView that serves as a label for this EditText:
android:labelFor="@+id/edittext_message"

The highlight on the EditText disappears.

  1. Build and run the app. TalkBack now reads the contents of the label to identify the EditText.

Android Studio project: SimpleAccessibility

Challenge: If the content of a view changes programmatically as the app runs, you need to update the content descriptions to reflect the new state.

  • Modify the SimpleAccessibility app to include a click handler for the Discard (trash can) button. When the button is clicked, toggle between two images: the default trash can and a lock icon. (You can use @android:drawable/ic_lock_lock for the lock icon.)
  • Use the setContentDescription() method to change the content description when the button image changes.
  • Test the app in TalkBack. Verify that the correct content description appears for each image.

Hints:

Get an image drawable from the resources:

Drawable img = ContextCompat.getDrawable(this, R.drawable.my_drawable);

Get a string from the resources:

String str = getResources().getString(R.string.my_string);

Compare two drawables:

if (drawable1.getConstantState() == drawable2.getConstantState()) {
   ... 
}
  • Adding accessibility to your app does not require significant code changes. You can add many accessibility features to an existing app through attributes in the XML layout. Use Android's TalkBack feature to test your app for users with low vision.
  • Android Studio can highlight missing accessibility attributes (content descriptions and labels) in your app's layout.
  • To provide readable descriptions of buttons, add android:contentDescription attributes to ImageView and ImageButton elements.
  • To provide the ability to navigate your app's UI, use focus and focus order.
  • Add android:focusable attributes to ImageView views that are not by default focusable.
  • You don't need to add content descriptions or focus to decorative images.
  • For EditText views, use android:hint instead of android:contentDescription.
  • If your app supports API 17 or higher, use the android:labelFor attribute to indicate that a view is a label for some other view.

The related concept documentation is in 6.1 Accessibility.

Android support documentation:

Android developer documentation:

Material Design: Usability - Accessibility

Videos:

Other:

This section lists possible homework assignments for students who are working through this codelab as part of a course led by an instructor. It's up to the instructor to do the following:

  • Assign homework if required.
  • Communicate to students how to submit homework assignments.
  • Grade the homework assignments.

Instructors can use these suggestions as little or as much as they want, and should feel free to assign any other homework they feel is appropriate.

If you're working through this codelab on your own, feel free to use these homework assignments to test your knowledge.

Build and run an app

In the SimpleAccessibility app, add three new images:

  1. Add a description for the first image that describes the image. Ensure that the image is focusable.
  2. Add a decorative image with no description. Ensure that the image is not focusable.
  3. For the third image, add a text label that describes the image.

Answer these questions

Question 1

Which of the following attributes should you add to ImageView and ImageButton elements to enable screen readers to describe the image?

  • android:text
  • android:contentDescription
  • android:hint
  • android:labelFor

Question 2

When should you add a content description to an ImageView or ImageButton?

  • When the image's role on the screen is solely decorative and does not provide any function or meaning.
  • When an image's dimensions are very small and the image is difficult to see.
  • When the image is meaningful to the user in their use of the app.
  • When the image is also a button.

Question 3

When do you NOT need to add a content description to a view element?

  • When the view is a TextView or EditText.
  • When the view is an ImageView that serves only a decorative purpose.
  • When the view is a checkbox or radio button.
  • When the view has an associated text view that includes with the android:labelFor attribute.
  • All of the above.

Submit your findings for grading

Guidance for graders

Check that the app has the following features:

  • The app should have three new images, of any kind.
  • The third image should have a text view that serves as a label.

The layout for the first new image should include the following:

  • An android:contentDescription attribute with a description of the image.
  • An android:focusable="true" attribute.

The layout for the second new image should include the following:

  • An android:contentDescription attribute with a null string ("").
  • An android:focusable="false" attribute.

The layout for the third new image should include the following:

  • An android:focusable="true" attribute.
  • A TextView element with the android:labelFor attribute. The android:labelFor attribute should indicate the ID of the image.

To see all the codelabs in the Advanced Android Development training course, visit the Advanced Android Development codelabs landing page.