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

http://eyes-free.googlecode.com/ · Java · 352 lines · 269 code · 42 blank · 41 comment · 29 complexity · f0be6b8e8edbf5299c3b8056550fab62 MD5 · raw file

  1. /*
  2. * Copyright (C) 2008 The Android Open Source Project
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  5. * use this file except in compliance with the License. You may obtain a copy of
  6. * 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, WITHOUT
  12. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  13. * License for the specific language governing permissions and limitations under
  14. * the License.
  15. */
  16. package com.googlecode.eyesfree.inputmethod.latin;
  17. import android.app.AlertDialog;
  18. import android.app.Dialog;
  19. import android.app.backup.BackupManager;
  20. import android.content.DialogInterface;
  21. import android.content.Intent;
  22. import android.content.SharedPreferences;
  23. import android.net.Uri;
  24. import android.os.Build;
  25. import android.os.Bundle;
  26. import android.os.Vibrator;
  27. import android.preference.CheckBoxPreference;
  28. import android.preference.ListPreference;
  29. import android.preference.Preference;
  30. import android.preference.Preference.OnPreferenceClickListener;
  31. import android.preference.PreferenceActivity;
  32. import android.preference.PreferenceGroup;
  33. import android.provider.Settings;
  34. import android.speech.SpeechRecognizer;
  35. import android.text.AutoText;
  36. import android.util.Log;
  37. import com.googlecode.eyesfree.inputmethod.voice.SettingsUtil;
  38. import com.googlecode.eyesfree.inputmethod.voice.VoiceInputLogger;
  39. import com.googlecode.eyesfree.utils.PackageManagerUtils;
  40. import java.lang.reflect.InvocationTargetException;
  41. import java.lang.reflect.Method;
  42. import java.util.ArrayList;
  43. import java.util.Locale;
  44. public class LatinIMESettings extends PreferenceActivity implements
  45. SharedPreferences.OnSharedPreferenceChangeListener, DialogInterface.OnDismissListener {
  46. /** The package that provides the Linear Navigation service. */
  47. public static final String LINEAR_NAVIGATION_PACKAGE =
  48. "com.googlecode.eyesfree.linearnavigation";
  49. /** The URI string for launching the App Market. */
  50. private static final String MARKET_URI = "market://details?id=";
  51. /** Request code for accessibility settings activity. */
  52. private static final int REQUEST_ACCESSIBILITY_SETTINGS = 1;
  53. /** Request code for Market install activity. */
  54. private static final int REQUEST_MARKET_INSTALL = 2;
  55. /** Preference ordering for Linear Navigation setting. */
  56. private static final int LINEAR_NAVIGATION_ORDER = 7;
  57. private static final String VIBRATE_ON_KEY = "vibrate_on";
  58. private static final String QUICK_FIXES_KEY = "quick_fixes";
  59. private static final String PREDICTION_SETTINGS_KEY = "prediction_settings";
  60. private static final String VOICE_SETTINGS_KEY = "voice_mode";
  61. /* package */static final String PREF_DPAD_KEYS = "dpad_keys";
  62. private static final String TAG = "LatinIMESettings";
  63. // Dialog ids
  64. private static final int VOICE_INPUT_CONFIRM_DIALOG = 0;
  65. private CheckBoxPreference mHapticPreference;
  66. private CheckBoxPreference mQuickFixes;
  67. private ListPreference mVoicePreference;
  68. private boolean mVoiceOn;
  69. private Vibrator mVibrator;
  70. private VoiceInputLogger mLogger;
  71. private boolean mOkClicked = false;
  72. private String mVoiceModeOff;
  73. @Override
  74. protected void onCreate(Bundle icicle) {
  75. super.onCreate(icicle);
  76. addPreferencesFromResource(R.xml.prefs);
  77. mHapticPreference = (CheckBoxPreference) findPreference(VIBRATE_ON_KEY);
  78. mQuickFixes = (CheckBoxPreference) findPreference(QUICK_FIXES_KEY);
  79. mVoicePreference = (ListPreference) findPreference(VOICE_SETTINGS_KEY);
  80. SharedPreferences prefs = getPreferenceManager().getSharedPreferences();
  81. prefs.registerOnSharedPreferenceChangeListener(this);
  82. mVoiceModeOff = getString(R.string.voice_mode_off);
  83. mVoiceOn = !(prefs.getString(VOICE_SETTINGS_KEY, mVoiceModeOff).equals(mVoiceModeOff));
  84. mLogger = VoiceInputLogger.getLogger(this);
  85. mVibrator = (Vibrator) getSystemService(VIBRATOR_SERVICE);
  86. updateLinearNavigationPreference();
  87. updateHapticPreferenceVisibility();
  88. }
  89. @Override
  90. protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  91. switch (requestCode) {
  92. case REQUEST_ACCESSIBILITY_SETTINGS:
  93. case REQUEST_MARKET_INSTALL:
  94. updateLinearNavigationPreference();
  95. break;
  96. }
  97. super.onActivityResult(requestCode, resultCode, data);
  98. }
  99. @Override
  100. protected void onResume() {
  101. super.onResume();
  102. int autoTextSize = AutoText.getSize(getListView());
  103. if (autoTextSize < 1) {
  104. ((PreferenceGroup) findPreference(PREDICTION_SETTINGS_KEY))
  105. .removePreference(mQuickFixes);
  106. }
  107. if (!LatinIME.VOICE_INSTALLED || !SpeechRecognizer.isRecognitionAvailable(this)) {
  108. getPreferenceScreen().removePreference(mVoicePreference);
  109. } else {
  110. updateVoiceModeSummary();
  111. }
  112. }
  113. @Override
  114. protected void onDestroy() {
  115. getPreferenceManager().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(
  116. this);
  117. super.onDestroy();
  118. }
  119. /**
  120. * Returns <code>true</code> if this Android build supports
  121. * {@link BackupManager}.
  122. *
  123. * @return <code>true</code> if this Android build supports
  124. * {@link BackupManager}
  125. */
  126. private static boolean supportsBackupManager() {
  127. return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.FROYO);
  128. }
  129. @Override
  130. public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
  131. if (supportsBackupManager()) {
  132. (new BackupManager(this)).dataChanged();
  133. }
  134. // If turning on voice input, show dialog
  135. if (key.equals(VOICE_SETTINGS_KEY) && !mVoiceOn) {
  136. if (!prefs.getString(VOICE_SETTINGS_KEY, mVoiceModeOff).equals(mVoiceModeOff)) {
  137. showVoiceConfirmation();
  138. }
  139. }
  140. mVoiceOn = !(prefs.getString(VOICE_SETTINGS_KEY, mVoiceModeOff).equals(mVoiceModeOff));
  141. updateVoiceModeSummary();
  142. }
  143. private void updateHapticPreferenceVisibility() {
  144. if (Build.VERSION.SDK_INT < 11) {
  145. return;
  146. }
  147. try {
  148. Method hasVibrator = mVibrator.getClass().getMethod("hasVibrator");
  149. Object result = hasVibrator.invoke(mVibrator);
  150. if (result.equals(Boolean.FALSE)) {
  151. getPreferenceScreen().removePreference(mHapticPreference);
  152. }
  153. } catch (SecurityException e) {
  154. e.printStackTrace();
  155. } catch (NoSuchMethodException e) {
  156. e.printStackTrace();
  157. } catch (IllegalArgumentException e) {
  158. e.printStackTrace();
  159. } catch (IllegalAccessException e) {
  160. e.printStackTrace();
  161. } catch (InvocationTargetException e) {
  162. e.printStackTrace();
  163. }
  164. }
  165. /**
  166. * Disables the "Linear navigation" preference, if applicable.
  167. */
  168. private void updateLinearNavigationPreference() {
  169. final Preference existingPreference = findPreference("linear_navigation");
  170. if (existingPreference != null) {
  171. getPreferenceScreen().removePreference(existingPreference);
  172. }
  173. final boolean serviceSupported = Build.VERSION.SDK_INT >= 14;
  174. if (!serviceSupported) {
  175. return;
  176. }
  177. final boolean serviceInstalled =
  178. PackageManagerUtils.hasPackage(this, LINEAR_NAVIGATION_PACKAGE);
  179. if (!serviceInstalled) {
  180. final Preference installPreference = new Preference(this);
  181. installPreference.setKey("linear_navigation");
  182. installPreference.setTitle(R.string.linear_navigation);
  183. installPreference.setSummary(R.string.linear_navigation_missing);
  184. installPreference.setOrder(LINEAR_NAVIGATION_ORDER);
  185. installPreference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
  186. @Override
  187. public boolean onPreferenceClick(Preference preference) {
  188. final Intent intent =
  189. new Intent(Intent.ACTION_VIEW, Uri.parse(MARKET_URI
  190. + LINEAR_NAVIGATION_PACKAGE));
  191. startActivityForResult(intent, REQUEST_ACCESSIBILITY_SETTINGS);
  192. return true;
  193. }
  194. });
  195. getPreferenceScreen().addPreference(installPreference);
  196. return;
  197. }
  198. final String enabledServices =
  199. Settings.Secure.getString(getContentResolver(),
  200. Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
  201. final boolean serviceEnabled =
  202. (enabledServices != null) && enabledServices.contains(LINEAR_NAVIGATION_PACKAGE);
  203. if (!serviceEnabled) {
  204. final Preference enablePreference = new Preference(this);
  205. enablePreference.setKey("linear_navigation");
  206. enablePreference.setTitle(R.string.linear_navigation);
  207. enablePreference.setSummary(R.string.linear_navigation_disabled);
  208. enablePreference.setOrder(LINEAR_NAVIGATION_ORDER);
  209. enablePreference.setOnPreferenceClickListener(new OnPreferenceClickListener() {
  210. @Override
  211. public boolean onPreferenceClick(Preference preference) {
  212. final Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
  213. startActivityForResult(intent, REQUEST_ACCESSIBILITY_SETTINGS);
  214. return true;
  215. }
  216. });
  217. getPreferenceScreen().addPreference(enablePreference);
  218. return;
  219. }
  220. final CheckBoxPreference defaultPreference = new CheckBoxPreference(this);
  221. defaultPreference.setKey("linear_navigation");
  222. defaultPreference.setTitle(R.string.linear_navigation);
  223. defaultPreference.setSummary(R.string.linear_navigation_summary);
  224. defaultPreference.setOrder(LINEAR_NAVIGATION_ORDER);
  225. getPreferenceScreen().addPreference(defaultPreference);
  226. }
  227. private void showVoiceConfirmation() {
  228. mOkClicked = false;
  229. showDialog(VOICE_INPUT_CONFIRM_DIALOG);
  230. }
  231. private void updateVoiceModeSummary() {
  232. mVoicePreference.setSummary(getResources()
  233. .getStringArray(R.array.voice_input_modes_summary)[mVoicePreference
  234. .findIndexOfValue(mVoicePreference.getValue())]);
  235. }
  236. @Override
  237. protected Dialog onCreateDialog(int id) {
  238. switch (id) {
  239. case VOICE_INPUT_CONFIRM_DIALOG:
  240. DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
  241. @Override
  242. public void onClick(DialogInterface dialog, int whichButton) {
  243. if (whichButton == DialogInterface.BUTTON_NEGATIVE) {
  244. mVoicePreference.setValue(mVoiceModeOff);
  245. mLogger.settingsWarningDialogCancel();
  246. } else if (whichButton == DialogInterface.BUTTON_POSITIVE) {
  247. mOkClicked = true;
  248. mLogger.settingsWarningDialogOk();
  249. }
  250. updateVoicePreference();
  251. }
  252. };
  253. AlertDialog.Builder builder =
  254. new AlertDialog.Builder(this).setTitle(R.string.voice_warning_title)
  255. .setPositiveButton(android.R.string.ok, listener)
  256. .setNegativeButton(android.R.string.cancel, listener);
  257. // Get the current list of supported locales and check the
  258. // current locale against
  259. // that list, to decide whether to put a warning that voice
  260. // input will not work in
  261. // the current language as part of the pop-up confirmation
  262. // dialog.
  263. String supportedLocalesString =
  264. SettingsUtil.getSettingsString(getContentResolver(),
  265. SettingsUtil.LATIN_IME_VOICE_INPUT_SUPPORTED_LOCALES,
  266. LatinIME.DEFAULT_VOICE_INPUT_SUPPORTED_LOCALES);
  267. ArrayList<String> voiceInputSupportedLocales =
  268. LatinIME.newArrayList(supportedLocalesString.split("\\s+"));
  269. boolean localeSupported =
  270. voiceInputSupportedLocales.contains(Locale.getDefault().toString());
  271. if (localeSupported) {
  272. String message =
  273. getString(R.string.voice_warning_may_not_understand) + "\n\n"
  274. + getString(R.string.voice_hint_dialog_message);
  275. builder.setMessage(message);
  276. } else {
  277. String message =
  278. getString(R.string.voice_warning_locale_not_supported) + "\n\n"
  279. + getString(R.string.voice_warning_may_not_understand) + "\n\n"
  280. + getString(R.string.voice_hint_dialog_message);
  281. builder.setMessage(message);
  282. }
  283. AlertDialog dialog = builder.create();
  284. dialog.setOnDismissListener(this);
  285. mLogger.settingsWarningDialogShown();
  286. return dialog;
  287. default:
  288. Log.e(TAG, "unknown dialog " + id);
  289. return null;
  290. }
  291. }
  292. @Override
  293. public void onDismiss(DialogInterface dialog) {
  294. mLogger.settingsWarningDialogDismissed();
  295. if (!mOkClicked) {
  296. // This assumes that onPreferenceClick gets called first, and this
  297. // if the user
  298. // agreed after the warning, we set the mOkClicked value to true.
  299. mVoicePreference.setValue(mVoiceModeOff);
  300. }
  301. }
  302. private void updateVoicePreference() {
  303. boolean isChecked = !mVoicePreference.getValue().equals(mVoiceModeOff);
  304. if (isChecked) {
  305. mLogger.voiceInputSettingEnabled();
  306. } else {
  307. mLogger.voiceInputSettingDisabled();
  308. }
  309. }
  310. }