Android apps should be usable by everyone, including people with disabilities. Common disabilities that affect a person's use of an Android device include blindness or low vision, deafness or impaired hearing, restricted motor skills, and color blindness. And this is just a partial list.

Apps written with accessibility in mind make the user experience better for everyone: keyboard shortcuts in Gmail help power users, high contrast helps when looking at a screen with glare in the background, and voice controls help you control your device when you're cooking.

By working through this codelab, you will gain knowledge about how people with certain kinds of disabilities use Android applications, and you will learn how to write applications that enrich the experience for these users. If you run into any issues (code bugs, grammatical errors, unclear wording, etc.) as you work through this codelab, please report the issue via the Report a mistake link in the lower left corner of the codelab.

Audience and Prerequisites

This codelab is intended for Android developers who want to understand how to make their apps accessible to users with disabilities.

This codelab assumes the following:

  1. Basic familiarity with writing Android applications.
  2. Access to an Android device running Lollipop (API level 21) or higher.
  3. Availability of TalkBack on your device. TalkBack is included in the Android Accessibility Suite.
  4. Availability of Accessibility Scanner.


In this codelab, you will:

The codelab is structured in small, discrete steps, and each step focuses on a specific accessibility issue.

Download the Code

You can clone the repo that contains the code for this codelab:

git clone https://github.com/googlecodelabs/basic-android-accessibility.git

Or you can download the code by clicking the following button and unpacking the zip file:

Download source code

Using a terminal, change into the root directory.

Git branches

The code is organized in two branches, the master branch, and the accessible branch.

Each step in this codelab is structured so that you start working with a screen or a feature that has been implemented in an inaccessible manner. By the end of each step, you will have modified the code, and you will have made the screen or feature accessible.

Setting up Android Studio

Launch Android Studio by clicking the Studio icon:

The logo for Android Studio. Clicking this on your computer launches Android Studio.

Select the Open an existing Android Studio project option:

Navigate to the location where you cloned or unzipped the source, and select basic-android-accessibility-Java. If you prefer Kotlin, select basic-android-accessibility-Kotlin.

Your Android studio screen should now look something like this:

Expose the directory structure of the application using the following steps:

  1. Expand app/ in left column.
  2. Expand java/ and res/.
  3. Under res/, expand layout/.

All source files are located under app/java, and all layout files appear under app/res/layout.

The Android Studio screen with the expanded directories should look something like this:

Launching the demo application

Make sure a device is connected to your workstation. Press the green Play icon Screen Shot 2016-05-11 at 8.53.21 AM.png from the menu bar towards the top of the screen. This should launch the Basic Android Accessibility Codelab app. The landing page for that app looks something like this:

Don't close the app. We'll return to it soon.

In this step, we'll be setting up TalkBack, which is included in the Android Accessibility Suite App (usually included by default in Android).

TalkBack is Android's bundled accessibility solution. It is a screen reader that offers auditory, haptic, and spoken feedback, which allows users to navigate and consume content on their devices without using their eyes. Using TalkBack is a great way to become acquainted with the ways in which someone with visual impairments might access content on their device, and it's also a great way to test the accessibility of your own application.

TalkBack Settings

We'll use TalkBack with a developer-mode option that will show the text from the auditory feedback on the screen.

Follow these steps to set up TalkBack. These instructions assume a Pixel device; the location of TalkBack settings can vary on other Android devices.

TalkBack tutorial

At this point, TalkBack may launch its Tutorial, which goes over TalkBack fundamentals. You are welcome to work through the tutorial, but you can skip it for now if you prefer.

We use only a subset of Talkback's functionality in this codelab, and the next step provides enough help to get you started with Talkback.

In the previous step, we configured and turned on TalkBack. In this step, we'll cover basic navigation using TalkBack.

Basic Touch Explore

  1. Tap the Overview button. This is the square button on the bottom right of your screen. TalkBack announces the selected button (it draws a green rectangle around it to show that the button has focus).

  1. Double-tap anywhere on the screen to select a focused item.

This two-step process is integral to exploring Android apps by touch. TalkBack announces icons, buttons, and other items as you touch them. You double-tap on the screen to select the focused item.

If you did not close the codelab app before starting Step 1, your screen should look something like this:

To start using the codelab app, do the following:

  1. Tap on the codelab screen. TalkBack announces that it has focus.
  2. Double-tap to return to the codelab activity.

Linear navigation

To explore your screen one item at a time, swipe-left or swipe-right to move through the items in sequence. Swipe-left takes you to the item previous from the one you're on. Swipe-right takes you to the next item.

Execute the following steps:

  1. Click on the "Basic Android Accessibility Codelab" title in the toolbar at the top of the screen. TalkBack focuses on this view.
  2. Swipe-right. The focus moves to "CONTENT LABELING SCREEN".
  3. Swipe-right again. The focus now moves to "CONTENT GROUPING SCREEN".
  4. Swipe-left. The focus moves back to "CONTENT LABELING SCREEN".

TalkBack offers a rich option of gestures (learn more about TalkBack gestures), but in this codelab we'll restrict ourselves to the gestures covered in this step.

For help with TalkBack, visit Get Started on Android with TalkBack.

When a user with vision impairment tries to navigate an application by touch, TalkBack announces all actionable content as long as it has meaningful, useful, and descriptive labels. If such labels are missing, TalkBack may not be able to properly explain the function of a particular control to a user. In some cases, TalkBack may skip over some content entirely.

In this step, you'll explore how TalkBack handles inadequately labeled content. Once you improve the labeling, you'll see how that improves the experience of the TalkBack user.

Unlabeled Content

Navigate to Content Labeling Screen (remember this is a two-step process when using TalkBack). The screen looks like this:

The screen contains a title, an EditText for entering text, a "Go" button, a Share button, and Play button. When the play button is clicked, it toggles to a Pause button.

Discover the content on the screen using TalkBack:

  1. Tap on the title. TalkBack announces "Content labeling screen".
  2. Swipe right to get to the next view. TalkBack announces "Jukebox".
  3. Swipe right again. TalkBack skips over the purely decorative musical note image (we'll discuss that shortly), focuses on the EditText, and announces "Enter favorite song. Edit box. " TalkBack knows to announce "Enter favorite song" because the EditText has an android:hint attribute that is set to "Enter favorite song" in the layout XML.
  1. Swipe right to focus on the Go button. TalkBack picks up the text associated with the button and announces "Go button", and then adds "Double tap to activate." This tells the user how to interact with the view.
  2. Swipe right to focus on the Share button. TalkBack announces "Button, Unlabelled". This isn't very helpful, but we haven't given TalkBack much to work this. We'll fix that soon.
  3. Swipe right to focus on the Play button. TalkBack similarly announces "Button, Unlabelled". When you double-tap the Play icon, it changes to a Pause icon. When you tap on the icon again, TalkBack again announces "Button, Unlabelled". The button toggles state, but the TalkBack user has no way of knowing anything about the button state. We'll fix this soon.

Properly labeled content

Let's improve the experience for the TalkBack user by properly labeling content.

Fixing the decorative image

Go back to Android Studio and from res/layout, open content_labeling.xml.

Place your cursor over the first <ImageView>. Android Studio's lint checks warn about a missing contentDescription.

Let's fix this. Since the musical note is purely decorative, we should set the contentDescription to "@null":

   android:src="@drawable/ic_music_note" />

This satisfies Android Studio's lint check by confirming that you are not providing a contentDescription for this view intentionally, rather than forgetting to do so.

Fixing the Share image button

TalkBack simply reads the Share image button as "Button, Unlabelled", and Android Studio generates a lint warning about a missing contentDescription. Add a contentDescription, using "@string/share" as the value (this is defined in res/values/strings.xml with a value of "Share"):

   android:src="@drawable/ic_share" />

Press the green Play icon Screen Shot 2016-05-11 at 8.53.21 AM.png from the menu bar to run the app.

Tap on the Share icon. Talkback now announces, "Share Button".

Fixing the Play/Pause button

The Play/Pause toggle is managed dynamically through the code. Look at the code in the ContentLabelingFragment class:

private void updateImageButton() {
    if (mPlaying) {
    } else {

We toggle the image, but we don't add a contentDescription to describe the current state of the view. Add calls to setContentDescription() so the code looks like this:

private void updateImageButton() {
    if (mPlaying) {

    } else {

Press the green Play icon Screen Shot 2016-05-11 at 8.53.21 AM.png from the menu bar to run the app and navigate to the Play icon. TalkBack announcements are much more meaningful now:

  1. Tap on the Play icon. TalkBack announces "Play button".
  2. Double-tap to toggle the icon.
  3. Tap on the Pause icon. TalkBack announce "Pause button".

Helping keyboard users

To help users who interact with your app using a keyboard, you may need to manually specify that some clickable items (e.g. ImageView elements) are focusable using android:focusable="true". By default, content is not focusable, so you do not need to add android:focusable="false" to purely decorative views like the music note ImageView.

Sometimes the auditory feedback TalkBack gives for visual elements in an app may not reflect their logical and spatial structure. Even though elements may be ordered in a sensible way visually, they may be spoken out of order.

Incorrectly Grouped Content

To see an example for this, navigate to the Content Grouping Screen.

Click on the title, and swipe right repeatedly to move down to the other views. What do you notice?

TalkBack announces the title ("Song Details"), and then it announces the views in the following order:

  1. "Name"
  2. "Hey Jude"
  3. "Artists"
  4. "The Beatles"
  5. "Cost"
  6. "$1.45".

While the TalkBack user is able to discover all the content on the screen, the user has to do a lot of swiping. If the song details had many more fields, the experience would quickly become tedious.

Grouping Content for Accessibility

There are several ways to fix this. Since the song data is made up of only six short strings, we could have TalkBack group all six items into a single announcement. Let's experiment with this approach.

It is a common best practice to group non-focusable items (e.g. TextView elements) in a focusable container to have them read as a single item.

Open content_grouping.xml and locate the RelativeLayout that contains the six TextView elements that we wish to consolidate.

Add the focusable attribute to the <RelativeLayout> element:


Press the green Play icon Screen Shot 2016-05-11 at 8.53.21 AM.png from the menu bar run your code and try out the new version of the Content Grouping Screen with TalkBack.

What do you notice now? TalkBack announces the title ("Song Details"), and then it announces the song details as a single announcement ( "Name, Hey Jude, Artists, The Beatles, Cost, $1.45").

Using natural groupings

In the example we're considering, having a single TalkBack announcement is better than having six; but this solution has its limits:

  1. It quickly becomes unscalable if the number of song detail fields increases, or if the fields contain a lot of text.
  2. Neither the original six-announcement version nor the single-announcement version we just implemented take the natural grouping of views into consideration. The data is clearly visually organized in two columns - the items on the left and the corresponding values on the right. This grouping is evident to a user who can see the screen, but you should ensure that this is just as obvious to a visually-impaired user with TalkBack.

You will now reimplement this functionality by having TalkBack announce the song details a single row at a time.

This requires placing the "Name" and "Hey Jude" TextView elements into a single focusable ViewGroup, placing the "Artists" and "The Beatles" into another focusable ViewGroup, and so on. To make TalkBack announce content by row, you'll need to split your RelativeLayout element into a new one for each row so that it's structured like this:



          ...  />
          ...  />


          ... />
          ...  />


          ...  />
          ...  />

Press the green Play icon Screen Shot 2016-05-11 at 8.53.21 AM.png from the menu bar to run your app and try out Content Grouping Screen once again with TalkBack. The song details are now announced like this:

  1. "Name, Hey Jude"
  2. "Artists, The Beatles"
  3. "Cost, $1.45"

So far, all the examples have involved using Talkback with views that a user has explicitly focused on. However, you sometimes need to discover text that updates dynamically without having to explicitly navigate to it and focus on it.

Return to MainActivity using the Back button, and navigate to the Live Region Screen.

This screen shows a multiple choice question. Here's how Talkback works with radio buttons:

  1. When you focus on a radio button, TalkBack announces the button text and its checked status ("not checked, JellyBean Radio button", for example).
  2. When you double-tap to select a button, TalkBack announces the changed button state ("checked", for example).

Whenever you make a selection, text at the bottom of the screen informs you whether you picked correctly or incorrectly. To the user who can see the screen, this helpful feedback is immediately available. However, TalkBack doesn't automatically announce this feedback. To instruct TalkBack to do so, we need to use a live region.

Open content_live_region.xml and locate the TextView responsible for the correct/incorrect feedback.

   android:textSize="@dimen/large_text" />

Add an accessibilityLiveRegion attribute to this view, giving it a value of "polite":

   android:accessibilityLiveRegion="polite" />

Press the green Play icon Screen Shot 2016-05-11 at 8.53.21 AM.png from the menu bar to run the app. Try using LiveRegionScreen again.

When you focus on a radio button and double-tap to select it, TalkBack announces the changed button state and also gives you feedback about whether you were right or not ("Incorrect. Checked", or "Correct! Checked", for example).

How live regions work

Using an accessibilityLiveRegion with a view means that when that view updates, it generates an extra AccessibilityEvent in the event stream that an AccessibilityService like TalkBack can pay attention to.

Being "polite"

We gave our accessibilityLiveRegion a value of "polite". This simply means that TalkBack won't interrupt anything it may already be announcing when it processes the event generated by a live region. An alternate to "polite" is "assertive", which instructs TalkBack to move announcements related to a live region up the event queue and interrupt ongoing announcements. You should use live regions sparingly, and nearly always avoid "assertive" live regions.

You will notice that the solutions to accessibility problems discussed in this codelab so far - adding contentDescription attributes and grouping related UI elements in the same container - have not required you to define the announcements that an AccessibilityService makes. This is mostly because default Android UI components have accessibility "baked in" - that is to say, there is useful metadata in the code for buttons, switches, checkboxes, etc. that tells a service like TalkBack how to speak these components out loud.

When you create your own custom views instead of using the default ones in the framework, the accessibility problems quickly become more difficult and the solutions become non-trivial.

Covering accessibility of custom views is outside the scope of this codelab, but it is worth touching on the subject briefly.

Here are some APIs for making custom views accessible:

In every example so far, we've used TalkBack to discuss accessibility features for visually impaired and blind users. We'll switch gears now and talk about accessibility more broadly. We won't be using TalkBack any more in this codelab, so we should disable the tool. First, we need to find our way back to the Accessibility Settings screen. Follow these steps:

  1. Tap the Overview Button on the screen's bottom right, and double-tap to see recent applications.
  2. Tap on Settings, and double-tap visit the Settings page.
  3. Use two fingers to scroll down to Accessibility.
  4. Tap on Accessibility, and double-tap to enter the Accessibility screen.

To turn off TalkBack, follow these steps:

  1. Tap on TalkBack, and double-tap to enter the TalkBack screen.
  2. Tap on the Switch button, and double tap to turn it off.
  3. Tap on "OK" in the dialog that pops up, and double-tap to dismiss the dialog and turn off TalkBack.

Many people have difficulty focusing on small touch targets on the screen. This could be because their fingers are large, or because they have a medical condition that impairs their motor skills. Small touch targets also make it harder for screen reader users to navigate apps using explore by touch.

Open Expand Touch Area Screen. This screen contains a single button, which toggles between Play and Cancel states. The button is small (24dp X 24dp) and has only 1/4th the touchable area than the 48dp X 48dp buttons we have used in other activities in this codelab. Small touch targets are easy for anyone to miss, and in general you want the touchable area of focusable items to be a minimum of 48dp X 48dp. Larger than that is even better.

In this step, you'll expand the touchable area of the play/cancel button without changing its appearance. But before we change anything, let's get a better sense of just how much area the button actually takes.

Tooling and layout bounds

Enable developer options by going to Settings > System > Developer Options. Under the Drawing category, find "Show layout bounds" and turn it on. Your screen should now show the clip bounds, margins, etc. of every visible view.


Go back to the Expand Touch Area Screen, and notice the small layout bounds for the button.


In Android Studio, open content_expand_touch_area.xml, and look at the XML for the image button:

   android:contentDescription="@null" />

Add a minimum width and height to the ImageButton:

   android:minHeight="48dp" />

Press the green Play icon Screen Shot 2016-05-11 at 8.53.21 AM.png from the menu bar to run the app, and look at the layout bounds of the button again. What do you see?


The layout bounds have expanded, making the touchable area 48dp X 48dp, our recommended minimum target.

Try rapidly clicking on the button to toggle between the play and cancel icons, and you'll find that the expanded touch target makes it easier to avoid missing the button.

Go back to developer options (Settings > Developer Options). In the Drawing category, find "Show layout bounds" and set it to "off".

Users with low vision can't read information on a screen if there is not enough contrast between the foreground and background. Low contrast ratios between foreground and background colors can cause views to blur together for some users, while high contrast ratios makes them stand out more clearly. Different lighting situations can amplify the problems created by low contrast ratios.

In this step, you'll see two versions of a screen. One version uses low contrast between background and foreground, and the other version uses high contrast.

There's no coding component in this step. Instead we'll be discussing the contrast ratios used in the two versions, and discuss why one works for accessibility and one does not.

Open Insufficient Contrast Screen, which opens with the default low-contrast version. The screen displays three views—a title, some text, and a Floating Action Button—and these are displayed against a light gray background using the following ratios:


View color

Contrast ratio

Lorem Ipsum Title


Light gray (#BDBDBD)


Lorem Ipsum Text


Medium gray (#757575)


Floating Action Button


Light indigo (#7986CB)


The contrast on all three views is inadequate.

Use the Switch button at the bottom of the screen to toggle to the higher-contrast version of the same screen. This version introduces the following changes:

  1. Overall background: light gray is replaced with white.
  2. Title: light gray is replaced with a medium gray.
  3. Text: medium gray is replaced with a darker gray.
  4. FAB color: light indigo is replaced by a deeper indigo.

Here are the new, improved contrast ratios:


View color

Contrast ratio

Lorem Ipsum Title


Light gray (#757575)


Lorem Ipsum Text


Dark gray (#424242)


Floating Action Button


Indigo (#303F9F)


We've touched on a lot of topics related to Android accessibility. Here are some links and resources you can explore:

Making Android Accessibility Easy (Android Dev Summit '18)

What's new in Android accessibility (Google I/O '18)

What's New in Android Accessibility (Google I/O '17)

Google I/O 2015 - Improve your Android app's accessibility