Adding search for dynamic accessibility settings.

The language and input settings are highly dynamic and this change adds search
support for that. This category depends on installed IMEs, input devices, user
dictionary configuration, etc. We not only compute the right preferences to be
indexed but also track related system state in the settings app to rebuild the
index if needed.

bug:14066763

Change-Id: Ia89d9e35bd79abf8d74614691aedf4ca9b11b6f2
This commit is contained in:
Svetoslav
2014-04-14 17:14:59 -07:00
parent 853e47181d
commit 990159abaa
4 changed files with 373 additions and 50 deletions

View File

@@ -40,6 +40,9 @@ import android.content.pm.ResolveInfo;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.content.res.TypedArray; import android.content.res.TypedArray;
import android.content.res.XmlResourceParser; import android.content.res.XmlResourceParser;
import android.database.ContentObserver;
import android.hardware.input.InputManager;
import android.net.Uri;
import android.nfc.NfcAdapter; import android.nfc.NfcAdapter;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
@@ -57,7 +60,7 @@ import android.preference.PreferenceScreen;
import android.print.PrintManager; import android.print.PrintManager;
import android.printservice.PrintService; import android.printservice.PrintService;
import android.printservice.PrintServiceInfo; import android.printservice.PrintServiceInfo;
import android.provider.SearchIndexableData; import android.provider.UserDictionary;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.Log; import android.util.Log;
@@ -69,6 +72,8 @@ import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
import android.view.accessibility.AccessibilityManager; import android.view.accessibility.AccessibilityManager;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button; import android.widget.Button;
import android.widget.ListView; import android.widget.ListView;
@@ -119,7 +124,6 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.Iterator;
import java.util.List; import java.util.List;
import static com.android.settings.dashboard.Header.HEADER_ID_UNDEFINED; import static com.android.settings.dashboard.Header.HEADER_ID_UNDEFINED;
@@ -315,8 +319,8 @@ public class SettingsActivity extends Activity
} }
}; };
private final DynamicIndexablePackageMonitor mDynamicIndexablePackageMonitor = private final DynamicIndexableContentMonitor mDynamicIndexableContentMonitor =
new DynamicIndexablePackageMonitor(); new DynamicIndexableContentMonitor();
private Button mNextButton; private Button mNextButton;
private ActionBar mActionBar; private ActionBar mActionBar;
@@ -625,7 +629,7 @@ public class SettingsActivity extends Activity
registerReceiver(mBatteryInfoReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED)); registerReceiver(mBatteryInfoReceiver, new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
mDynamicIndexablePackageMonitor.register(this); mDynamicIndexableContentMonitor.register(this);
} }
@Override @Override
@@ -641,7 +645,7 @@ public class SettingsActivity extends Activity
mDevelopmentPreferencesListener = null; mDevelopmentPreferencesListener = null;
mDynamicIndexablePackageMonitor.unregister(); mDynamicIndexableContentMonitor.unregister();
} }
@Override @Override
@@ -1290,13 +1294,18 @@ public class SettingsActivity extends Activity
mSearchMenuItem.collapseActionView(); mSearchMenuItem.collapseActionView();
} }
private static final class DynamicIndexablePackageMonitor extends PackageMonitor { private static final class DynamicIndexableContentMonitor extends PackageMonitor implements
InputManager.InputDeviceListener {
private static final Intent ACCESSIBILITY_SERVICE_INTENT = private static final Intent ACCESSIBILITY_SERVICE_INTENT =
new Intent(AccessibilityService.SERVICE_INTERFACE); new Intent(AccessibilityService.SERVICE_INTERFACE);
private static final Intent PRINT_SERVICE_INTENT = private static final Intent PRINT_SERVICE_INTENT =
new Intent(PrintService.SERVICE_INTERFACE); new Intent(PrintService.SERVICE_INTERFACE);
private static final Intent IME_SERVICE_INTENT =
new Intent("android.view.InputMethod");
private static final long DELAY_PROCESS_PACKAGE_CHANGE = 2000; private static final long DELAY_PROCESS_PACKAGE_CHANGE = 2000;
private static final int MSG_PACKAGE_AVAILABLE = 1; private static final int MSG_PACKAGE_AVAILABLE = 1;
@@ -1304,6 +1313,7 @@ public class SettingsActivity extends Activity
private final List<String> mAccessibilityServices = new ArrayList<String>(); private final List<String> mAccessibilityServices = new ArrayList<String>();
private final List<String> mPrintServices = new ArrayList<String>(); private final List<String> mPrintServices = new ArrayList<String>();
private final List<String> mImeServices = new ArrayList<String>();
private final Handler mHandler = new Handler() { private final Handler mHandler = new Handler() {
@Override @Override
@@ -1322,6 +1332,8 @@ public class SettingsActivity extends Activity
} }
}; };
private final ContentObserver mContentObserver = new MyContentObserver(mHandler);
private Context mContext; private Context mContext;
public void register(Context context) { public void register(Context context) {
@@ -1350,13 +1362,41 @@ public class SettingsActivity extends Activity
.serviceInfo.packageName); .serviceInfo.packageName);
} }
// Cache IME service packages to know when they go away.
InputMethodManager imeManager = (InputMethodManager)
mContext.getSystemService(Context.INPUT_METHOD_SERVICE);
List<InputMethodInfo> inputMethods = imeManager.getInputMethodList();
final int inputMethodCount = inputMethods.size();
for (int i = 0; i < inputMethodCount; i++) {
InputMethodInfo inputMethod = inputMethods.get(i);
mImeServices.add(inputMethod.getServiceInfo().packageName);
}
// Watch for related content URIs.
mContext.getContentResolver().registerContentObserver(
UserDictionary.Words.CONTENT_URI, true, mContentObserver);
// Watch for input device changes.
InputManager inputManager = (InputManager) context.getSystemService(
Context.INPUT_SERVICE);
inputManager.registerInputDeviceListener(this, mHandler);
// Start tracking packages.
register(context, Looper.getMainLooper(), UserHandle.CURRENT, false); register(context, Looper.getMainLooper(), UserHandle.CURRENT, false);
} }
public void unregister() { public void unregister() {
super.unregister(); super.unregister();
InputManager inputManager = (InputManager) mContext.getSystemService(
Context.INPUT_SERVICE);
inputManager.unregisterInputDeviceListener(this);
mContext.getContentResolver().unregisterContentObserver(mContentObserver);
mAccessibilityServices.clear(); mAccessibilityServices.clear();
mPrintServices.clear(); mPrintServices.clear();
mImeServices.clear();
} }
// Covers installed, appeared external storage with the package, upgraded. // Covers installed, appeared external storage with the package, upgraded.
@@ -1385,6 +1425,23 @@ public class SettingsActivity extends Activity
} }
} }
@Override
public void onInputDeviceAdded(int deviceId) {
Index.getInstance(mContext).updateFromClassNameResource(
InputMethodAndLanguageSettings.class.getName(), false, true);
}
@Override
public void onInputDeviceRemoved(int deviceId) {
onInputDeviceChanged(deviceId);
}
@Override
public void onInputDeviceChanged(int deviceId) {
Index.getInstance(mContext).updateFromClassNameResource(
InputMethodAndLanguageSettings.class.getName(), true, true);
}
private void postMessage(int what, String packageName) { private void postMessage(int what, String packageName) {
Message message = mHandler.obtainMessage(what, packageName); Message message = mHandler.obtainMessage(what, packageName);
mHandler.sendMessageDelayed(message, DELAY_PROCESS_PACKAGE_CHANGE); mHandler.sendMessageDelayed(message, DELAY_PROCESS_PACKAGE_CHANGE);
@@ -1412,6 +1469,17 @@ public class SettingsActivity extends Activity
} }
intent.setPackage(null); intent.setPackage(null);
} }
if (!mImeServices.contains(packageName)) {
Intent intent = IME_SERVICE_INTENT;
intent.setPackage(packageName);
if (!mContext.getPackageManager().queryIntentServices(intent, 0).isEmpty()) {
mImeServices.add(packageName);
Index.getInstance(mContext).updateFromClassNameResource(
InputMethodAndLanguageSettings.class.getName(), false, true);
}
intent.setPackage(null);
}
} }
private void handlePackageUnavailable(String packageName) { private void handlePackageUnavailable(String packageName) {
@@ -1429,5 +1497,20 @@ public class SettingsActivity extends Activity
PrintSettingsFragment.class.getName(), true, true); PrintSettingsFragment.class.getName(), true, true);
} }
} }
private final class MyContentObserver extends ContentObserver {
public MyContentObserver(Handler handler) {
super(handler);
}
@Override
public void onChange(boolean selfChange, Uri uri) {
if (UserDictionary.Words.CONTENT_URI.equals(uri)) {
Index.getInstance(mContext).updateFromClassNameResource(
InputMethodAndLanguageSettings.class.getName(), true, true);
}
};
}
} }
} }

View File

@@ -23,6 +23,9 @@ import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.UserDictionarySettings; import com.android.settings.UserDictionarySettings;
import com.android.settings.Utils; import com.android.settings.Utils;
import com.android.settings.VoiceInputOutputSettings; import com.android.settings.VoiceInputOutputSettings;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
import com.android.settings.search.SearchIndexableRaw;
import android.app.Activity; import android.app.Activity;
import android.app.Fragment; import android.app.Fragment;
@@ -30,6 +33,7 @@ import android.content.ContentResolver;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.content.res.Resources; import android.content.res.Resources;
import android.database.ContentObserver; import android.database.ContentObserver;
@@ -47,10 +51,13 @@ import android.preference.PreferenceCategory;
import android.preference.PreferenceScreen; import android.preference.PreferenceScreen;
import android.provider.Settings; import android.provider.Settings;
import android.provider.Settings.System; import android.provider.Settings.System;
import android.speech.RecognitionService;
import android.speech.tts.TtsEngines;
import android.text.TextUtils; import android.text.TextUtils;
import android.view.InputDevice; import android.view.InputDevice;
import android.view.inputmethod.InputMethodInfo; import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.InputMethodSubtype;
import android.widget.BaseAdapter; import android.widget.BaseAdapter;
import java.util.ArrayList; import java.util.ArrayList;
@@ -60,7 +67,7 @@ import java.util.TreeSet;
public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment
implements Preference.OnPreferenceChangeListener, InputManager.InputDeviceListener, implements Preference.OnPreferenceChangeListener, InputManager.InputDeviceListener,
KeyboardLayoutDialogFragment.OnSetupKeyboardLayoutsListener { KeyboardLayoutDialogFragment.OnSetupKeyboardLayoutsListener, Indexable {
private static final String KEY_PHONE_LANGUAGE = "phone_language"; private static final String KEY_PHONE_LANGUAGE = "phone_language";
private static final String KEY_CURRENT_INPUT_METHOD = "current_input_method"; private static final String KEY_CURRENT_INPUT_METHOD = "current_input_method";
@@ -242,34 +249,8 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment
if (!mIsOnlyImeSettings) { if (!mIsOnlyImeSettings) {
if (mLanguagePref != null) { if (mLanguagePref != null) {
Configuration conf = getResources().getConfiguration(); String localeName = getLocaleName(getResources());
String language = conf.locale.getLanguage(); mLanguagePref.setSummary(localeName);
String localeString;
// TODO: This is not an accurate way to display the locale, as it is
// just working around the fact that we support limited dialects
// and want to pretend that the language is valid for all locales.
// We need a way to support languages that aren't tied to a particular
// locale instead of hiding the locale qualifier.
if (language.equals("zz")) {
String country = conf.locale.getCountry();
if (country.equals("ZZ")) {
localeString = "[Developer] Accented English (zz_ZZ)";
} else if (country.equals("ZY")) {
localeString = "[Developer] Fake Bi-Directional (zz_ZY)";
} else {
localeString = "";
}
} else if (hasOnlyOneLanguageInstance(language,
Resources.getSystem().getAssets().getLocales())) {
localeString = conf.locale.getDisplayLanguage(conf.locale);
} else {
localeString = conf.locale.getDisplayName(conf.locale);
}
if (localeString.length() > 1) {
localeString = Character.toUpperCase(localeString.charAt(0))
+ localeString.substring(1);
mLanguagePref.setSummary(localeString);
}
} }
updateUserDictionaryPreference(findPreference(KEY_USER_DICTIONARY_SETTINGS)); updateUserDictionaryPreference(findPreference(KEY_USER_DICTIONARY_SETTINGS));
@@ -361,7 +342,40 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment
return super.onPreferenceTreeClick(preferenceScreen, preference); return super.onPreferenceTreeClick(preferenceScreen, preference);
} }
private boolean hasOnlyOneLanguageInstance(String languageCode, String[] locales) { private static String getLocaleName(Resources resources) {
Configuration conf = resources.getConfiguration();
String language = conf.locale.getLanguage();
String localeName;
// TODO: This is not an accurate way to display the locale, as it is
// just working around the fact that we support limited dialects
// and want to pretend that the language is valid for all locales.
// We need a way to support languages that aren't tied to a particular
// locale instead of hiding the locale qualifier.
if (language.equals("zz")) {
String country = conf.locale.getCountry();
if (country.equals("ZZ")) {
localeName = "[Developer] Accented English (zz_ZZ)";
} else if (country.equals("ZY")) {
localeName = "[Developer] Fake Bi-Directional (zz_ZY)";
} else {
localeName = "";
}
} else if (hasOnlyOneLanguageInstance(language,
Resources.getSystem().getAssets().getLocales())) {
localeName = conf.locale.getDisplayLanguage(conf.locale);
} else {
localeName = conf.locale.getDisplayName(conf.locale);
}
if (localeName.length() > 1) {
localeName = Character.toUpperCase(localeName.charAt(0))
+ localeName.substring(1);
}
return localeName;
}
private static boolean hasOnlyOneLanguageInstance(String languageCode, String[] locales) {
int count = 0; int count = 0;
for (String localeCode : locales) { for (String localeCode : locales) {
if (localeCode.length() > 2 if (localeCode.length() > 2
@@ -582,7 +596,7 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment
} }
} }
private boolean haveInputDeviceWithVibrator() { private static boolean haveInputDeviceWithVibrator() {
final int[] devices = InputDevice.getDeviceIds(); final int[] devices = InputDevice.getDeviceIds();
for (int i = 0; i < devices.length; i++) { for (int i = 0; i < devices.length; i++) {
InputDevice device = InputDevice.getDevice(devices[i]); InputDevice device = InputDevice.getDevice(devices[i]);
@@ -617,4 +631,225 @@ public class InputMethodAndLanguageSettings extends SettingsPreferenceFragment
mContext.getContentResolver().unregisterContentObserver(this); mContext.getContentResolver().unregisterContentObserver(this);
} }
} }
public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider() {
@Override
public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) {
List<SearchIndexableRaw> indexables = new ArrayList<SearchIndexableRaw>();
Resources resources = context.getResources();
String screenTitle = context.getString(R.string.language_keyboard_settings_title);
// Locale picker.
if (context.getAssets().getLocales().length > 1) {
String localeName = getLocaleName(resources);
SearchIndexableRaw indexable = new SearchIndexableRaw(context);
indexable.title = context.getString(R.string.phone_language);
indexable.summaryOn = localeName;
indexable.summaryOff = localeName;
indexable.screenTitle = screenTitle;
indexables.add(indexable);
}
// Spell checker.
SearchIndexableRaw indexable = new SearchIndexableRaw(context);
indexable.title = context.getString(R.string.spellcheckers_settings_title);
indexable.screenTitle = screenTitle;
indexables.add(indexable);
// User dictionary.
if (UserDictionaryList.getUserDictionaryLocalesSet(context) != null) {
indexable = new SearchIndexableRaw(context);
indexable.title = context.getString(R.string.user_dict_settings_title);
indexable.screenTitle = screenTitle;
indexables.add(indexable);
}
// Keyboard settings.
indexable = new SearchIndexableRaw(context);
indexable.title = context.getString(R.string.keyboard_settings_category);
indexable.screenTitle = screenTitle;
indexables.add(indexable);
InputMethodSettingValuesWrapper immValues = InputMethodSettingValuesWrapper
.getInstance(context);
immValues.refreshAllInputMethodAndSubtypes();
// Current IME.
String currImeName = immValues.getCurrentInputMethodName(context).toString();
indexable = new SearchIndexableRaw(context);
indexable.title = context.getString(R.string.current_input_method);
indexable.summaryOn = currImeName;
indexable.summaryOff = currImeName;
indexable.screenTitle = screenTitle;
indexables.add(indexable);
InputMethodManager inputMethodManager = (InputMethodManager) context.getSystemService(
Context.INPUT_METHOD_SERVICE);
// All other IMEs.
List<InputMethodInfo> inputMethods = immValues.getInputMethodList();
final int inputMethodCount = (inputMethods == null ? 0 : inputMethods.size());
for (int i = 0; i < inputMethodCount; ++i) {
InputMethodInfo inputMethod = inputMethods.get(i);
StringBuilder builder = new StringBuilder();
List<InputMethodSubtype> subtypes = inputMethodManager
.getEnabledInputMethodSubtypeList(inputMethod, true);
final int subtypeCount = subtypes.size();
for (int j = 0; j < subtypeCount; j++) {
InputMethodSubtype subtype = subtypes.get(j);
if (builder.length() > 0) {
builder.append(',');
}
CharSequence subtypeLabel = subtype.getDisplayName(context,
inputMethod.getPackageName(), inputMethod.getServiceInfo()
.applicationInfo);
builder.append(subtypeLabel);
}
String summary = builder.toString();
indexable = new SearchIndexableRaw(context);
indexable.title = inputMethod.loadLabel(context.getPackageManager()).toString();
indexable.summaryOn = summary;
indexable.summaryOff = summary;
indexable.screenTitle = screenTitle;
indexables.add(indexable);
}
// Hard keyboards
InputManager inputManager = (InputManager) context.getSystemService(
Context.INPUT_SERVICE);
if (resources.getConfiguration().keyboard == Configuration.KEYBOARD_QWERTY) {
boolean hasHardKeyboards = false;
final int[] devices = InputDevice.getDeviceIds();
for (int i = 0; i < devices.length; i++) {
InputDevice device = InputDevice.getDevice(devices[i]);
if (device == null || device.isVirtual() || !device.isFullKeyboard()) {
continue;
}
hasHardKeyboards = true;
InputDeviceIdentifier identifier = device.getIdentifier();
String keyboardLayoutDescriptor =
inputManager.getCurrentKeyboardLayoutForInputDevice(identifier);
KeyboardLayout keyboardLayout = keyboardLayoutDescriptor != null ?
inputManager.getKeyboardLayout(keyboardLayoutDescriptor) : null;
String summary;
if (keyboardLayout != null) {
summary = keyboardLayout.toString();
} else {
summary = context.getString(R.string.keyboard_layout_default_label);
}
indexable = new SearchIndexableRaw(context);
indexable.title = device.getName();
indexable.summaryOn = summary;
indexable.summaryOff = summary;
indexable.screenTitle = screenTitle;
indexables.add(indexable);
}
if (hasHardKeyboards) {
// Hard keyboard category.
indexable = new SearchIndexableRaw(context);
indexable.title = context.getString(
R.string.builtin_keyboard_settings_title);
indexable.screenTitle = screenTitle;
indexables.add(indexable);
// Auto replace.
indexable = new SearchIndexableRaw(context);
indexable.title = context.getString(R.string.auto_replace);
indexable.summaryOn = context.getString(R.string.auto_replace_summary);
indexable.summaryOff = context.getString(R.string.auto_replace_summary);
indexable.screenTitle = screenTitle;
indexables.add(indexable);
// Auto caps.
indexable = new SearchIndexableRaw(context);
indexable.title = context.getString(R.string.auto_caps);
indexable.summaryOn = context.getString(R.string.auto_caps_summary);
indexable.summaryOff = context.getString(R.string.auto_caps_summary);
indexable.screenTitle = screenTitle;
indexables.add(indexable);
// Auto punctuate.
indexable = new SearchIndexableRaw(context);
indexable.title = context.getString(R.string.auto_punctuate);
indexable.summaryOn = context.getString(R.string.auto_punctuate_summary);
indexable.summaryOff = context.getString(R.string.auto_punctuate_summary);
indexable.screenTitle = screenTitle;
indexables.add(indexable);
}
}
// Voice recognizers.
List<ResolveInfo> recognizers = context.getPackageManager()
.queryIntentServices(new Intent(RecognitionService.SERVICE_INTERFACE),
PackageManager.GET_META_DATA);
final int recognizerCount = recognizers.size();
// Recognizer settings.
if (recognizerCount > 0) {
indexable = new SearchIndexableRaw(context);
indexable.title = context.getString(R.string.recognizer_settings_title);
indexable.screenTitle = screenTitle;
indexables.add(indexable);
}
if (recognizerCount > 1) {
// Recognizer chooser.
indexable = new SearchIndexableRaw(context);
indexable.title = context.getString(R.string.recognizer_title);
indexable.screenTitle = screenTitle;
indexables.add(indexable);
}
for (int i = 0; i < recognizerCount; i++) {
ResolveInfo recognizer = recognizers.get(i);
indexable = new SearchIndexableRaw(context);
indexable.title = recognizer.loadLabel(context.getPackageManager()).toString();
indexable.screenTitle = screenTitle;
indexables.add(indexable);
}
// Text-to-speech.
TtsEngines ttsEngines = new TtsEngines(context);
if (!ttsEngines.getEngines().isEmpty()) {
indexable = new SearchIndexableRaw(context);
indexable.title = context.getString(R.string.tts_settings_title);
indexable.screenTitle = screenTitle;
indexables.add(indexable);
}
// Pointer settings.
indexable = new SearchIndexableRaw(context);
indexable.title = context.getString(R.string.pointer_settings_category);
indexable.screenTitle = screenTitle;
indexables.add(indexable);
indexable = new SearchIndexableRaw(context);
indexable.title = context.getString(R.string.pointer_speed);
indexable.screenTitle = screenTitle;
indexables.add(indexable);
// Game controllers.
if (haveInputDeviceWithVibrator()) {
indexable = new SearchIndexableRaw(context);
indexable.title = context.getString(R.string.vibrate_input_devices);
indexable.summaryOn = context.getString(R.string.vibrate_input_devices_summary);
indexable.summaryOff = context.getString(R.string.vibrate_input_devices_summary);
indexable.screenTitle = screenTitle;
indexables.add(indexable);
}
return indexables;
}
};
} }

View File

@@ -72,22 +72,27 @@ public class UserDictionaryList extends SettingsPreferenceFragment {
mLocale = locale; mLocale = locale;
} }
public static TreeSet<String> getUserDictionaryLocalesSet(Activity activity) { public static TreeSet<String> getUserDictionaryLocalesSet(Context context) {
@SuppressWarnings("deprecation") final Cursor cursor = context.getContentResolver().query(
final Cursor cursor = activity.managedQuery(UserDictionary.Words.CONTENT_URI, UserDictionary.Words.CONTENT_URI, new String[] { UserDictionary.Words.LOCALE },
new String[] { UserDictionary.Words.LOCALE },
null, null, null); null, null, null);
final TreeSet<String> localeSet = new TreeSet<String>(); final TreeSet<String> localeSet = new TreeSet<String>();
if (null == cursor) { if (null == cursor) {
// The user dictionary service is not present or disabled. Return null. // The user dictionary service is not present or disabled. Return null.
return null; return null;
} else if (cursor.moveToFirst()) {
final int columnIndex = cursor.getColumnIndex(UserDictionary.Words.LOCALE);
do {
final String locale = cursor.getString(columnIndex);
localeSet.add(null != locale ? locale : "");
} while (cursor.moveToNext());
} }
try {
if (cursor.moveToFirst()) {
final int columnIndex = cursor.getColumnIndex(UserDictionary.Words.LOCALE);
do {
final String locale = cursor.getString(columnIndex);
localeSet.add(null != locale ? locale : "");
} while (cursor.moveToNext());
}
} finally {
cursor.close();
}
// CAVEAT: Keep this for consistency of the implementation between Keyboard and Settings // CAVEAT: Keep this for consistency of the implementation between Keyboard and Settings
// if (!UserDictionarySettings.IS_SHORTCUT_API_SUPPORTED) { // if (!UserDictionarySettings.IS_SHORTCUT_API_SUPPORTED) {
// // For ICS, we need to show "For all languages" in case that the keyboard locale // // For ICS, we need to show "For all languages" in case that the keyboard locale
@@ -96,7 +101,7 @@ public class UserDictionaryList extends SettingsPreferenceFragment {
// } // }
final InputMethodManager imm = final InputMethodManager imm =
(InputMethodManager)activity.getSystemService(Context.INPUT_METHOD_SERVICE); (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
final List<InputMethodInfo> imis = imm.getEnabledInputMethodList(); final List<InputMethodInfo> imis = imm.getEnabledInputMethodList();
for (final InputMethodInfo imi : imis) { for (final InputMethodInfo imi : imis) {
final List<InputMethodSubtype> subtypes = final List<InputMethodSubtype> subtypes =

View File

@@ -168,7 +168,7 @@ public final class SearchIndexableResources {
sResMap.put(InputMethodAndLanguageSettings.class.getName(), sResMap.put(InputMethodAndLanguageSettings.class.getName(),
new SearchIndexableResource(RANK_IME, new SearchIndexableResource(RANK_IME,
R.xml.language_settings, NO_DATA_RES_ID,
InputMethodAndLanguageSettings.class.getName(), InputMethodAndLanguageSettings.class.getName(),
R.drawable.ic_settings_language)); R.drawable.ic_settings_language));