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