diff options
| author | Svetoslav Ganov <svetoslavganov@google.com> | 2011-10-28 19:08:02 -0700 |
|---|---|---|
| committer | Svetoslav Ganov <svetoslavganov@google.com> | 2011-10-28 19:18:24 -0700 |
| commit | 101f061d3566023ac65b7bcdc548b5875b58a2e7 (patch) | |
| tree | f4a3a375c3702328dc071501e3b5c729fde28465 /samples/ApiDemos/src/com/example/android/apis/accessibility/TaskBackService.java | |
| parent | ded0dc055f64492894445b76fdce060ae9b98b90 (diff) | |
Folding Accessibility Service sample into ApiDemos.
1. Moving Accerssibility Service sample into ApiDemos since
we are putting all accessibility samples there.
2. Fixed regressions (mainly due to adding new event types)
in the Accessibility Service sample.
3. Updated the Query Window Content sample to have some
instructions and to work with touch exploration.
Change-Id: I226ac4130f7f8cae47bb52cbdeab9f104cfaba40
Diffstat (limited to 'samples/ApiDemos/src/com/example/android/apis/accessibility/TaskBackService.java')
| -rw-r--r-- | samples/ApiDemos/src/com/example/android/apis/accessibility/TaskBackService.java | 145 |
1 files changed, 88 insertions, 57 deletions
diff --git a/samples/ApiDemos/src/com/example/android/apis/accessibility/TaskBackService.java b/samples/ApiDemos/src/com/example/android/apis/accessibility/TaskBackService.java index dbbfe3a1b..c7088be98 100644 --- a/samples/ApiDemos/src/com/example/android/apis/accessibility/TaskBackService.java +++ b/samples/ApiDemos/src/com/example/android/apis/accessibility/TaskBackService.java @@ -19,6 +19,7 @@ package com.example.android.apis.accessibility; import com.example.android.apis.R; import android.accessibilityservice.AccessibilityService; +import android.text.TextUtils; import android.util.Log; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityNodeInfo; @@ -28,26 +29,40 @@ import android.speech.tts.TextToSpeech.OnInitListener; import java.util.Locale; -/** The TaskBackService listens for AccessibilityEvents, and turns them into information it can - * communicate to the user with speech. +/** + * This class demonstrates how an accessibility service can query + * window content to improve the feedback given to the user. */ public class TaskBackService extends AccessibilityService implements OnInitListener { - private final String LOG_TAG = "TaskBackService/onAccessibilityEvent"; - private boolean mTextToSpeechInitialized = false; - private TextToSpeech mTts = null; + /** Tag for logging. */ + private static final String LOG_TAG = "TaskBackService/onAccessibilityEvent"; + + /** Comma separator. */ private static final String SEPARATOR = ", "; + /** The class name of TaskListView - for simplicity we speak only its items. */ + private static final String TASK_LIST_VIEW_CLASS_NAME = + "com.example.android.apis.accessibility.TaskListView"; + + /** Flag whether Text-To-Speech is initialized. */ + private boolean mTextToSpeechInitialized; + /** Handle to the Text-To-Speech engine. */ + private TextToSpeech mTts; - /** Initializes the Text-To-Speech engine as soon as the service is connected. */ + /** + * {@inheritDoc} + */ @Override public void onServiceConnected() { + // Initializes the Text-To-Speech engine as soon as the service is connected. mTts = new TextToSpeech(getApplicationContext(), this); } - /** Processes an AccessibilityEvent, by traversing the View's tree and putting together a - * message to speak to the user. + /** + * Processes an AccessibilityEvent, by traversing the View's tree and + * putting together a message to speak to the user. */ @Override public void onAccessibilityEvent(AccessibilityEvent event) { @@ -56,55 +71,49 @@ public class TaskBackService extends AccessibilityService implements OnInitListe return; } - int eventType = event.getEventType(); - if (eventType != AccessibilityEvent.TYPE_VIEW_CLICKED) { + // This AccessibilityNodeInfo represents the view that fired the + // AccessibilityEvent. The following code will use it to traverse the + // view hierarchy, using this node as a starting point. + // + // NOTE: Every method that returns an AccessibilityNodeInfo may return null, + // because the explored window is in another process and the + // corresponding View might be gone by the time your request reaches the + // view hierarchy. + AccessibilityNodeInfo source = event.getSource(); + if (source == null) { return; } - /* This AccessibilityNodeInfo represents the view that fired the - * AccessibilityEvent. The following code will use it to traverse - * the view hierarchy, using this node as a starting point. - */ - AccessibilityNodeInfo entryNode = event.getSource(); - - /* Every method that returns an AccessibilityNodeInfo may return null, - * because the explored window is in another process and the corresponding - * View might be gone by the time your request reaches the view hierarchy." - */ - if (entryNode == null) { - return; - } // Grab the parent of the view that fired the event. - AccessibilityNodeInfo rowNode = entryNode.getParent(); - + AccessibilityNodeInfo rowNode = getListItemNodeInfo(source); if (rowNode == null) { - return; + return; } - /* Using this parent, get references to both child nodes, - * the label and the checkbox. - */ + // Using this parent, get references to both child nodes, the label and the checkbox. AccessibilityNodeInfo labelNode = rowNode.getChild(0); - AccessibilityNodeInfo completeNode = rowNode.getChild(1); - - if (labelNode == null || completeNode == null) { - return; + if (labelNode == null) { + rowNode.recycle(); + return; } - /* Using these to determine what the task is and whether or not - * it's complete, based on the text inside the label, and the state - * of the checkbox. - */ + AccessibilityNodeInfo completeNode = rowNode.getChild(1); + if (completeNode == null) { + rowNode.recycle(); + return; + } - // Quick check to make sure we're not in the ApiDemos nav. + // 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() < 2 || !rowNode.getChild(1).isCheckable()) { + rowNode.recycle(); return; } CharSequence taskLabel = labelNode.getText(); - boolean isComplete = completeNode.isChecked(); + final boolean isComplete = completeNode.isChecked(); - String completeStr = null;; + String completeStr = null; if (isComplete) { completeStr = getString(R.string.task_complete); } else { @@ -112,44 +121,66 @@ public class TaskBackService extends AccessibilityService implements OnInitListe } String taskStr = getString(R.string.task_complete_template, taskLabel, completeStr); - StringBuilder forSpeech = new StringBuilder(taskStr); - - /* The custom listview added extra context to the event by adding - * an AccessibilityRecord to it. Extract that from the event and read it. - */ - int records = event.getRecordCount(); + StringBuilder utterance = new StringBuilder(taskStr); + // The custom ListView added extra context to the event by adding an + // AccessibilityRecord to it. Extract that from the event and read it. + final int records = event.getRecordCount(); for (int i = 0; i < records; i++) { AccessibilityRecord record = event.getRecord(i); CharSequence contentDescription = record.getContentDescription(); - if (contentDescription != null) { - forSpeech.append(SEPARATOR).append(contentDescription); + if (!TextUtils.isEmpty(contentDescription )) { + utterance.append(SEPARATOR); + utterance.append(contentDescription); } } - /* Speak the forSpeech string to the user. QUEUE_ADD adds the string to the end of the - * queue, QUEUE_FLUSH would interrupt whatever was currently being said. - */ - mTts.speak(forSpeech.toString() , TextToSpeech.QUEUE_ADD, null); - Log.d(LOG_TAG, forSpeech.toString()); + // Announce the utterance. + mTts.speak(utterance.toString(), TextToSpeech.QUEUE_FLUSH, null); + Log.d(LOG_TAG, utterance.toString()); + } + + private AccessibilityNodeInfo getListItemNodeInfo(AccessibilityNodeInfo source) { + AccessibilityNodeInfo current = source; + while (true) { + AccessibilityNodeInfo parent = current.getParent(); + if (parent == null) { + return null; + } + if (TASK_LIST_VIEW_CLASS_NAME.equals(parent.getClassName())) { + return current; + } + // NOTE: Recycle the infos. + AccessibilityNodeInfo oldCurrent = current; + current = parent; + oldCurrent.recycle(); + } } + /** + * {@inheritDoc} + */ @Override public void onInterrupt() { - /* do nothing */ + /* do nothing */ } - /** Sets a flag so that the TaskBackService knows that the Text-To-Speech engine has been - * initialized, and can now handle speaking requests. + /** + * {@inheritDoc} */ @Override - public void onInit (int status) { + public void onInit(int status) { + // Set a flag so that the TaskBackService knows that the Text-To-Speech + // engine has been initialized, and can now handle speaking requests. if (status == TextToSpeech.SUCCESS) { mTts.setLanguage(Locale.US); mTextToSpeechInitialized = true; } } + /** + * {@inheritDoc} + */ @Override public void onDestroy() { super.onDestroy(); |
