SettingsFragment.java revision 00b49cad9cc8a350bde8210d50c4b638908ef1c4
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 17package com.android.inputmethod.latin.settings; 18 19import android.app.Activity; 20import android.app.backup.BackupManager; 21import android.content.Context; 22import android.content.Intent; 23import android.content.SharedPreferences; 24import android.content.res.Resources; 25import android.media.AudioManager; 26import android.os.Bundle; 27import android.preference.ListPreference; 28import android.preference.Preference; 29import android.preference.PreferenceGroup; 30import android.preference.PreferenceScreen; 31import android.preference.TwoStatePreference; 32import android.util.Log; 33import android.view.Menu; 34import android.view.MenuInflater; 35import android.view.MenuItem; 36 37import com.android.inputmethod.keyboard.KeyboardTheme; 38import com.android.inputmethod.latin.AudioAndHapticFeedbackManager; 39import com.android.inputmethod.latin.R; 40import com.android.inputmethod.latin.define.ProductionFlags; 41import com.android.inputmethod.latin.setup.LauncherIconVisibilityManager; 42import com.android.inputmethod.latin.utils.ApplicationUtils; 43import com.android.inputmethod.latin.utils.FeedbackUtils; 44import com.android.inputmethodcommon.InputMethodSettingsFragment; 45 46public final class SettingsFragment extends InputMethodSettingsFragment 47 implements SharedPreferences.OnSharedPreferenceChangeListener { 48 private static final String TAG = SettingsFragment.class.getSimpleName(); 49 50 private static final int NO_MENU_GROUP = Menu.NONE; // We don't care about menu grouping. 51 private static final int MENU_FEEDBACK = Menu.FIRST; // The first menu item id and order. 52 private static final int MENU_ABOUT = Menu.FIRST + 1; // The second menu item id and order. 53 54 private void setPreferenceEnabled(final String preferenceKey, final boolean enabled) { 55 final Preference preference = findPreference(preferenceKey); 56 if (preference != null) { 57 preference.setEnabled(enabled); 58 } 59 } 60 61 private void updateListPreferenceSummaryToCurrentValue(final String prefKey) { 62 // Because the "%s" summary trick of {@link ListPreference} doesn't work properly before 63 // KitKat, we need to update the summary programmatically. 64 final ListPreference listPreference = (ListPreference)findPreference(prefKey); 65 if (listPreference == null) { 66 return; 67 } 68 final CharSequence entries[] = listPreference.getEntries(); 69 final int entryIndex = listPreference.findIndexOfValue(listPreference.getValue()); 70 listPreference.setSummary(entryIndex < 0 ? null : entries[entryIndex]); 71 } 72 73 private static void removePreference(final String preferenceKey, final PreferenceGroup parent) { 74 if (parent == null) { 75 return; 76 } 77 final Preference preference = parent.findPreference(preferenceKey); 78 if (preference != null) { 79 parent.removePreference(preference); 80 } 81 } 82 83 @Override 84 public void onCreate(final Bundle icicle) { 85 super.onCreate(icicle); 86 setHasOptionsMenu(true); 87 setInputMethodSettingsCategoryTitle(R.string.language_selection_title); 88 setSubtypeEnablerTitle(R.string.select_language); 89 addPreferencesFromResource(R.xml.prefs); 90 final PreferenceScreen preferenceScreen = getPreferenceScreen(); 91 TwoStatePreferenceHelper.replaceCheckBoxPreferencesBySwitchPreferences(preferenceScreen); 92 preferenceScreen.setTitle( 93 ApplicationUtils.getActivityTitleResId(getActivity(), SettingsActivity.class)); 94 95 final Resources res = getResources(); 96 final Context context = getActivity(); 97 98 // When we are called from the Settings application but we are not already running, some 99 // singleton and utility classes may not have been initialized. We have to call 100 // initialization method of these classes here. See {@link LatinIME#onCreate()}. 101 AudioAndHapticFeedbackManager.init(context); 102 103 final SharedPreferences prefs = getPreferenceManager().getSharedPreferences(); 104 prefs.registerOnSharedPreferenceChangeListener(this); 105 106 final PreferenceScreen advancedScreen = 107 (PreferenceScreen) findPreference(Settings.SCREEN_ADVANCED); 108 final PreferenceScreen debugScreen = 109 (PreferenceScreen) findPreference(Settings.SCREEN_DEBUG); 110 111 if (!Settings.isInternal(prefs)) { 112 advancedScreen.removePreference(debugScreen); 113 } 114 115 if (!AudioAndHapticFeedbackManager.getInstance().hasVibrator()) { 116 removePreference(Settings.PREF_VIBRATION_DURATION_SETTINGS, advancedScreen); 117 } 118 119 // TODO: consolidate key preview dismiss delay with the key preview animation parameters. 120 if (!Settings.readFromBuildConfigIfToShowKeyPreviewPopupOption(res)) { 121 removePreference(Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY, advancedScreen); 122 } else { 123 // TODO: Cleanup this setup. 124 final ListPreference keyPreviewPopupDismissDelay = 125 (ListPreference) findPreference(Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY); 126 final String popupDismissDelayDefaultValue = Integer.toString(res.getInteger( 127 R.integer.config_key_preview_linger_timeout)); 128 keyPreviewPopupDismissDelay.setEntries(new String[] { 129 res.getString(R.string.key_preview_popup_dismiss_no_delay), 130 res.getString(R.string.key_preview_popup_dismiss_default_delay), 131 }); 132 keyPreviewPopupDismissDelay.setEntryValues(new String[] { 133 "0", 134 popupDismissDelayDefaultValue 135 }); 136 if (null == keyPreviewPopupDismissDelay.getValue()) { 137 keyPreviewPopupDismissDelay.setValue(popupDismissDelayDefaultValue); 138 } 139 keyPreviewPopupDismissDelay.setEnabled( 140 Settings.readKeyPreviewPopupEnabled(prefs, res)); 141 } 142 143 if (!res.getBoolean(R.bool.config_setup_wizard_available)) { 144 removePreference(Settings.PREF_SHOW_SETUP_WIZARD_ICON, advancedScreen); 145 } 146 147 if (ProductionFlags.IS_METRICS_LOGGING_SUPPORTED) { 148 final Preference enableMetricsLogging = 149 findPreference(Settings.PREF_ENABLE_METRICS_LOGGING); 150 if (enableMetricsLogging != null) { 151 final int applicationLabelRes = context.getApplicationInfo().labelRes; 152 final String applicationName = res.getString(applicationLabelRes); 153 final String enableMetricsLoggingTitle = res.getString( 154 R.string.enable_metrics_logging, applicationName); 155 enableMetricsLogging.setTitle(enableMetricsLoggingTitle); 156 } 157 } else { 158 removePreference(Settings.PREF_ENABLE_METRICS_LOGGING, advancedScreen); 159 } 160 161 if (!Settings.readFromBuildConfigIfGestureInputEnabled(res)) { 162 getPreferenceScreen().removePreference(findPreference(Settings.SCREEN_GESTURE)); 163 } 164 165 AdditionalFeaturesSettingUtils.addAdditionalFeaturesPreferences(context, this); 166 167 setupKeypressVibrationDurationSettings(prefs, res); 168 setupKeypressSoundVolumeSettings(prefs, res); 169 refreshEnablingsOfKeypressSoundAndVibrationSettings(prefs, res); 170 } 171 172 @Override 173 public void onResume() { 174 super.onResume(); 175 final SharedPreferences prefs = getPreferenceManager().getSharedPreferences(); 176 final TwoStatePreference showSetupWizardIcon = 177 (TwoStatePreference)findPreference(Settings.PREF_SHOW_SETUP_WIZARD_ICON); 178 if (showSetupWizardIcon != null) { 179 showSetupWizardIcon.setChecked(Settings.readShowSetupWizardIcon(prefs, getActivity())); 180 } 181 updateListPreferenceSummaryToCurrentValue(Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY); 182 final ListPreference keyboardThemePref = (ListPreference)findPreference( 183 Settings.PREF_KEYBOARD_THEME); 184 if (keyboardThemePref != null) { 185 final KeyboardTheme keyboardTheme = KeyboardTheme.getKeyboardTheme(prefs); 186 final String value = Integer.toString(keyboardTheme.mThemeId); 187 final CharSequence entries[] = keyboardThemePref.getEntries(); 188 final int entryIndex = keyboardThemePref.findIndexOfValue(value); 189 keyboardThemePref.setSummary(entryIndex < 0 ? null : entries[entryIndex]); 190 keyboardThemePref.setValue(value); 191 } 192 } 193 194 @Override 195 public void onPause() { 196 super.onPause(); 197 final SharedPreferences prefs = getPreferenceManager().getSharedPreferences(); 198 final ListPreference keyboardThemePref = (ListPreference)findPreference( 199 Settings.PREF_KEYBOARD_THEME); 200 if (keyboardThemePref != null) { 201 KeyboardTheme.saveKeyboardThemeId(keyboardThemePref.getValue(), prefs); 202 } 203 } 204 205 @Override 206 public void onDestroy() { 207 getPreferenceManager().getSharedPreferences().unregisterOnSharedPreferenceChangeListener( 208 this); 209 super.onDestroy(); 210 } 211 212 @Override 213 public void onSharedPreferenceChanged(final SharedPreferences prefs, final String key) { 214 final Activity activity = getActivity(); 215 if (activity == null) { 216 // TODO: Introduce a static function to register this class and ensure that 217 // onCreate must be called before "onSharedPreferenceChanged" is called. 218 Log.w(TAG, "onSharedPreferenceChanged called before activity starts."); 219 return; 220 } 221 (new BackupManager(activity)).dataChanged(); 222 final Resources res = getResources(); 223 if (key.equals(Settings.PREF_POPUP_ON)) { 224 setPreferenceEnabled(Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY, 225 Settings.readKeyPreviewPopupEnabled(prefs, res)); 226 } else if (key.equals(Settings.PREF_SHOW_SETUP_WIZARD_ICON)) { 227 LauncherIconVisibilityManager.updateSetupWizardIconVisibility(getActivity()); 228 } 229 updateListPreferenceSummaryToCurrentValue(Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY); 230 updateListPreferenceSummaryToCurrentValue(Settings.PREF_KEYBOARD_THEME); 231 refreshEnablingsOfKeypressSoundAndVibrationSettings(prefs, getResources()); 232 } 233 234 private void refreshEnablingsOfKeypressSoundAndVibrationSettings( 235 final SharedPreferences sp, final Resources res) { 236 setPreferenceEnabled(Settings.PREF_VIBRATION_DURATION_SETTINGS, 237 Settings.readVibrationEnabled(sp, res)); 238 setPreferenceEnabled(Settings.PREF_KEYPRESS_SOUND_VOLUME, 239 Settings.readKeypressSoundEnabled(sp, res)); 240 } 241 242 private void setupKeypressVibrationDurationSettings(final SharedPreferences sp, 243 final Resources res) { 244 final SeekBarDialogPreference pref = (SeekBarDialogPreference)findPreference( 245 Settings.PREF_VIBRATION_DURATION_SETTINGS); 246 if (pref == null) { 247 return; 248 } 249 pref.setInterface(new SeekBarDialogPreference.ValueProxy() { 250 @Override 251 public void writeValue(final int value, final String key) { 252 sp.edit().putInt(key, value).apply(); 253 } 254 255 @Override 256 public void writeDefaultValue(final String key) { 257 sp.edit().remove(key).apply(); 258 } 259 260 @Override 261 public int readValue(final String key) { 262 return Settings.readKeypressVibrationDuration(sp, res); 263 } 264 265 @Override 266 public int readDefaultValue(final String key) { 267 return Settings.readDefaultKeypressVibrationDuration(res); 268 } 269 270 @Override 271 public void feedbackValue(final int value) { 272 AudioAndHapticFeedbackManager.getInstance().vibrate(value); 273 } 274 275 @Override 276 public String getValueText(final int value) { 277 if (value < 0) { 278 return res.getString(R.string.settings_system_default); 279 } 280 return res.getString(R.string.abbreviation_unit_milliseconds, value); 281 } 282 }); 283 } 284 285 private void setupKeypressSoundVolumeSettings(final SharedPreferences sp, final Resources res) { 286 final SeekBarDialogPreference pref = (SeekBarDialogPreference)findPreference( 287 Settings.PREF_KEYPRESS_SOUND_VOLUME); 288 if (pref == null) { 289 return; 290 } 291 final AudioManager am = (AudioManager)getActivity().getSystemService(Context.AUDIO_SERVICE); 292 pref.setInterface(new SeekBarDialogPreference.ValueProxy() { 293 private static final float PERCENTAGE_FLOAT = 100.0f; 294 295 private float getValueFromPercentage(final int percentage) { 296 return percentage / PERCENTAGE_FLOAT; 297 } 298 299 private int getPercentageFromValue(final float floatValue) { 300 return (int)(floatValue * PERCENTAGE_FLOAT); 301 } 302 303 @Override 304 public void writeValue(final int value, final String key) { 305 sp.edit().putFloat(key, getValueFromPercentage(value)).apply(); 306 } 307 308 @Override 309 public void writeDefaultValue(final String key) { 310 sp.edit().remove(key).apply(); 311 } 312 313 @Override 314 public int readValue(final String key) { 315 return getPercentageFromValue(Settings.readKeypressSoundVolume(sp, res)); 316 } 317 318 @Override 319 public int readDefaultValue(final String key) { 320 return getPercentageFromValue(Settings.readDefaultKeypressSoundVolume(res)); 321 } 322 323 @Override 324 public String getValueText(final int value) { 325 if (value < 0) { 326 return res.getString(R.string.settings_system_default); 327 } 328 return Integer.toString(value); 329 } 330 331 @Override 332 public void feedbackValue(final int value) { 333 am.playSoundEffect( 334 AudioManager.FX_KEYPRESS_STANDARD, getValueFromPercentage(value)); 335 } 336 }); 337 } 338 339 @Override 340 public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) { 341 if (FeedbackUtils.isFeedbackFormSupported()) { 342 menu.add(NO_MENU_GROUP, MENU_FEEDBACK /* itemId */, MENU_FEEDBACK /* order */, 343 R.string.send_feedback); 344 } 345 final int aboutResId = FeedbackUtils.getAboutKeyboardTitleResId(); 346 if (aboutResId != 0) { 347 menu.add(NO_MENU_GROUP, MENU_ABOUT /* itemId */, MENU_ABOUT /* order */, aboutResId); 348 } 349 } 350 351 @Override 352 public boolean onOptionsItemSelected(final MenuItem item) { 353 final int itemId = item.getItemId(); 354 if (itemId == MENU_FEEDBACK) { 355 FeedbackUtils.showFeedbackForm(getActivity()); 356 return true; 357 } 358 if (itemId == MENU_ABOUT) { 359 final Intent aboutIntent = FeedbackUtils.getAboutKeyboardIntent(getActivity()); 360 if (aboutIntent != null) { 361 startActivity(aboutIntent); 362 return true; 363 } 364 } 365 return super.onOptionsItemSelected(item); 366 } 367} 368