Making Airbnb’s Android app more accessible

Julia Fu
The Airbnb Tech Blog
7 min readJan 11, 2023

--

By: Julia Fu, Peter Elliott

Decorative image for the blog post.

At Airbnb, we have been consciously designing and building products to be equally usable by all users. Making our mobile apps and websites more accessible not only aligns with our company’s mission of creating a world where people can belong anywhere, but also supports the civil rights of people with disabilities and complies with the law.

In this article, we highlight some of the efforts we have made to make the app more accessible, for example, labeling UI elements, grouping related content, supporting large font scale, providing heading and page names. The Airbnb app is one of the most popular travel apps with millions of users and supports many features. Making such a complex app more accessible is a huge endeavor that we are continuously working on.

Part I: Build for all: best practices we apply

At Airbnb, we follow industry best practices to make the Android app accessible. If you are interested, you can find all best practices we follow from the official Android documentation for platform specific guidelines and the Web Content Accessibility Guidelines as an industry standard. Here we want to highlight a few examples where we apply the best practices:

Best Practice: content descriptions

Everything shall have accurate content descriptions unless they should be ignored by assistive technology. In these examples, the share button has a content description that TalkBack reads aloud. TalkBack skips the house icon.

Share button highlighted on a listing page. TalkBack output says ‘Share, Button’.
Row highlighted with a star icon, bolded and underlined text, another icon with text, and subtitle text on a listing page. TalkBack output omits content for the icons and says ‘Rated 4.88 out of 5 from 203 reviews. Superhost Willington, Connecticut, United States’.

Best practice: grouping

Elements of a natural group can be announced together with focusable containers for better usability and accuracy. For instance, Talkback reads all listing content on the card together.

Listing card with a photo, rating, title, and price highlighted on a listing collections page. TalkBack output reads all the information together.

Best practice: font scale

UI shall be usable when the user increases the system font scale.

Default vs enlarged font scale:

A listing search page with a search bar, tabs with category names, two listing cards, a floating Map button, and a navigation bar at the bottom
Same page in a larger font, with only the first listing card visible
Default font scale on the left. Enlarged font scale on the right.

Scaling best practices

The Airbnb Android app is a large app with many screens. It would be exhausting and not scalable if we needed to add accessibility code everywhere. Fortunately, our Design Language System enables us to broadly apply these best practices across product surfaces in a highly efficient way. Every screen is built with a collection of reusable UI components. When we improve the accessibility for one component, the change applies to all the pages with this component as part of the view. This has a long-lasting positive effect on our app’s accessibility improvements. Here’s an example:

The accessibility filters screen for a stay includes a large icon, a heading, subheadings, multiple checkbox options for various features (such as “no stairs or steps to enter”), and a footer..
The same screen with component names overlaid on top, such as DocumentMarquee for the heading, LeadingIconRow and CheckboxRows.

Take SectionHeader as an example. This UI component is used to communicate the structure on the page and group content together. We mark this component to be an accessibility heading in the component code so it is accessible in all screens that contain this component.

Part II: Empower engineers with automated checks

We invested in automated accessibility testing and linting to run with every code commit, which creates a quick feedback loop for engineers and empowers them to make the app accessible at code writing time. The checks are fast, reliable, and scale well with our fast-growing features in the Android app.

Automated testing

We set up Espresso-based automated testing to check for accessibility issues. Espresso is a popular testing library for Android UI with built-in accessibility checks. It supports a comprehensive set of accessibility rules and is easy to set up:

If accessibility checks fail, the test outputs an error stack trace that engineers can use to debug the issue. For example:

In this example, engineers can provide a content description to the image view to satisfy accessibility requirements.

We also screenshot test our components with a larger font size to ensure the behavior is correct using Happo.

A screenshot test of the marquee component using a larger system font. The marquee component contains a vertical stack with an icon, smaller kicker text, larger title text, and smaller subtitle text.

Linting

In addition to automated testing, we also enabled linting, including Android Lint rules for accessibility and custom lint rules built with Ktlint.

Here is an example of an Android accessibility lint rule:

Besides the built-in Android Lint, we also use Ktlint to build custom lint rules. For instance, when a user navigates to a new screen, we provide a page name for a screen reader to announce. We use the following rule to make sure that the page name is localized.

Lint rules are straightforward to set up and provide timely feedback, but linting has limitations — it can only perform static code analysis.

Today, these automated checks run as part of CI (Continuous Integration) checks for every code commit. If a pull request does not pass the checks, it will be blocked from being merged into the primary code branch. We still use manual testing to cover the areas that automated checks do not cover, such as the traversal order of UI elements on a page. Automated and manual checks complement each other well.

Part III: Looking into the future: Accessibility with Compose

Over the past year, we have been integrating Jetpack Compose into our app. Google’s Accessibility in Compose documentation has been a great resource to ensure our Compose components and screens remain accessible. While there are some notable things missing that existed with Views (e.g. focus order modification), Compose is still a young library and we look forward to future improvements. Here are a couple of things worth mentioning about our Compose-specific accessibility tooling:

Proactively encourage content descriptions in the API

One of our guidelines for UI components is that content descriptions exposed via a function parameter should not use a default value. This brings accessibility to the top of mind when an engineer uses the component as they need to consider what value to pass. A null value is still acceptable in cases where that UI element is not important for accessibility.

A screenshot of an IconRow component that shows an icon beside two lines of text.

Page name announcements

A screenshot of several photos of a listing with the up button focused in the toolbar. The TalkBack output says “Photo tour of the listing”. We allow hosts to add captions for photos. If captions are provided, they are announced by Talkback when a user clicks on the photo. If no captions are provided, we do not generate them.

When using Fragments and Views, we use the View.setAccessibilityPaneTitle() and View.announceForAccessibility() APIs when navigating to a new screen to announce a descriptive page name to the user. These APIs do not exist in Compose but we wanted to keep the functionality since it helps to provide more context as to what the new screen displays. Our current workaround sets certain semantics on the screen’s outer composable:

We use the liveRegion property so changes can be announced when the content description changes. This is useful for pages whose entire content is determined by a response from the server. In this case, TalkBack would announce “Content Loading” while the network request is pending, followed by “Content Loaded” when it completes, and finally the page description defined in the server response. One downside of this approach is that it requires the outer container to be focusable, which requires an additional navigation action to get to the content.

Closing thoughts

Making our Android app more accessible has been an impactful journey. Improving app accessibility involves following best practices, adding rigorous enforcements, continually learning from mistakes, and putting in the work. All of these are worthy efforts to make sure an app works for all users.

If you are excited about building highly accessible products and the framework to support them, check out some of our related open positions:

Staff Android Software Engineer, Guest

Senior iOS Software Engineer, Infrastructure

Acknowledgments

It is a huge endeavor to make a complex app like the Airbnb Android app more accessible. This work wouldn’t be possible without the enormous efforts from the digital accessibility team and the close-knit Android community at Airbnb. Every engineer has contributed to making the features they own accessible. Making the Android app more accessible is an ongoing effort and it could not succeed without all of them.

****************

All product names, logos, and brands are property of their respective owners. All company, product and service names used in this website are for identification purposes only. Use of these names, logos, and brands does not imply endorsement.

All bookings included in this blog post are intended to illustrate. Airbnb does not endorse or promote these listings or any other accommodations or experiences on the platform.

--

--