summaryrefslogtreecommitdiffstats
path: root/docs/html/training
diff options
context:
space:
mode:
authorAlexander Lucas <alexlucas@google.com>2012-03-06 18:13:07 -0800
committerAlexander Lucas <alexlucas@google.com>2012-04-02 17:25:10 -0700
commitdf6c8270e300e2d04f57e24bb2b34c33edce4a0d (patch)
tree0ce203d4d1e189bbdea58ebe24b2c1a6f7dec409 /docs/html/training
parent0e87370077b322b3a88c345a44c6bf3d56617071 (diff)
downloadframeworks_base-df6c8270e300e2d04f57e24bb2b34c33edce4a0d.zip
frameworks_base-df6c8270e300e2d04f57e24bb2b34c33edce4a0d.tar.gz
frameworks_base-df6c8270e300e2d04f57e24bb2b34c33edce4a0d.tar.bz2
initial accessibility class commit
Change-Id: Ib3b8f6e8f70f856e4bb9aae60b5d58d0f3e320be
Diffstat (limited to 'docs/html/training')
-rw-r--r--docs/html/training/accessibility/accessible-app.jd194
-rw-r--r--docs/html/training/accessibility/index.jd56
-rw-r--r--docs/html/training/accessibility/service.jd286
3 files changed, 536 insertions, 0 deletions
diff --git a/docs/html/training/accessibility/accessible-app.jd b/docs/html/training/accessibility/accessible-app.jd
new file mode 100644
index 0000000..f4087b8
--- /dev/null
+++ b/docs/html/training/accessibility/accessible-app.jd
@@ -0,0 +1,194 @@
+
+page.title=Developing Accessible Applications
+parent.title=Implementing Accessibility
+parent.link=index.html
+
+trainingnavtop=true
+next.title=Developing an Accessibility Service
+next.link=service.html
+
+@jd:body
+
+
+
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to</h2>
+<ol>
+ <li><a href="#contentdesc">Add Content Descriptions</a></li>
+ <li><a href="#focus">Design for Focus Navigation</a></li>
+ <li><a href="#events">Fire Accessibility Events</a></li>
+ <li><a href="#testing">Test Your Application</a></li>
+</ol>
+
+<!-- other docs (NOT javadocs) -->
+<h2>You should also read</h2>
+<ul>
+ <li><a href="{@docRoot}guide/topics/ui/accessibility/apps.html">Making
+ Applications Accessible</a></li>
+</ul>
+
+
+</div>
+</div>
+
+<p>Android has several accessibility-focused features baked into the platform,
+which make it easy to optimize your application for those with visual or
+physical disabilities. However, it's not always obvious what the correct
+optimizations are, or the easiest way to leverage the framework toward this
+purpose. This lesson shows you how to implement the strategies and platform
+features that make for a great accessibility-enabled Android application.</p>
+
+<h2 id="contentdesc">Add Content Descriptions</h2>
+<p>A well-designed user interface (UI) often has elements that don't require an explicit
+label to indicate their purpose to the user. A checkbox next to an item in a
+task list application has a fairly obvious purpose, as does a trash can in a file
+manager application. However, to your users with vision impairment, other UI
+cues are needed.</p>
+
+<p>Fortunately, it's easy to add labels to UI elements in your application that
+can be read out loud to your user by a speech-based accessibility service like <a
+ href="https://market.android.com/details?id=com.google.android.marvin.talkback">TalkBack</a>.
+If you have a label that's likely not to change during the lifecycle of the
+application (such as "Pause" or "Purchase"), you can add it via the XML layout,
+by setting a UI element's <a
+ href="{@docRoot}reference/android/view.View#attr_android:contentDescription">android:contentDescription</a> attribute, like in this
+example:</p>
+<pre>
+&lt;Button
+ android:id=”@+id/pause_button”
+ android:src=”@drawable/pause”
+ android:contentDescription=”@string/pause”/&gt;
+</pre>
+
+<p>However, there are plenty of situations where it's desirable to base the content
+description on some context, such as the state of a toggle button, or a piece
+selectable data like a list item. To edit the content description at runtime,
+use the {@link android.view.View#setContentDescription(CharSequence)
+setContentDescription()} method, like this:</p>
+
+<pre>
+String contentDescription = "Select " + strValues[position];
+label.setContentDescription(contentDescription);
+</pre>
+
+<p>This addition to your code is the simplest accessibility improvement you can make to your
+application, but one of the most useful. Try to add content descriptions
+wherever there's useful information, but avoid the web-developer pitfall of
+labelling <em>everything</em> with useless information. For instance, don't set
+an application icon's content description to "app icon". That just increases
+the noise a user needs to navigate in order to pull useful information from your
+interface.</p>
+
+<p>Try it out! Download <a
+ href="https://market.android.com/details?id=com.google.android.marvin.talkback">TalkBack</a>
+(an accessibility service published by Google) and enable it in <strong>Settings
+ &gt; Accessibility &gt; TalkBack</strong>. Then navigate around your own
+application and listen for the audible cues provided by TalkBack.</p>
+
+<h2 id="focus">Design for Focus Navigation</h2>
+<p>Your application should support more methods of navigation than the
+touch screen alone. Many Android devices come with navigation hardware other
+than the touchscreen, like a D-Pad, arrow keys, or a trackball. In addition,
+later Android releases also support connecting external devices like keyboards
+via USB or bluetooth.</p>
+
+<p>In order to enable this form of navigation, all navigational elements that
+the user should be able to navigate to need to be set as focusable. This
+modification can be
+done at runtime using the
+{@link android.view.View#setFocusable View.setFocusable()} method on that UI
+control, or by setting the <a
+ href="{@docRoot}android.view.View#attr_android:focusable">{@code
+ android:focusable}</a>
+attrubute in your XML layout files.</p>
+
+<p>Also, each UI control has 4 attributes,
+<a href="{@docRoot}reference/android/view/View#attr_android:nextFocusUp">{@code
+ android:nextFocusUp}</a>,
+<a
+ href="{@docRoot}reference/android/view/View#attr_android:nextFocusDown">{@code
+ android:nextFocusDown}</a>,
+<a
+ href="{@docRoot}reference/android/view/View#attr_android:nextFocusLeft">{@code
+ android:nextFocusLeft}</a>,
+and <a
+ href="{@docRoot}reference/android/view/View#attr_android:nextFocusRight">{@code
+ android:nextFocusRight}</a>,
+which you can use to designate
+the next view to receive focus when the user navigates in that direction. While
+the platform determines navigation sequences automatically based on layout
+proximity, you can use these attributes to override that sequence if it isn't
+appropriate in your application. </p>
+
+<p>For instance, here's how you represent a button and label, both
+focusable, such that pressing down takes you from the button to the text view, and
+pressing up would take you back to the button.</p>
+
+
+<pre>
+&lt;Button android:id="@+id/doSomething"
+ android:focusable="true"
+ android:nextFocusDown=”@id/label”
+ ... /&gt;
+&lt;TextView android:id="@+id/label"
+ android:focusable=”true”
+ android:text="@string/labelText"
+ android:nextFocusUp=”@id/doSomething”
+ ... /&gt;
+</pre>
+
+<p>Verify that your application works intuitively in these situations. The
+easiest way is to simply run your application in the Android emulator, and
+navigate around the UI with the emulator's arrow keys, using the OK button as a
+replacement for touch to select UI controls.</p>
+
+<h2 id="events">Fire Accessibility Events</h2>
+<p>If you're using the view components in the Android framework, an
+{@link android.view.accessibility.AccessibilityEvent} is created whenever you
+select an item or change focus in your UI. These events are examined by the
+accessibility service, enabling it to provide features like text-to-speech to
+the user.</p>
+
+<p>If you write a custom view, make sure it fires events at the appropriate
+times. Generate events by calling {@link
+android.view.View#sendAccessibilityEvent(int)}, with a parameter representing
+the type of event that occurred. A complete list of the event types currently
+supported can be found in the {@link
+android.view.accessibility.AccessibilityEvent} reference documentation.
+
+<p>As an example, if you want to extend an image view such that you can write
+captions by typing on the keyboard when it has focus, it makes sense to fire an
+{@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_TEXT_CHANGED}
+event, even though that's not normally built into image views. The code to
+generate that event would look like this:</p>
+<pre>
+public void onTextChanged(String before, String after) {
+ ...
+ if (AccessibilityManager.getInstance(mContext).isEnabled()) {
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED);
+ }
+ ...
+}
+</pre>
+
+<h2 id="testing">Test Your Application</h2>
+<p>Be sure to test the accessibility functionality as you add it to your
+application. In order to test the content descriptions and Accessibility
+events, install and enable an accessibility service. One option is <a
+ href="https://play.google.com/store/details?id=com.google.android.marvin.talkback">Talkback</a>,
+a free, open source screen reader available on Google Play. With the service
+enabled, test all the navigation flows through your application and listen to
+the spoken feedback.</p>
+
+<p>Also, attempt to navigate your application using a directional controller,
+instead of the touch screen. You can use a physical device with a d-pad or
+trackball if one is available. If not, use the Android emulator and it's
+simulated keyboard controls.</p>
+
+<p>Between the service providing feedback and the directional navigation through
+your application, you should get a sense of what your application is like to
+navigate without any visual cues. Fix problem areas as they appear, and you'll
+end up with with a more accessible Android application.</p>
diff --git a/docs/html/training/accessibility/index.jd b/docs/html/training/accessibility/index.jd
new file mode 100644
index 0000000..d5178a9
--- /dev/null
+++ b/docs/html/training/accessibility/index.jd
@@ -0,0 +1,56 @@
+page.title=Implementing Accessibility
+
+trainingnavtop=true
+startpage=true
+next.title=Developing Accessible Applications
+next.link=accessible-app.html
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>Dependencies and prerequisites</h2>
+<ul>
+ <li>Android 2.0 (API Level 5) or higher</li>
+Playback</a></li>
+</ul>
+
+<h2>You should also read</h2>
+<ul>
+ <li><a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a></li>
+</ul>
+
+</div>
+</div>
+
+<p>When it comes to reaching as wide a userbase as possible, it's important to
+pay attention to accessibility in your Android application. Cues in your user
+interface that may work for a majority of users, such as a visible change in
+state when a button is pressed, can be less optimal if the user is visually
+impaired.</p>
+
+<p>This class shows you how to make the most of the accessibility features
+built into the Android framework. It covers how to optimize your app for
+accessibility, leveraging platform features like focus navigation and content
+descriptions. It also covers how to build accessibility services, that can
+facilitate user interaction with <strong>any</strong> Android application, not
+just your own.</p>
+
+<h2>Lessons</h2>
+
+<dl>
+ <dt><b><a href="accessible-app.html">Developing Accessible Applications</a></b></dt>
+ <dd>Learn to make your Android application accessible. Allow for easy
+ navigation with a keyboard or directional pad, set labels and fire events
+ that can be interpreted by an accessibility service to facilitate a smooth
+ user experience.</dd>
+
+ <dt><b><a href="service.html">Developing Accessibility Services</a></b></dt>
+ <dd>Develop an accessibility service that listens for accessibility events,
+ mines those events for information like event type and content descriptions,
+ and uses that information to communicate with the user. The example will
+ use a text-to-speech engine to speak to the user.</dd>
+
+</dl>
+
diff --git a/docs/html/training/accessibility/service.jd b/docs/html/training/accessibility/service.jd
new file mode 100644
index 0000000..f62506b
--- /dev/null
+++ b/docs/html/training/accessibility/service.jd
@@ -0,0 +1,286 @@
+
+page.title=Developing an Accessibility Service
+parent.title=Implementing Accessibility
+parent.link=index.html
+
+trainingnavtop=true
+previous.title=Developing Accessible Applications
+previous.link=accessible-app.html
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<h2>This lesson teaches you to</h2>
+<ol>
+ <li><a href="#create">Create Your Accessibility Service</a></li>
+ <li><a href="#configure">Configure Your Accessibility Service</a></li>
+ <li><a href="#events">Respond to AccessibilityEvents</a></li>
+ <li><a href="#query">Query the View Heirarchy for More Context</a></li>
+</ol>
+
+<h2>You should also read</h2>
+<ul>
+ <li><a href="{@docRoot}guide/topics/ui/accessibility/services.html">Building
+ Accessibility Services</a></li>
+</ul>
+
+</div>
+</div>
+
+
+<p>Accessibility services are a feature of the Android framework designed to
+provide alternative navigation feedback to the user on behalf of applications
+installed on Android devices. An accessibility service can communicate to the
+user on the application's behalf, such as converting text to speech, or haptic
+feedback when a user is hovering on an important area of the screen. This
+lesson covers how to create an accessibility service, process information
+received from the application, and report that information back to the
+user.</p>
+
+
+<h2 id="create">Create Your Accessibility Service</h2>
+<p>An accessibility service can be bundled with a normal application, or created
+as a standalone Android project. The steps to creating the service are the same
+in either situation. Within your project, create a class that extends {@link
+android.accessibilityservice.AccessibilityService}.</p>
+
+<pre>
+package com.example.android.apis.accessibility;
+
+import android.accessibilityservice.AccessibilityService;
+
+public class MyAccessibilityService extends AccessibilityService {
+...
+ &#64;Override
+ public void onAccessibilityEvent(AccessibilityEvent event) {
+ }
+
+ &#64;Override
+ public void onInterrupt() {
+ }
+
+...
+}
+</pre>
+
+<p>Like any other service, you also declare it in the manifest file.
+Remember to specify that it handles the {@code android.accessibilityservice} intent,
+so that the service is called when applications fire an
+{@link android.view.accessibility.AccessibilityEvent}.</p>
+
+<pre>
+&lt;application ...&gt;
+...
+&lt;service android:name=".MyAccessibilityService"&gt;
+ &lt;intent-filter&gt;
+ &lt;action android:name="android.accessibilityservice.AccessibilityService" /&gt;
+ &lt;/intent-filter&gt;
+ . . .
+&lt;/service&gt;
+...
+&lt;/application&gt;
+</pre>
+
+<p>If you created a new project for this service, and don't plan on having an
+application, you can remove the starter Activity class (usually called MainActivity.java) from your source. Remember to
+also remove the corresponding activity element from your manifest.</p>
+
+<h2 id="configure">Configure Your Accessibility Service</h2>
+<p>Setting the configuration variables for your accessibility service tells the
+system how and when you want it to run. Which event types would you like to
+respond to? Should the service be active for all applications, or only specific
+package names? What different feedback types does it use?</p>
+
+<p>You have two options for how to set these variables. The
+backwards-compatible option is to set them in code, using {@link
+android.accessibilityservice.AccessibilityService#setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo)}.
+To do that, override the {@link
+android.accessibilityservice.AccessibilityService#onServiceConnected()} method
+and configure your service in there.</p>
+
+<pre>
+&#64;Override
+public void onServiceConnected() {
+ // Set the type of events that this service wants to listen to. Others
+ // won't be passed to this service.
+ info.eventTypes = AccessibilityEvent.TYPE_VIEW_CLICKED |
+ AccessibilityEvent.TYPE_VIEW_FOCUSED;
+
+ // If you only want this service to work with specific applications, set their
+ // package names here. Otherwise, when the service is activated, it will listen
+ // to events from all applications.
+ info.packageNames = new String[]
+ {"com.example.android.myFirstApp", "com.example.android.mySecondApp"};
+
+ // Set the type of feedback your service will provide.
+ info.feedbackType = AccessibilityServiceInfo.FEEDBACK_SPOKEN;
+
+ // Default services are invoked only if no package-specific ones are present
+ // for the type of AccessibilityEvent generated. This service *is*
+ // application-specific, so the flag isn't necessary. If this was a
+ // general-purpose service, it would be worth considering setting the
+ // DEFAULT flag.
+
+ // info.flags = AccessibilityServiceInfo.DEFAULT;
+
+ info.notificationTimeout = 100;
+
+ this.setServiceInfo(info);
+
+}
+</pre>
+
+<p>Starting with Android 4.0, there is a second option available: configure the
+service using an XML file. Certain configuration options like
+{@link android.R.attr#canRetrieveWindowContent} are only available if you
+configure your service using XML. The same configuration options above, defined
+using XML, would look like this:</p>
+
+<pre>
+&lt;accessibility-service
+ android:accessibilityEventTypes="typeViewClicked|typeViewFocused"
+ android:packageNames="com.example.android.myFirstApp, com.example.android.mySecondApp"
+ android:accessibilityFeedbackType="feedbackSpoken"
+ android:notificationTimeout="100"
+ android:settingsActivity="com.example.android.apis.accessibility.TestBackActivity"
+ android:canRetrieveWindowContent="true"
+/&gt;
+</pre>
+
+<p>If you go the XML route, be sure to reference it in your manifest, by adding
+a <a
+href="{@docRoot}guide/topics/manifest/meta-data-element.html">&lt;meta-data&gt;</a> tag to
+your service declaration, pointing at the XML file. If you stored your XML file
+in {@code res/xml/serviceconfig.xml}, the new tag would look like this:</p>
+
+<pre>
+&lt;service android:name=".MyAccessibilityService"&gt;
+ &lt;intent-filter&gt;
+ &lt;action android:name="android.accessibilityservice.AccessibilityService" /&gt;
+ &lt;/intent-filter&gt;
+ &lt;meta-data android:name="android.accessibilityservice"
+ android:resource="@xml/serviceconfig" /&gt;
+&lt;/service&gt;
+</pre>
+
+<h2 id="events">Respond to AccessibilityEvents</h2>
+<p>Now that your service is set up to run and listen for events, write some code
+so it knows what to do when an {@link
+android.view.accessibility.AccessibilityEvent} actually arrives! Start by
+overriding the {@link
+android.accessibilityservice.AccessibilityService#onAccessibilityEvent} method.
+In that method, use {@link
+android.view.accessibility.AccessibilityEvent#getEventType} to determine the
+type of event, and {@link
+android.view.accessibility.AccessibilityEvent#getContentDescription} to extract
+any label text associated with the fiew that fired the event.</pre>
+
+<pre>
+&#64;Override
+public void onAccessibilityEvent(AccessibilityEvent event) {
+ final int eventType = event.getEventType();
+ String eventText = null;
+ switch(eventType) {
+ case AccessibilityEvent.TYPE_VIEW_CLICKED:
+ eventText = "Focused: ";
+ break;
+ case AccessibilityEvent.TYPE_VIEW_FOCUSED:
+ eventText = "Focused: ";
+ break;
+ }
+
+ eventText = eventText + event.getContentDescription();
+
+ // Do something nifty with this text, like speak the composed string
+ // back to the user.
+ speakToUser(eventText);
+ ...
+}
+</pre>
+
+<h2 id="query">Query the View Heirarchy for More Context</h2>
+<p>This step is optional, but highly useful. One of the new features in Android
+4.0 (API Level 14) is the ability for an
+{@link android.accessibilityservice.AccessibilityService} to query the view
+hierarchy, collecting information about the the UI component that generated an event, and
+its parent and children. In order to do this, make sure that you set the
+following line in your XML configuration:</p>
+<pre>
+android:canRetrieveWindowContent="true"
+</pre>
+<p>Once that's done, get an {@link
+android.view.accessibility.AccessibilityNodeInfo} object using {@link
+android.view.accessibility.AccessibilityEvent#getSource}. This call only
+returns an object if the window where the event originated is still the active
+window. If not, it will return null, so <em>behave accordingly</em>. The
+following example is a snippet of code that, when it receives an event, does
+the following:
+<ol>
+ <li>Immediately grab the parent of the view where the event originated</li>
+ <li>In that view, look for a label and a check box as children views</li>
+ <li>If it finds them, create a string to report to the user, indicating
+ the label and whether it was checked or not.</li>
+ <li>If at any point a null value is returned while traversing the view
+ hierarchy, the method quietly gives up.</li>
+</ol>
+
+<pre>
+
+// Alternative onAccessibilityEvent, that uses AccessibilityNodeInfo
+
+&#64;Override
+public void onAccessibilityEvent(AccessibilityEvent event) {
+
+ AccessibilityNodeInfo source = event.getSource();
+ if (source == null) {
+ return;
+ }
+
+ // Grab the parent of the view that fired the event.
+ AccessibilityNodeInfo rowNode = getListItemNodeInfo(source);
+ if (rowNode == null) {
+ return;
+ }
+
+ // Using this parent, get references to both child nodes, the label and the checkbox.
+ AccessibilityNodeInfo labelNode = rowNode.getChild(0);
+ if (labelNode == null) {
+ rowNode.recycle();
+ return;
+ }
+
+ AccessibilityNodeInfo completeNode = rowNode.getChild(1);
+ if (completeNode == null) {
+ rowNode.recycle();
+ return;
+ }
+
+ // Determine what the task is and whether or not it's complete, based on
+ // the text inside the label, and the state of the check-box.
+ if (rowNode.getChildCount() &lt; 2 || !rowNode.getChild(1).isCheckable()) {
+ rowNode.recycle();
+ return;
+ }
+
+ CharSequence taskLabel = labelNode.getText();
+ final boolean isComplete = completeNode.isChecked();
+ String completeStr = null;
+
+ if (isComplete) {
+ completeStr = getString(R.string.checked);
+ } else {
+ completeStr = getString(R.string.not_checked);
+ }
+ String reportStr = taskLabel + completeStr;
+ speakToUser(reportStr);
+}
+
+</pre>
+
+<p>Now you have a complete, functioning accessibility service. Try configuring
+how it interacts with the user, by adding Android's <a
+ href="http://developer.android.com/resources/articles/tts.html">text-to-speech
+ engine</a>, or using a {@link android.os.Vibrator} to provide haptic
+feedback!</p>