1 /* 2 * Copyright (C) 2008 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 17 package com.android.settings.inputmethod; 18 19 import com.android.settings.R; 20 import com.android.settings.Settings.KeyboardLayoutPickerActivity; 21 import com.android.settings.Settings.SpellCheckersSettingsActivity; 22 import com.android.settings.SettingsPreferenceFragment; 23 import com.android.settings.UserDictionarySettings; 24 import com.android.settings.Utils; 25 import com.android.settings.VoiceInputOutputSettings; 26 27 import android.app.Activity; 28 import android.app.Fragment; 29 import android.content.ContentResolver; 30 import android.content.Context; 31 import android.content.Intent; 32 import android.content.pm.PackageManager; 33 import android.content.res.Configuration; 34 import android.content.res.Resources; 35 import android.database.ContentObserver; 36 import android.hardware.input.InputManager; 37 import android.hardware.input.KeyboardLayout; 38 import android.os.Bundle; 39 import android.os.Handler; 40 import android.preference.CheckBoxPreference; 41 import android.preference.ListPreference; 42 import android.preference.Preference; 43 import android.preference.Preference.OnPreferenceChangeListener; 44 import android.preference.Preference.OnPreferenceClickListener; 45 import android.preference.PreferenceCategory; 46 import android.preference.PreferenceScreen; 47 import android.provider.Settings; 48 import android.provider.Settings.System; 49 import android.text.TextUtils; 50 import android.view.InputDevice; 51 import android.view.inputmethod.InputMethodInfo; 52 import android.view.inputmethod.InputMethodManager; 53 import android.widget.BaseAdapter; 54 55 import java.util.ArrayList; 56 import java.util.Collections; 57 import java.util.List; 58 import java.util.TreeSet; 59 60 public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment 61 implements Preference.OnPreferenceChangeListener, InputManager.InputDeviceListener, 62 KeyboardLayoutDialogFragment.OnSetupKeyboardLayoutsListener { 63 64 private static final String KEY_PHONE_LANGUAGE = "phone_language"; 65 private static final String KEY_CURRENT_INPUT_METHOD = "current_input_method"; 66 private static final String KEY_INPUT_METHOD_SELECTOR = "input_method_selector"; 67 private static final String KEY_USER_DICTIONARY_SETTINGS = "key_user_dictionary_settings"; 68 // false: on ICS or later 69 private static final boolean SHOW_INPUT_METHOD_SWITCHER_SETTINGS = false; 70 71 private static final String[] sSystemSettingNames = { 72 System.TEXT_AUTO_REPLACE, System.TEXT_AUTO_CAPS, System.TEXT_AUTO_PUNCTUATE, 73 }; 74 75 private static final String[] sHardKeyboardKeys = { 76 "auto_replace", "auto_caps", "auto_punctuate", 77 }; 78 79 private int mDefaultInputMethodSelectorVisibility = 0; 80 private ListPreference mShowInputMethodSelectorPref; 81 private PreferenceCategory mKeyboardSettingsCategory; 82 private PreferenceCategory mHardKeyboardCategory; 83 private PreferenceCategory mGameControllerCategory; 84 private Preference mLanguagePref; 85 private final ArrayList<InputMethodPreference> mInputMethodPreferenceList = 86 new ArrayList<InputMethodPreference>(); 87 private final ArrayList<PreferenceScreen> mHardKeyboardPreferenceList = 88 new ArrayList<PreferenceScreen>(); 89 private InputManager mIm; 90 private InputMethodManager mImm; 91 private boolean mIsOnlyImeSettings; 92 private Handler mHandler; 93 private SettingsObserver mSettingsObserver; 94 private Intent mIntentWaitingForResult; 95 private InputMethodSettingValuesWrapper mInputMethodSettingValues; 96 97 private final OnPreferenceChangeListener mOnImePreferenceChangedListener = 98 new OnPreferenceChangeListener() { 99 @Override 100 public boolean onPreferenceChange(Preference arg0, Object arg1) { 101 InputMethodSettingValuesWrapper.getInstance( 102 arg0.getContext()).refreshAllInputMethodAndSubtypes(); 103 ((BaseAdapter)getPreferenceScreen().getRootAdapter()).notifyDataSetChanged(); 104 updateInputMethodPreferenceViews(); 105 return true; 106 } 107 }; 108 109 @Override 110 public void onCreate(Bundle icicle) { 111 super.onCreate(icicle); 112 113 addPreferencesFromResource(R.xml.language_settings); 114 115 try { 116 mDefaultInputMethodSelectorVisibility = Integer.valueOf( 117 getString(R.string.input_method_selector_visibility_default_value)); 118 } catch (NumberFormatException e) { 119 } 120 121 if (getActivity().getAssets().getLocales().length == 1) { 122 // No "Select language" pref if there's only one system locale available. 123 getPreferenceScreen().removePreference(findPreference(KEY_PHONE_LANGUAGE)); 124 } else { 125 mLanguagePref = findPreference(KEY_PHONE_LANGUAGE); 126 } 127 if (SHOW_INPUT_METHOD_SWITCHER_SETTINGS) { 128 mShowInputMethodSelectorPref = (ListPreference)findPreference( 129 KEY_INPUT_METHOD_SELECTOR); 130 mShowInputMethodSelectorPref.setOnPreferenceChangeListener(this); 131 // TODO: Update current input method name on summary 132 updateInputMethodSelectorSummary(loadInputMethodSelectorVisibility()); 133 } 134 135 new VoiceInputOutputSettings(this).onCreate(); 136 137 // Get references to dynamically constructed categories. 138 mHardKeyboardCategory = (PreferenceCategory)findPreference("hard_keyboard"); 139 mKeyboardSettingsCategory = (PreferenceCategory)findPreference( 140 "keyboard_settings_category"); 141 mGameControllerCategory = (PreferenceCategory)findPreference( 142 "game_controller_settings_category"); 143 144 // Filter out irrelevant features if invoked from IME settings button. 145 mIsOnlyImeSettings = Settings.ACTION_INPUT_METHOD_SETTINGS.equals( 146 getActivity().getIntent().getAction()); 147 getActivity().getIntent().setAction(null); 148 if (mIsOnlyImeSettings) { 149 getPreferenceScreen().removeAll(); 150 getPreferenceScreen().addPreference(mHardKeyboardCategory); 151 if (SHOW_INPUT_METHOD_SWITCHER_SETTINGS) { 152 getPreferenceScreen().addPreference(mShowInputMethodSelectorPref); 153 } 154 getPreferenceScreen().addPreference(mKeyboardSettingsCategory); 155 } 156 157 // Build IME preference category. 158 mImm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); 159 mInputMethodSettingValues = InputMethodSettingValuesWrapper.getInstance(getActivity()); 160 161 mKeyboardSettingsCategory.removeAll(); 162 if (!mIsOnlyImeSettings) { 163 final PreferenceScreen currentIme = new PreferenceScreen(getActivity(), null); 164 currentIme.setKey(KEY_CURRENT_INPUT_METHOD); 165 currentIme.setTitle(getResources().getString(R.string.current_input_method)); 166 mKeyboardSettingsCategory.addPreference(currentIme); 167 } 168 169 // Build hard keyboard and game controller preference categories. 170 mIm = (InputManager)getActivity().getSystemService(Context.INPUT_SERVICE); 171 updateInputDevices(); 172 173 // Spell Checker 174 final Intent intent = new Intent(Intent.ACTION_MAIN); 175 intent.setClass(getActivity(), SpellCheckersSettingsActivity.class); 176 final SpellCheckersPreference scp = ((SpellCheckersPreference)findPreference( 177 "spellcheckers_settings")); 178 if (scp != null) { 179 scp.setFragmentIntent(this, intent); 180 } 181 182 mHandler = new Handler(); 183 mSettingsObserver = new SettingsObserver(mHandler, getActivity()); 184 } 185 186 private void updateInputMethodSelectorSummary(int value) { 187 String[] inputMethodSelectorTitles = getResources().getStringArray( 188 R.array.input_method_selector_titles); 189 if (inputMethodSelectorTitles.length > value) { 190 mShowInputMethodSelectorPref.setSummary(inputMethodSelectorTitles[value]); 191 mShowInputMethodSelectorPref.setValue(String.valueOf(value)); 192 } 193 } 194 195 private void updateUserDictionaryPreference(Preference userDictionaryPreference) { 196 final Activity activity = getActivity(); 197 final TreeSet<String> localeSet = UserDictionaryList.getUserDictionaryLocalesSet(activity); 198 if (null == localeSet) { 199 // The locale list is null if and only if the user dictionary service is 200 // not present or disabled. In this case we need to remove the preference. 201 getPreferenceScreen().removePreference(userDictionaryPreference); 202 } else { 203 userDictionaryPreference.setOnPreferenceClickListener( 204 new OnPreferenceClickListener() { 205 @Override 206 public boolean onPreferenceClick(Preference arg0) { 207 // Redirect to UserDictionarySettings if the user needs only one 208 // language. 209 final Bundle extras = new Bundle(); 210 final Class<? extends Fragment> targetFragment; 211 if (localeSet.size() <= 1) { 212 if (!localeSet.isEmpty()) { 213 // If the size of localeList is 0, we don't set the locale 214 // parameter in the extras. This will be interpreted by the 215 // UserDictionarySettings class as meaning 216 // "the current locale". Note that with the current code for 217 // UserDictionaryList#getUserDictionaryLocalesSet() 218 // the locale list always has at least one element, since it 219 // always includes the current locale explicitly. 220 // @see UserDictionaryList.getUserDictionaryLocalesSet(). 221 extras.putString("locale", localeSet.first()); 222 } 223 targetFragment = UserDictionarySettings.class; 224 } else { 225 targetFragment = UserDictionaryList.class; 226 } 227 startFragment(InputMethodAndLanguageSettings.this, 228 targetFragment.getCanonicalName(), -1, extras); 229 return true; 230 } 231 }); 232 } 233 } 234 235 @Override 236 public void onResume() { 237 super.onResume(); 238 239 mSettingsObserver.resume(); 240 mIm.registerInputDeviceListener(this, null); 241 242 if (!mIsOnlyImeSettings) { 243 if (mLanguagePref != null) { 244 Configuration conf = getResources().getConfiguration(); 245 String language = conf.locale.getLanguage(); 246 String localeString; 247 // TODO: This is not an accurate way to display the locale, as it is 248 // just working around the fact that we support limited dialects 249 // and want to pretend that the language is valid for all locales. 250 // We need a way to support languages that aren't tied to a particular 251 // locale instead of hiding the locale qualifier. 252 if (language.equals("zz")) { 253 String country = conf.locale.getCountry(); 254 if (country.equals("ZZ")) { 255 localeString = "[Developer] Accented English (zz_ZZ)"; 256 } else if (country.equals("ZY")) { 257 localeString = "[Developer] Fake Bi-Directional (zz_ZY)"; 258 } else { 259 localeString = ""; 260 } 261 } else if (hasOnlyOneLanguageInstance(language, 262 Resources.getSystem().getAssets().getLocales())) { 263 localeString = conf.locale.getDisplayLanguage(conf.locale); 264 } else { 265 localeString = conf.locale.getDisplayName(conf.locale); 266 } 267 if (localeString.length() > 1) { 268 localeString = Character.toUpperCase(localeString.charAt(0)) 269 + localeString.substring(1); 270 mLanguagePref.setSummary(localeString); 271 } 272 } 273 274 updateUserDictionaryPreference(findPreference(KEY_USER_DICTIONARY_SETTINGS)); 275 if (SHOW_INPUT_METHOD_SWITCHER_SETTINGS) { 276 mShowInputMethodSelectorPref.setOnPreferenceChangeListener(this); 277 } 278 } 279 280 // Hard keyboard 281 if (!mHardKeyboardPreferenceList.isEmpty()) { 282 for (int i = 0; i < sHardKeyboardKeys.length; ++i) { 283 CheckBoxPreference chkPref = (CheckBoxPreference) 284 mHardKeyboardCategory.findPreference(sHardKeyboardKeys[i]); 285 chkPref.setChecked( 286 System.getInt(getContentResolver(), sSystemSettingNames[i], 1) > 0); 287 } 288 } 289 290 updateInputDevices(); 291 292 // Refresh internal states in mInputMethodSettingValues to keep the latest 293 // "InputMethodInfo"s and "InputMethodSubtype"s 294 mInputMethodSettingValues.refreshAllInputMethodAndSubtypes(); 295 updateInputMethodPreferenceViews(); 296 } 297 298 @Override 299 public void onPause() { 300 super.onPause(); 301 302 mIm.unregisterInputDeviceListener(this); 303 mSettingsObserver.pause(); 304 305 if (SHOW_INPUT_METHOD_SWITCHER_SETTINGS) { 306 mShowInputMethodSelectorPref.setOnPreferenceChangeListener(null); 307 } 308 // TODO: Consolidate the logic to InputMethodSettingsWrapper 309 InputMethodAndSubtypeUtil.saveInputMethodSubtypeList( 310 this, getContentResolver(), mInputMethodSettingValues.getInputMethodList(), 311 !mHardKeyboardPreferenceList.isEmpty()); 312 } 313 314 @Override 315 public void onInputDeviceAdded(int deviceId) { 316 updateInputDevices(); 317 } 318 319 @Override 320 public void onInputDeviceChanged(int deviceId) { 321 updateInputDevices(); 322 } 323 324 @Override 325 public void onInputDeviceRemoved(int deviceId) { 326 updateInputDevices(); 327 } 328 329 @Override 330 public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { 331 // Input Method stuff 332 if (Utils.isMonkeyRunning()) { 333 return false; 334 } 335 if (preference instanceof PreferenceScreen) { 336 if (preference.getFragment() != null) { 337 // Fragment will be handled correctly by the super class. 338 } else if (KEY_CURRENT_INPUT_METHOD.equals(preference.getKey())) { 339 final InputMethodManager imm = (InputMethodManager) 340 getSystemService(Context.INPUT_METHOD_SERVICE); 341 imm.showInputMethodPicker(); 342 } 343 } else if (preference instanceof CheckBoxPreference) { 344 final CheckBoxPreference chkPref = (CheckBoxPreference) preference; 345 if (!mHardKeyboardPreferenceList.isEmpty()) { 346 for (int i = 0; i < sHardKeyboardKeys.length; ++i) { 347 if (chkPref == mHardKeyboardCategory.findPreference(sHardKeyboardKeys[i])) { 348 System.putInt(getContentResolver(), sSystemSettingNames[i], 349 chkPref.isChecked() ? 1 : 0); 350 return true; 351 } 352 } 353 } 354 if (chkPref == mGameControllerCategory.findPreference("vibrate_input_devices")) { 355 System.putInt(getContentResolver(), Settings.System.VIBRATE_INPUT_DEVICES, 356 chkPref.isChecked() ? 1 : 0); 357 return true; 358 } 359 } 360 return super.onPreferenceTreeClick(preferenceScreen, preference); 361 } 362 363 private boolean hasOnlyOneLanguageInstance(String languageCode, String[] locales) { 364 int count = 0; 365 for (String localeCode : locales) { 366 if (localeCode.length() > 2 367 && localeCode.startsWith(languageCode)) { 368 count++; 369 if (count > 1) { 370 return false; 371 } 372 } 373 } 374 return count == 1; 375 } 376 377 private void saveInputMethodSelectorVisibility(String value) { 378 try { 379 int intValue = Integer.valueOf(value); 380 Settings.Secure.putInt(getContentResolver(), 381 Settings.Secure.INPUT_METHOD_SELECTOR_VISIBILITY, intValue); 382 updateInputMethodSelectorSummary(intValue); 383 } catch(NumberFormatException e) { 384 } 385 } 386 387 private int loadInputMethodSelectorVisibility() { 388 return Settings.Secure.getInt(getContentResolver(), 389 Settings.Secure.INPUT_METHOD_SELECTOR_VISIBILITY, 390 mDefaultInputMethodSelectorVisibility); 391 } 392 393 @Override 394 public boolean onPreferenceChange(Preference preference, Object value) { 395 if (SHOW_INPUT_METHOD_SWITCHER_SETTINGS) { 396 if (preference == mShowInputMethodSelectorPref) { 397 if (value instanceof String) { 398 saveInputMethodSelectorVisibility((String)value); 399 } 400 } 401 } 402 return false; 403 } 404 405 private void updateInputMethodPreferenceViews() { 406 synchronized (mInputMethodPreferenceList) { 407 // Clear existing "InputMethodPreference"s 408 for (final InputMethodPreference imp : mInputMethodPreferenceList) { 409 mKeyboardSettingsCategory.removePreference(imp); 410 } 411 mInputMethodPreferenceList.clear(); 412 final List<InputMethodInfo> imis = mInputMethodSettingValues.getInputMethodList(); 413 final int N = (imis == null ? 0 : imis.size()); 414 for (int i = 0; i < N; ++i) { 415 final InputMethodInfo imi = imis.get(i); 416 final InputMethodPreference pref = getInputMethodPreference(imi); 417 pref.setOnImePreferenceChangeListener(mOnImePreferenceChangedListener); 418 mInputMethodPreferenceList.add(pref); 419 } 420 421 if (!mInputMethodPreferenceList.isEmpty()) { 422 Collections.sort(mInputMethodPreferenceList); 423 for (int i = 0; i < N; ++i) { 424 mKeyboardSettingsCategory.addPreference(mInputMethodPreferenceList.get(i)); 425 } 426 } 427 428 // update views status 429 for (Preference pref : mInputMethodPreferenceList) { 430 if (pref instanceof InputMethodPreference) { 431 ((InputMethodPreference) pref).updatePreferenceViews(); 432 } 433 } 434 } 435 updateCurrentImeName(); 436 // TODO: Consolidate the logic with InputMethodSettingsWrapper 437 // CAVEAT: The preference class here does not know about the default value - that is 438 // managed by the Input Method Manager Service, so in this case it could save the wrong 439 // value. Hence we must update the checkboxes here. 440 InputMethodAndSubtypeUtil.loadInputMethodSubtypeList( 441 this, getContentResolver(), 442 mInputMethodSettingValues.getInputMethodList(), null); 443 } 444 445 private void updateCurrentImeName() { 446 final Context context = getActivity(); 447 if (context == null || mImm == null) return; 448 final Preference curPref = getPreferenceScreen().findPreference(KEY_CURRENT_INPUT_METHOD); 449 if (curPref != null) { 450 final CharSequence curIme = 451 mInputMethodSettingValues.getCurrentInputMethodName(context); 452 if (!TextUtils.isEmpty(curIme)) { 453 synchronized(this) { 454 curPref.setSummary(curIme); 455 } 456 } 457 } 458 } 459 460 private InputMethodPreference getInputMethodPreference(InputMethodInfo imi) { 461 final PackageManager pm = getPackageManager(); 462 final CharSequence label = imi.loadLabel(pm); 463 // IME settings 464 final Intent intent; 465 final String settingsActivity = imi.getSettingsActivity(); 466 if (!TextUtils.isEmpty(settingsActivity)) { 467 intent = new Intent(Intent.ACTION_MAIN); 468 intent.setClassName(imi.getPackageName(), settingsActivity); 469 } else { 470 intent = null; 471 } 472 473 // Add a check box for enabling/disabling IME 474 final InputMethodPreference pref = 475 new InputMethodPreference(this, intent, mImm, imi); 476 pref.setKey(imi.getId()); 477 pref.setTitle(label); 478 return pref; 479 } 480 481 private void updateInputDevices() { 482 updateHardKeyboards(); 483 updateGameControllers(); 484 } 485 486 private void updateHardKeyboards() { 487 mHardKeyboardPreferenceList.clear(); 488 if (getResources().getConfiguration().keyboard == Configuration.KEYBOARD_QWERTY) { 489 final int[] devices = InputDevice.getDeviceIds(); 490 for (int i = 0; i < devices.length; i++) { 491 InputDevice device = InputDevice.getDevice(devices[i]); 492 if (device != null 493 && !device.isVirtual() 494 && device.isFullKeyboard()) { 495 final String inputDeviceDescriptor = device.getDescriptor(); 496 final String keyboardLayoutDescriptor = 497 mIm.getCurrentKeyboardLayoutForInputDevice(inputDeviceDescriptor); 498 final KeyboardLayout keyboardLayout = keyboardLayoutDescriptor != null ? 499 mIm.getKeyboardLayout(keyboardLayoutDescriptor) : null; 500 501 final PreferenceScreen pref = new PreferenceScreen(getActivity(), null); 502 pref.setTitle(device.getName()); 503 if (keyboardLayout != null) { 504 pref.setSummary(keyboardLayout.toString()); 505 } else { 506 pref.setSummary(R.string.keyboard_layout_default_label); 507 } 508 pref.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { 509 @Override 510 public boolean onPreferenceClick(Preference preference) { 511 showKeyboardLayoutDialog(inputDeviceDescriptor); 512 return true; 513 } 514 }); 515 mHardKeyboardPreferenceList.add(pref); 516 } 517 } 518 } 519 520 if (!mHardKeyboardPreferenceList.isEmpty()) { 521 for (int i = mHardKeyboardCategory.getPreferenceCount(); i-- > 0; ) { 522 final Preference pref = mHardKeyboardCategory.getPreference(i); 523 if (pref.getOrder() < 1000) { 524 mHardKeyboardCategory.removePreference(pref); 525 } 526 } 527 528 Collections.sort(mHardKeyboardPreferenceList); 529 final int count = mHardKeyboardPreferenceList.size(); 530 for (int i = 0; i < count; i++) { 531 final Preference pref = mHardKeyboardPreferenceList.get(i); 532 pref.setOrder(i); 533 mHardKeyboardCategory.addPreference(pref); 534 } 535 536 getPreferenceScreen().addPreference(mHardKeyboardCategory); 537 } else { 538 getPreferenceScreen().removePreference(mHardKeyboardCategory); 539 } 540 } 541 542 private void showKeyboardLayoutDialog(String inputDeviceDescriptor) { 543 KeyboardLayoutDialogFragment fragment = 544 new KeyboardLayoutDialogFragment(inputDeviceDescriptor); 545 fragment.setTargetFragment(this, 0); 546 fragment.show(getActivity().getFragmentManager(), "keyboardLayout"); 547 } 548 549 @Override 550 public void onSetupKeyboardLayouts(String inputDeviceDescriptor) { 551 final Intent intent = new Intent(Intent.ACTION_MAIN); 552 intent.setClass(getActivity(), KeyboardLayoutPickerActivity.class); 553 intent.putExtra(KeyboardLayoutPickerFragment.EXTRA_INPUT_DEVICE_DESCRIPTOR, 554 inputDeviceDescriptor); 555 mIntentWaitingForResult = intent; 556 startActivityForResult(intent, 0); 557 } 558 559 @Override 560 public void onActivityResult(int requestCode, int resultCode, Intent data) { 561 super.onActivityResult(requestCode, resultCode, data); 562 563 if (mIntentWaitingForResult != null) { 564 String inputDeviceDescriptor = mIntentWaitingForResult.getStringExtra( 565 KeyboardLayoutPickerFragment.EXTRA_INPUT_DEVICE_DESCRIPTOR); 566 mIntentWaitingForResult = null; 567 showKeyboardLayoutDialog(inputDeviceDescriptor); 568 } 569 } 570 571 private void updateGameControllers() { 572 if (haveInputDeviceWithVibrator()) { 573 getPreferenceScreen().addPreference(mGameControllerCategory); 574 575 CheckBoxPreference chkPref = (CheckBoxPreference) 576 mGameControllerCategory.findPreference("vibrate_input_devices"); 577 chkPref.setChecked(System.getInt(getContentResolver(), 578 Settings.System.VIBRATE_INPUT_DEVICES, 1) > 0); 579 } else { 580 getPreferenceScreen().removePreference(mGameControllerCategory); 581 } 582 } 583 584 private boolean haveInputDeviceWithVibrator() { 585 final int[] devices = InputDevice.getDeviceIds(); 586 for (int i = 0; i < devices.length; i++) { 587 InputDevice device = InputDevice.getDevice(devices[i]); 588 if (device != null && !device.isVirtual() && device.getVibrator().hasVibrator()) { 589 return true; 590 } 591 } 592 return false; 593 } 594 595 private class SettingsObserver extends ContentObserver { 596 private Context mContext; 597 598 public SettingsObserver(Handler handler, Context context) { 599 super(handler); 600 mContext = context; 601 } 602 603 @Override public void onChange(boolean selfChange) { 604 updateCurrentImeName(); 605 } 606 607 public void resume() { 608 final ContentResolver cr = mContext.getContentResolver(); 609 cr.registerContentObserver( 610 Settings.Secure.getUriFor(Settings.Secure.DEFAULT_INPUT_METHOD), false, this); 611 cr.registerContentObserver(Settings.Secure.getUriFor( 612 Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE), false, this); 613 } 614 615 public void pause() { 616 mContext.getContentResolver().unregisterContentObserver(this); 617 } 618 } 619 } 620