Android accessibility for developers and QA

Android Accessibility

Bangalore Accessibility Week October 6-10, 2014 Ted Drake, Intuit Accessibility

Accessibility Interaction

Users move accessibility focus by interacting with the touch screen using explore by touch and accessibility gestures.

AccessibilityServices interpret exploration and gestures to facilitate different types of navigation

AccessibilityService Documentation: An accessibility service runs in the background and receives callbacks by the system when AccessibilityEvents are fired. Such events denote some state transition in the user interface, for example, the focus has changed, a button has been clicked, etc. Such a service can optionally request the capability for querying the content of the active window. Development of an accessibility service requires extending this class and implementing its abstract methods.

Meet Talk Back

TalkBack is preinstalled on most Android devices, but is also available on the Play Store. TalkBack is enabled from Settings > Accessibility > TalkBack. Enabling TalkBack changes the interaction model of the device.

  • Explore with a single finger.
  • Double-tap to activate the focused item.
  • Use two-finger drag to scroll lists.
  • TalkBack support

Turn on TalkBack

This video shows how to enable TalkBack and how to use it as a developer.

Common Problems

Content Labeling

  • All interactive elements must have a content description:
    • android:contentDescription
    • View#setContentDescription
  • Decorative images:
    • android:contentDescription=“@null”
  • For EditText
    • android:hint
    • labelFor
  • Keep labels short and clear. Send Email

You spend a lot of time making your screens look great, but are you providing the same experience to TalkBack users? contentDescription allows you to own the experience. Setting the contentDescription to null will tell talkback to ignore the image. Use android:hint on form inputs, as the contentDescription will inherit the value of the input.

<textview android:layout_height="match_parent" android:labelfor="@+id/edit_item_name" android:text="Invoice amount">
<edittext android:id="@+id/edit_item_name" android:layout_height="wrap_content" android:hint="Invoice Amount">

This example shows labelFor and android:hint being used on an input. The hint is not announced when the edit text has a value. More information by SSB Bart: Android Accessibility Properties and TalkBack

Grouping and Ordering

TalkBack uses view hierarchy order and on-screen positioning to determine grouping and ordering.

  • Use ViewGroup containers to associate related information. Set android:focusable=“true”
  • The order of items displayed may be controlled.
  • Use android:contentDescription or View#setContentDescription

Font Sizing

  • Android supports large font substitution for low-vision users.
  • Always use scale-independent pixels(sp).
  • Avoid density-independent pixels (dip or dp)
  • This is also important for i18n

WebViews

  • Supported in Android 3.1+
  • Enable JavaScript within WebView
  • Garbage In, Garbage Out! Make sure your HTML is accessible. http://developer.android.com/reference/android/webkit/WebView.html
  • WebViews are not accessible by default, the user must activate this because it uses a JavaScript driven ChromeVox ! The setting for this is ‘Enhanced Web Accessibility‘ or on older devices:’Inject Web Scripts’.This has been solved in KitKat, enhanced web accessibility is included when TalkBack is enabled.
  • Turning on Accessibility mode, including ‘Explore by Touch’ in 4.0+.

Custom Views

This pie chart could be considered a custom view. TalkBack needs to tell the user about positioning, color, text. It also need to describe interactions, such as gestures, taps, and states.

Virtual View Hierarchy

  • Pie Chart
  • Om Parkash 30%
    • clickable
    • checkable
  • Dev Anand 45%
    • clickable
    • checkable
  • Aamir Khan 25%
    • clickable
    • checkable

What are the components? What are their states?

What TalkBack Sees

  • ViewDecor
    • Action Bar
    • Pie Chart
  • LinearLayout
    • Favorite Actor
    • Pie Chart
      • Om Parkash 30%
      • Dev Anand 45%
      • Aamir Khan 25%

Custom Views

  • Delegate accessibility support
  • Map logical items to virtual views
  • Expose information about views
  • Formalize interaction model

setAccessibilityDelegate

ViewCompat.setAccessibilityDelegate(this,  mAccessibilityHelper);
}
@Override
public boolean dispatchHoverEvent(MotionEvent  event) {
  if (mAccessibilityHelper != null &amp;&amp;  mAccessibilityHelper.dispatchHoverEvent(event)) {
      return true;
  }
  return super.dispatchHoverEvent(event);
}  

We want to check for mAccessibilityHelper support

Map Logical to Virtual

Reuse your existing code. The pie chart already:

  • Is drawn on the screen
  • Includes touch events
  • Uniquely identified
@Override
protected int getVirtualViewAt(float x, float y) {
  Wedge wedge = getWedgeAt(x, y);
  if (wedge != null)
     return wedge.getId();
     return ExploreByTouchHelper.INVALID_ID;
}
@Override
protected void getVisibleVirtualViews(List&lt;Integer&gt;  virtualViewIds) {
  for (Wedge wedge : mWedges) {
      virtualViewIds.add(wedge.getId());
  }
} 

Expose Information

Reuse existing code

  • Position
  • Color
  • Label
  • Relative Size
  • Click Handling
  • Checked Status
@Override
protected void onPopulateEventForVirtualView( int virtualViewId, AccessibilityEvent event) {
  Wedge wedge = getWedgeForId(virtualViewId);
  event.setContentDescription(wedge.getLabel() + ": " +  wedge.getPercent() + "%");
}
@Override
protected void onPopulateNodeForVirtualView(int virtualViewId, AccessibilityNodeInfoCompat node) {
  Wedge wedge = getWedgeForId(virtualViewId);
  node.setContentDescription(wedge.getLabel() + ": " +  wedge.getPercent() + "%");
  node.setBoundsInParent(wedge.getLabelBounds());
... 

Formalize Interactions

node.setCheckable(true);
node.setChecked(wedge.isChecked());
node.addAction(AccessibilityNodeInfoCompat.ACTION_CLICK);
}
@Override
protected boolean onPerformActionForVirtualView(int virtualViewId, int action, Bundle arguments) {
  if (action == AccessibilityNodeInfoCompat.ACTION_CLICK) {
      return onWedgeClicked(getWedgeForId(virtualViewId));
  }  

Assign your pre-existing actions to the accessibility node

Android L

  • Custom AccessibilityAction
  • Live Regions
  • Collections
  • Window API

Documentation is sparse for these new features. For more information, see the presentation from Google IO 14 and the Developer preview for Android L: Accessibility and Testing

AccessibilityAction

  • Swipes and other hard to discover actions
  • Actions are activated from the Local Context Menu
  • Provide hints for actions Documentation for this has not yet been released.

Create AccessibilityAction

/**
* @param actionId The id for this action. This should either be one of
* the standard actions or a specific action for your app. In that case it
* is required to use a resource identifier.
*/
public AccessibilityAction(int id, CharSequence label)
new AccessibilityAction(R.id.dismiss, getString(R.string.dismiss));
new AccessibilityAction(ACTION_CLICK,  getString(R.string.play_song));
// Constants for all the standard actions with default label:
AccessibilityAction.ACTION_CLICK 

Handling a Custom Action

eventView.setAccessibilityDelegate(new AccessibilityDelegate {
  @Override
  public onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
      super.onInitializeAccessibilityNodeInfo(host, info);
      info.addAction(new AccessibilityAction(R.id.dismiss,
  }
  @Override getString(R.string.dismiss)));
  public boolean performAccessibilityAction(View host, int action,  Bundle args) {
      if (action == R.id.dismiss) {} // Logic for action
  }
}); 

Live Regions

Collections

Window API

  • Introspect all interactive windows: autocomplete, drawers…
  • AccessibilityFocus can move from one window to another
  • Retrieve information about properties of windows on the screen that sighted users can interact with.
  • Retrieve a list of objects representing windows information: android.accessibilityservice.AccessibilityServic e.getWindows():
  • TYPE_WINDOWS_CHANGED: AccessibilityEvent to see events

Android Testing

  • Use Android Lint
  • Use TalkBack’s Read From Top to make sure everything is announced on the screen
  • Use the On-Screen Overlay to see what is being spoken
  • Touch exploration help

One thought on “Android accessibility for developers and QA”

Leave a Reply

Your email address will not be published. Required fields are marked *