Sorry about the red box, but we really need you to update your browser. Read this excellent article if you're wondering why we are no longer supporting this browser version. Go to Browse Happy for browser suggestions and how to update.

Developing Accessible apps

Accessibility API concepts

Before you use the Accessibility API, you should understand the following concepts.

Concept

Description

role

Each accessible UI object has a role. A role specifies the type of UI component. Roles include text fields, labels, screens, dialog boxes, lists, icons, radio buttons, tables, check boxes, and buttons.

The AccessibleRole interface in the Accessibility API defines roles as constants.

state

Each accessible UI object has a state. A state specifies the current object state as a mask of flags. States include focusable, focused, checked, active, selected, and editable. Objects can have multiple states at a time, such as focusable and focused.

The AccessibleState interface defines states as constants.

container

Some accessible UI objects are containers. Containers are visual elements, such as screens, dialog boxes, lists, and menus, that contain children.

You can discover the children of a container with methods in the AccessibleContext interface.

table

A table is a type of container that displays children in a tabular format.

Examples of tables include the monthly view and weekly view in the calendar, and a table on a web page.

You can discover the table properties for an accessible UI object by using the methods in the AccessibleTable interface.

Introduction to the Accessibility API

Standard UI components, such as TextField, automatically provide information to assistive technology devices such as screen readers. If you use custom UI components (components that extend the standard UI components), you must use the Accessibility API to provide information to assistive technology applications.

For all the custom UI components in your accessible app, you must implement the net.rim.device.api.ui.accessibility.AccessibleContext interface. The methods in this interface identify the information that you want to send to an assistive technology application. For example, in a custom UI component that implements AccessibleContext, getAccessibleRole() returns the control's role, such as AccessibleRole.TEXT_FIELD. If your app contains custom text fields, custom numeric fields, or custom tables, you can also use the AccessibleText, AccessibleValue, or AccessibleTable interfaces.

An assistive technology app registers as an accessibility event listener. When an accessibility event occurs on a custom UI component, the accessible application invokes the accessibleEventOccurred() method in the registered assistive technology application and passes in the event information. The assistive technology app handles the event and performs the appropriate action, such as speaking the text or playing a sound.

The following diagram shows the relationship between an accessible app and an assistive technology app. The AccessibilityDemo sample app that is provided with the BlackBerry Java Plug-in for Eclipse is structured this way.

A diagram showing the relationship between an accessible app and an assistive technology app.

Notifying an assistive technology application when the UI changes

You can enable an app that uses custom UI components to send information to an assistive technology application by using the net.rim.device.api.ui.accessibility package. When a custom UI component changes, an assistive technology application receives a notification about the change and can retrieve more information about the change from the custom UI component.

The notification about the change contains the following information:
  • Name of the custom UI component
  • Type of event, for example, the contents of the custom UI component changing or the custom UI component getting focus
  • Value of the custom UI component before the event
  • Value of the custom UI component after the event

For example, consider an app that uses a custom class called myTextField that extends the TextField class. When a BlackBerry device user changes the text in a myTextField instance, an assistive technology application receives a notification and retrieves information about the text that the user changed.

UI changes that trigger a notification to an assistive technology application

The following changes to a UI component can trigger a notification to an assistive technology application:

  • a change to the position of a cursor
  • a change to the name
  • a change to the text
  • a change in a child component
  • a change in the state
  • a change to the numeric value

UI component states and properties

A UI component can have one or more of the following states:

  • focused
  • focusable
  • expanded
  • expandable
  • collapsed
  • selected
  • selectable
  • pushed
  • checked
  • editable
  • active
  • busy

A UI component can have one or more of the following properties:

  • modal
  • horizontal
  • vertical
  • single-line
  • multi-line

Provide an assistive technology application with information about a UI change

Import the required interface.

import net.rim.device.api.ui.accessibility.AccessibleContext;

AccessibleContext provides the basic accessibility information about a custom UI component.

Create a class that extends the Field class and implements AccessibleContext.

public class MyCustomComponent extends Field 
  implements AccessibleContext
{
}

Create the variables to store the accessibility information for a custom UI component, such as state information.

private int _state = AccessibleState.UNSET;
private String _accessibleName;
private String _title;

Create the methods that add and remove the states for a custom UI component.

protected void addAccessibleStates(int states) 
{
  _state = _state & ~AccessibleState.UNSET;
  _state = _state | states;
}

protected void removeAccessibleStates(int states) 
{
  _state = _state & ~states;
}

public void setAccessibleName(String accessibleName) 
{
  _accessibleName = accessibleName;
}

Implement the get() methods of AccessibleContext to provide access to the tabular, textual, or numerical information for a custom UI component. Return null if the method does not apply to a custom UI component. For example, if the component does not provide textual information, return null in getAccessibleText().

public AccessibleTable getAccessibleTable() 
{
  return null;
}

public AccessibleText getAccessibleText() 
{
  return null;
}

public AccessibleValue getAccessibleValue() 
{
  return null;
}

Create a method that returns an instance of the class that implements AccessibleContext to provide accessibility information about a change to a custom UI component.

public AccessibleContext getAccessibleContext() 
{
  return this;
}

Implement AccessibleContext.getAccessibleRole() to provide information about the type of custom UI component.

public int getAccessibleRole() 
{
  return AccessibleRole.PANEL;
}

Implement AccessibleContext.getAccessibleChildCount() to provide information about the number of accessible child components that a custom UI component contains. It is up to you as the developer of a custom UI component to decide whether or not the component contains accessible children. For example, you can decide whether a child element is an accessible child component based on whether the child element can gain focus and whether the user can interact with the child element directly.

public int getAccessibleChildCount() 
{
  return _icons.size();
}

Implement AccessibleContext.getAccessibleChildAt(int) to provide information about an accessible child component that a custom UI component contains.

public AccessibleContext getAccessibleChildAt(int arg0) 
{
  return (Icon) _icons.elementAt( index );
}

Implement AccessibleContext.getAccessibleName() to provide the name of a custom UI component that changes.

public String getAccessibleName() 
{
  return _accessibleName;
}

Create a method that invokes AccessibleEventDispatcher.dispatchAccessibleEvent (stateChange, oldState, newState, this) to send a notification when the state of a custom UI component changes. Pass the following arguments to the method:

  • the event
  • the old state of the custom UI component
  • the new state of the custom UI component
  • an instance of the custom UI component
protected void onFocus(int direction)
{
  super.onFocus(direction);
       
  int oldState = _state;
  _state = _state | AccessibleState.FOCUSED;
     
  if(isVisible())
  {
    AccessibleEventDispatcher.dispatchAccessibleEvent( 
      AccessibleContext.ACCESSIBLE_STATE_CHANGED, 
      new Integer(oldState), 
      new Integer(_state), 
      this);
  }
}

Provide an assistive technology application with information about text changes

You can provide accessibility information about the custom UI components that display text.

Import the required interfaces.

import net.rim.device.api.ui.accessibility.AccessibleContext;
import net.rim.device.api.ui.accessibility.AccessibleText;

AccessibleContext provides the basic accessibility information about a custom UI component. AccessibleText provides the information about the text in a custom UI component that displays text.

Create a class that extends the Field class and implements AccessibleContext and AccessibleText.

public class AccessibleTextClass extends Field 
  implements AccessibleContext, AccessibleText 
{
}

Create the variables to store the information about the custom UI component's state and contents.

private int _state;
private int _cursor, _anchor;
private String _text;
private Vector _lines; 
private Vector _words; 

Implement AccessibleText.getAtIndex(int part, int index) to provide access to the text at a given position.

public String getAtIndex(int part, int index)
{
  switch(part) 
  {
    case AccessibleText.CHAR:
      return String.valueOf(_text.charAt(index));
                
    case AccessibleText.LINE:
      return (String) _lines.elementAt(index);
                
    case AccessibleText.WORD:
      return (String) _words.elementAt(index);
  }
        
  return null;
}   

Implement AccessibleText.getSelectionStart() to provide access to the position of the first character of text that a BlackBerry device user selects. Return 0 if the user cannot select text.

public int getSelectionStart() 
{
  return _anchor;
}

Implement AccessibleText.getSelectionEnd() to provide access to the position of the last character of text that a BlackBerry device user selects. Return 0 if the user cannot select text.

public int getSelectionEnd() 
{
  return _cursor;
}

Implement AccessibleText.getCaretPosition() to provide access to the position of the cursor within the text. Return 0 if the user cannot select text.

public int getCaretPosition() 
{
  return _cursor;
}

Implement AccessibleText.getSelectionText() to provide access to the selected part of the text.

public String getSelectionText() 
{
  int start = getSelectionStart();
  int end = getSelectionEnd();
  if (start<end) {
    return _text.getText(start,end);
  } else {
    return _text.getText(end,start);
  }
}

Implement AccessibleText.getLineCount() to provide access to the number of lines of text.

public int getLineCount()
{
  return _lines.size();
}

Implement AccessibleText.getCharCount() to provide access to the number of characters in the text.

public int getCharCount()
{
  return _text.length();
}

Provide an assistive technology application with access to information from a table

You can provide accessibility information about the custom UI components that display tabular information.

Import the required interfaces.

import net.rim.device.api.ui.accessibility.AccessibleContext;
import net.rim.device.api.ui.accessibility.AccessibleTable;

AccessibleContext provides the basic accessibility information about a custom UI component. AccessibleTable provides the information about the tabular information in a custom UI component.

Create a class that implements AccessibleContext and AccessibleTable.

public class AccessibleTableClass 
  implements AccessibleContext, AccessibleTable 
{
}

Create the variables to store the accessibility information about the tabular custom UI component.

private int _columnCount;
private int _rowCount;    
private String[] _columnNames;
private String[][] _cells;    

Implement the get() methods of AccessibleTable to provide the accessibility information about the table.

public int getAccessibleColumnCount()
{
  return _columnCount;
}

public int getAccessibleRowCount()
{
  return _rowCount;
}

public AccessibleContext[] getAccessibleColumnHeader()
{
  AccessibleContext[] result = new AccessibleContext[_columnNames.length];
        
  for( int i = 0; i < result.length; i++ ) 
  {
    result[i] = new AccessibleLabel(_columnNames[i], false);
  }
     
  return result;
}

public AccessibleContext[] getAccessibleRowHeader()
{
  return null;
}

Provide an assistive technology application with access to numeric values

You can provide accessibility information about custom UI components that display numeric values, such as progress indicators.

Import the required interfaces.

import net.rim.device.api.ui.accessibility.AccessibleContext;
import net.rim.device.api.ui.accessibility.AccessibleValue;

AccessibleContext provides the basic accessibility information about a custom UI component. AccessibleValue provides the information about the numeric values in a custom UI component that displays numeric values.

Create a class that extends the Field class and implements AccessibleContext and AccessibleValue.

public class GaugeFieldAccessibleValue extends Field
  implements AccessibleContext, AccessibleValue 
{
}

Create the variables to store the custom UI component's state and contents.

private int _state;
private int _min;
private int _current;    
private int _max;

Implement the get() methods of AccessibleValue to provide the information about the numeric values.

public int getCurrentAccessibleValue() 
{
  return _current;
}

public int getMaxAccessibleValue() 
{
  return _max;
}

public int getMinAccessibleValue() 
{
  return _min;
}        

Enable an assistive technology application to receive notification of UI events

If you are building an assistive technology application, such as a screen reader, implement the AccessibleEventListener interface.

Import the required interface.

import net.rim.device.api.ui.accessibility.AccessibleEventListener;

Create a class that implements AccessibleEventListener.

public class ScreenReader implements AccessibleEventListener 
{
}

Implement AccessibleEventListener.accessibleEventOccurred(int event, Object oldValue, Object newValue, AccessibleContext context) to respond to the UI events in an accessible application that registers this assistive technology application as an accessible event listener.

public synchronized void accessibleEventOccurred(
  int event, 
  Object oldValue, 
  Object newValue, 
  AccessibleContext context)
{
  if(context == null)
  {
    return;
  }
        
  int oldState = (oldValue instanceof Integer) ? ((Integer) oldValue).intValue() 
    : 0;
  int newState = (newValue instanceof Integer) ? ((Integer) newValue).intValue() 
    : 0;  
        
  switch(context.getAccessibleRole()) 
  {
    case AccessibleRole.APP_ICON: 
      ScreenReaderHandler.handleAppIcon(event, oldState, newState, context);
      break;
                
    case AccessibleRole.ICON: 
      ScreenReaderHandler.handleIcon(event, oldState, newState, context);
      break;
                
    case AccessibleRole.CHECKBOX: 
      ScreenReaderHandler.handleCheckBox(event, oldState, newState, context);
      break;
                
    case AccessibleRole.CHOICE: 
      ScreenReaderHandler.handleChoice(event, oldState, newState, context);
      break;
            
    ...

  }
}