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