InputMethodAndLanguageSettings.java revision d79934731c8d33f6fc63b21c120b9ffba5d06f54
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.settings; 18 19import android.app.AlertDialog; 20import android.content.Context; 21import android.content.DialogInterface; 22import android.content.Intent; 23import android.content.pm.ApplicationInfo; 24import android.content.res.Configuration; 25import android.os.Bundle; 26import android.preference.CheckBoxPreference; 27import android.preference.Preference; 28import android.preference.PreferenceGroup; 29import android.preference.PreferenceScreen; 30import android.provider.Settings; 31import android.text.TextUtils; 32import android.view.inputmethod.InputMethodInfo; 33import android.view.inputmethod.InputMethodManager; 34 35import java.util.ArrayList; 36import java.util.HashSet; 37import java.util.List; 38 39public class LanguageSettings extends SettingsPreferenceFragment { 40 41 private static final String KEY_PHONE_LANGUAGE = "phone_language"; 42 private static final String KEY_INPUT_METHOD = "input_method"; 43 44 private boolean mHaveHardKeyboard; 45 46 private List<InputMethodInfo> mInputMethodProperties; 47 private List<CheckBoxPreference> mCheckboxes; 48 private Preference mLanguagePref; 49 50 final TextUtils.SimpleStringSplitter mStringColonSplitter 51 = new TextUtils.SimpleStringSplitter(':'); 52 53 private String mLastInputMethodId; 54 private String mLastTickedInputMethodId; 55 56 private AlertDialog mDialog = null; 57 58 static public String getInputMethodIdFromKey(String key) { 59 return key; 60 } 61 62 @Override 63 public void onCreate(Bundle icicle) { 64 super.onCreate(icicle); 65 66 addPreferencesFromResource(R.xml.language_settings); 67 68 if (getActivity().getAssets().getLocales().length == 1) { 69 getPreferenceScreen(). 70 removePreference(findPreference("language_category")); 71 } else { 72 mLanguagePref = findPreference(KEY_PHONE_LANGUAGE); 73 } 74 75 Configuration config = getResources().getConfiguration(); 76 if (config.keyboard != Configuration.KEYBOARD_QWERTY) { 77 getPreferenceScreen().removePreference( 78 getPreferenceScreen().findPreference("hardkeyboard_category")); 79 } else { 80 mHaveHardKeyboard = true; 81 } 82 mCheckboxes = new ArrayList<CheckBoxPreference>(); 83 onCreateIMM(); 84 } 85 86 private boolean isSystemIme(InputMethodInfo property) { 87 return (property.getServiceInfo().applicationInfo.flags 88 & ApplicationInfo.FLAG_SYSTEM) != 0; 89 } 90 91 private void onCreateIMM() { 92 InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); 93 94 mInputMethodProperties = imm.getInputMethodList(); 95 96 mLastInputMethodId = Settings.Secure.getString(getContentResolver(), 97 Settings.Secure.DEFAULT_INPUT_METHOD); 98 99 PreferenceGroup textCategory = (PreferenceGroup) findPreference("text_category"); 100 101 int N = (mInputMethodProperties == null ? 0 : mInputMethodProperties 102 .size()); 103 for (int i = 0; i < N; ++i) { 104 InputMethodInfo property = mInputMethodProperties.get(i); 105 String prefKey = property.getId(); 106 107 CharSequence label = property.loadLabel(getActivity().getPackageManager()); 108 boolean systemIME = isSystemIme(property); 109 // Add a check box. 110 // Don't show the toggle if it's the only keyboard in the system, or it's a system IME. 111 if (mHaveHardKeyboard || (N > 1 && !systemIME)) { 112 CheckBoxPreference chkbxPref = new CheckBoxPreference(getActivity()); 113 chkbxPref.setKey(prefKey); 114 chkbxPref.setTitle(label); 115 textCategory.addPreference(chkbxPref); 116 mCheckboxes.add(chkbxPref); 117 } 118 119 // If setting activity is available, add a setting screen entry. 120 if (null != property.getSettingsActivity()) { 121 PreferenceScreen prefScreen = new PreferenceScreen(getActivity(), null); 122 String settingsActivity = property.getSettingsActivity(); 123 if (settingsActivity.lastIndexOf("/") < 0) { 124 settingsActivity = property.getPackageName() + "/" + settingsActivity; 125 } 126 prefScreen.setKey(settingsActivity); 127 prefScreen.setTitle(label); 128 if (N == 1) { 129 prefScreen.setSummary(getResources().getString( 130 R.string.onscreen_keyboard_settings_summary)); 131 } else { 132 CharSequence settingsLabel = getResources().getString( 133 R.string.input_methods_settings_label_format, label); 134 prefScreen.setSummary(settingsLabel); 135 } 136 textCategory.addPreference(prefScreen); 137 } 138 } 139 } 140 141 @Override 142 public void onResume() { 143 super.onResume(); 144 145 final HashSet<String> enabled = new HashSet<String>(); 146 String enabledStr = Settings.Secure.getString(getContentResolver(), 147 Settings.Secure.ENABLED_INPUT_METHODS); 148 if (enabledStr != null) { 149 final TextUtils.SimpleStringSplitter splitter = mStringColonSplitter; 150 splitter.setString(enabledStr); 151 while (splitter.hasNext()) { 152 enabled.add(splitter.next()); 153 } 154 } 155 156 // Update the statuses of the Check Boxes. 157 int N = mInputMethodProperties.size(); 158 for (int i = 0; i < N; ++i) { 159 final String id = mInputMethodProperties.get(i).getId(); 160 CheckBoxPreference pref = (CheckBoxPreference) findPreference(mInputMethodProperties 161 .get(i).getId()); 162 if (pref != null) { 163 pref.setChecked(enabled.contains(id)); 164 } 165 } 166 mLastTickedInputMethodId = null; 167 168 if (mLanguagePref != null) { 169 Configuration conf = getResources().getConfiguration(); 170 String locale = conf.locale.getDisplayName(conf.locale); 171 if (locale != null && locale.length() > 1) { 172 locale = Character.toUpperCase(locale.charAt(0)) + locale.substring(1); 173 mLanguagePref.setSummary(locale); 174 } 175 } 176 } 177 178 @Override 179 public void onPause() { 180 super.onPause(); 181 182 StringBuilder builder = new StringBuilder(256); 183 StringBuilder disabledSysImes = new StringBuilder(256); 184 185 int firstEnabled = -1; 186 int N = mInputMethodProperties.size(); 187 for (int i = 0; i < N; ++i) { 188 final InputMethodInfo property = mInputMethodProperties.get(i); 189 final String id = property.getId(); 190 CheckBoxPreference pref = (CheckBoxPreference) findPreference(id); 191 boolean hasIt = id.equals(mLastInputMethodId); 192 boolean systemIme = isSystemIme(property); 193 if (((N == 1 || systemIme) && !mHaveHardKeyboard) 194 || (pref != null && pref.isChecked())) { 195 if (builder.length() > 0) builder.append(':'); 196 builder.append(id); 197 if (firstEnabled < 0) { 198 firstEnabled = i; 199 } 200 } else if (hasIt) { 201 mLastInputMethodId = mLastTickedInputMethodId; 202 } 203 // If it's a disabled system ime, add it to the disabled list so that it 204 // doesn't get enabled automatically on any changes to the package list 205 if (pref != null && !pref.isChecked() && systemIme && mHaveHardKeyboard) { 206 if (disabledSysImes.length() > 0) disabledSysImes.append(":"); 207 disabledSysImes.append(id); 208 } 209 } 210 211 // If the last input method is unset, set it as the first enabled one. 212 if (null == mLastInputMethodId || "".equals(mLastInputMethodId)) { 213 if (firstEnabled >= 0) { 214 mLastInputMethodId = mInputMethodProperties.get(firstEnabled).getId(); 215 } else { 216 mLastInputMethodId = null; 217 } 218 } 219 220 Settings.Secure.putString(getContentResolver(), 221 Settings.Secure.ENABLED_INPUT_METHODS, builder.toString()); 222 Settings.Secure.putString(getContentResolver(), 223 Settings.Secure.DISABLED_SYSTEM_INPUT_METHODS, disabledSysImes.toString()); 224 Settings.Secure.putString(getContentResolver(), 225 Settings.Secure.DEFAULT_INPUT_METHOD, 226 mLastInputMethodId != null ? mLastInputMethodId : ""); 227 } 228 229 @Override 230 public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) { 231 232 // Input Method stuff 233 if (Utils.isMonkeyRunning()) { 234 return false; 235 } 236 237 if (preference instanceof CheckBoxPreference) { 238 final CheckBoxPreference chkPref = (CheckBoxPreference) preference; 239 final String id = getInputMethodIdFromKey(chkPref.getKey()); 240 if (chkPref.isChecked()) { 241 InputMethodInfo selImi = null; 242 final int N = mInputMethodProperties.size(); 243 for (int i=0; i<N; i++) { 244 InputMethodInfo imi = mInputMethodProperties.get(i); 245 if (id.equals(imi.getId())) { 246 selImi = imi; 247 if (isSystemIme(imi)) { 248 // This is a built-in IME, so no need to warn. 249 mLastTickedInputMethodId = id; 250 return super.onPreferenceTreeClick(preferenceScreen, preference); 251 } 252 } 253 } 254 chkPref.setChecked(false); 255 if (selImi == null) { 256 return super.onPreferenceTreeClick(preferenceScreen, preference); 257 } 258 if (mDialog == null) { 259 // TODO: DialogFragment? 260 mDialog = (new AlertDialog.Builder(getActivity())) 261 .setTitle(android.R.string.dialog_alert_title) 262 .setIcon(android.R.drawable.ic_dialog_alert) 263 .setCancelable(true) 264 .setPositiveButton(android.R.string.ok, 265 new DialogInterface.OnClickListener() { 266 public void onClick(DialogInterface dialog, int which) { 267 chkPref.setChecked(true); 268 mLastTickedInputMethodId = id; 269 } 270 271 }) 272 .setNegativeButton(android.R.string.cancel, 273 new DialogInterface.OnClickListener() { 274 public void onClick(DialogInterface dialog, int which) { 275 } 276 277 }) 278 .create(); 279 } else { 280 if (mDialog.isShowing()) { 281 mDialog.dismiss(); 282 } 283 } 284 mDialog.setMessage(getResources().getString( 285 R.string.ime_security_warning, 286 selImi.getServiceInfo().applicationInfo.loadLabel(getPackageManager()))); 287 mDialog.show(); 288 } else if (id.equals(mLastTickedInputMethodId)) { 289 mLastTickedInputMethodId = null; 290 } 291 } else if (preference instanceof PreferenceScreen) { 292 if (KEY_INPUT_METHOD.equals(preference.getKey())) { 293 InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); 294 imm.showInputMethodPicker(); 295 } else if (preference.getIntent() == null) { 296 PreferenceScreen pref = (PreferenceScreen) preference; 297 String activityName = pref.getKey(); 298 String packageName = activityName.substring(0, activityName 299 .lastIndexOf(".")); 300 int slash = activityName.indexOf("/"); 301 if (slash > 0) { 302 packageName = activityName.substring(0, slash); 303 activityName = activityName.substring(slash + 1); 304 } 305 if (activityName.length() > 0) { 306 Intent i = new Intent(Intent.ACTION_MAIN); 307 i.setClassName(packageName, activityName); 308 startActivity(i); 309 } 310 } 311 } 312 return super.onPreferenceTreeClick(preferenceScreen, preference); 313 } 314 315 @Override 316 public void onDestroy() { 317 super.onDestroy(); 318 if (mDialog != null) { 319 mDialog.dismiss(); 320 mDialog = null; 321 } 322 } 323 324} 325