/ime/latinime/src/com/googlecode/eyesfree/inputmethod/latin/AccessibilityUtils.java

http://eyes-free.googlecode.com/ · Java · 198 lines · 131 code · 21 blank · 46 comment · 25 complexity · aceb7dcfef8b88e15c37ad4342c177e5 MD5 · raw file

  1. /*
  2. * Copyright (C) 2011 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package com.googlecode.eyesfree.inputmethod.latin;
  17. import android.content.Context;
  18. import android.content.res.Resources;
  19. import android.inputmethodservice.Keyboard;
  20. import android.inputmethodservice.Keyboard.Key;
  21. import android.os.SystemClock;
  22. import android.provider.Settings;
  23. import android.view.accessibility.AccessibilityEvent;
  24. import android.view.accessibility.AccessibilityManager;
  25. import com.googlecode.eyesfree.inputmethod.KeyCodeDescriptionMapper;
  26. /**
  27. * Utility functions for accessibility support.
  28. */
  29. public class AccessibilityUtils {
  30. private final Context mContext;
  31. private final AccessibilityManager mAccessibilityManager;
  32. private final KeyCodeDescriptionMapper mKeyCodeMapper;
  33. public AccessibilityUtils(Context context) {
  34. mContext = context;
  35. mAccessibilityManager = (AccessibilityManager) context
  36. .getSystemService(Context.ACCESSIBILITY_SERVICE);
  37. mKeyCodeMapper = KeyCodeDescriptionMapper.getInstance(context);
  38. }
  39. /**
  40. * Returns true if accessibility is enabled.
  41. *
  42. * @return true is accessibility is enabled.
  43. */
  44. public boolean isAccessibilityEnabled() {
  45. return mAccessibilityManager.isEnabled();
  46. }
  47. /**
  48. * Speaks a key's action after it has been released. Does not speak letter
  49. * keys since typed keys are already spoken aloud by TalkBack.
  50. *
  51. * @param key The primary code of the released key.
  52. * @param switcher The input method's {@link KeyboardSwitcher}.
  53. */
  54. public void onRelease(Key key, KeyboardSwitcher switcher) {
  55. if (!mAccessibilityManager.isEnabled()) {
  56. return;
  57. }
  58. final int primaryCode = key.codes[0];
  59. int resId = -1;
  60. switch (primaryCode) {
  61. case Keyboard.KEYCODE_SHIFT: {
  62. if (switcher.isAlphabetMode()) {
  63. if (switcher.isShiftedOrShiftLocked()) {
  64. if (switcher.isShiftLocked()) {
  65. resId = R.string.spoken_description_shift_locked;
  66. } else {
  67. resId = R.string.spoken_description_shift_on;
  68. }
  69. } else {
  70. resId = R.string.spoken_description_shift_off;
  71. }
  72. } else {
  73. if (switcher.isShiftedOrShiftLocked()) {
  74. resId = R.string.spoken_description_alt_on;
  75. } else {
  76. resId = R.string.spoken_description_alt_off;
  77. }
  78. }
  79. break;
  80. }
  81. case Keyboard.KEYCODE_MODE_CHANGE: {
  82. if (switcher.isAlphabetMode()) {
  83. resId = R.string.spoken_description_symbols_off;
  84. } else {
  85. resId = R.string.spoken_description_symbols_on;
  86. }
  87. break;
  88. }
  89. case LatinKeyboardView.KEYCODE_BACK:
  90. resId = R.string.spoken_description_back;
  91. break;
  92. case LatinKeyboardView.KEYCODE_HOME:
  93. resId = R.string.spoken_description_home;
  94. break;
  95. case LatinKeyboardView.KEYCODE_SEARCH:
  96. resId = R.string.spoken_description_search;
  97. break;
  98. case LatinKeyboardView.KEYCODE_MENU:
  99. resId = R.string.spoken_description_menu;
  100. break;
  101. case LatinKeyboardView.KEYCODE_CALL:
  102. resId = R.string.spoken_description_call;
  103. break;
  104. case LatinKeyboardView.KEYCODE_ENDCALL:
  105. resId = R.string.spoken_description_end_call;
  106. break;
  107. }
  108. if (resId >= 0) {
  109. speakDescription(mContext.getResources().getText(resId));
  110. }
  111. }
  112. /**
  113. * Speak key description for accessibility. If a key has an explicit
  114. * description defined in keycodes.xml, that will be used. Otherwise, if the
  115. * key is a Unicode character, then its character will be used.
  116. *
  117. * @param res The resources for the current context.
  118. * @param key The primary code of the pressed key.
  119. * @param switcher The input method's {@link KeyboardSwitcher}.
  120. */
  121. public void onPress(Resources res, KeyboardSwitcher switcher, Key key) {
  122. if (!mAccessibilityManager.isEnabled()) {
  123. return;
  124. }
  125. final CharSequence description = mKeyCodeMapper.getDescriptionForKey(res, switcher, key);
  126. if (description != null) {
  127. speakDescription(description);
  128. }
  129. }
  130. /**
  131. * Sends a character sequence to be read aloud.
  132. *
  133. * @param description The {@link CharSequence} to be read aloud.
  134. */
  135. public void speakDescription(CharSequence description) {
  136. if (!mAccessibilityManager.isEnabled()) {
  137. return;
  138. }
  139. // TODO Contact Loquendo so we can remove this workaround.
  140. if (Character.isLetterOrDigit(description.charAt(0))) {
  141. description = description + ".";
  142. }
  143. // TODO We need to add an AccessibilityEvent type for IMEs.
  144. AccessibilityEvent event = AccessibilityEvent
  145. .obtain(AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED);
  146. event.setPackageName(mContext.getPackageName());
  147. event.setClassName(getClass().getName());
  148. event.setEventTime(SystemClock.uptimeMillis());
  149. event.setBeforeText("");
  150. event.setAddedCount(description.length());
  151. event.setRemovedCount(0);
  152. event.setFromIndex(0);
  153. event.getText().add(description);
  154. mAccessibilityManager.sendAccessibilityEvent(event);
  155. }
  156. public static boolean isAccessibilityEnabled(Context context) {
  157. final int accessibilityEnabled = Settings.Secure.getInt(context.getContentResolver(),
  158. Settings.Secure.ACCESSIBILITY_ENABLED, 0);
  159. return accessibilityEnabled == 1;
  160. }
  161. public static boolean isInputMethodEnabled(Context context, Class<?> imeClass) {
  162. final String targetImePackage = imeClass.getPackage().getName();
  163. final String targetImeClass = imeClass.getSimpleName();
  164. final String enabledImeIds = Settings.Secure.getString(context.getContentResolver(),
  165. Settings.Secure.ENABLED_INPUT_METHODS);
  166. return enabledImeIds != null && enabledImeIds.contains(targetImePackage)
  167. && enabledImeIds.contains(targetImeClass);
  168. }
  169. public static boolean isInputMethodDefault(Context context, Class<?> imeClass) {
  170. final String targetImePackage = imeClass.getPackage().getName();
  171. final String targetImeClass = imeClass.getSimpleName();
  172. final String defaultImeId = Settings.Secure.getString(context.getContentResolver(),
  173. Settings.Secure.DEFAULT_INPUT_METHOD);
  174. return defaultImeId != null && defaultImeId.contains(targetImePackage)
  175. && defaultImeId.contains(targetImeClass);
  176. }
  177. }