Use reflections for classes related to InputMethodSubtype

Change-Id: Ica53ce879c2b4c5eb47f757fb788a795a881c30e
main
satok 2011-03-17 22:49:06 -07:00
parent 0a7cf81ca2
commit 610f1dc855
10 changed files with 333 additions and 35 deletions

View File

@ -0,0 +1,35 @@
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.inputmethod.compat;
import android.util.Log;
public abstract class AbstractCompatWrapper {
private static final String TAG = AbstractCompatWrapper.class.getSimpleName();
protected final Object mObj;
public AbstractCompatWrapper(Object obj) {
if (obj == null) {
Log.e(TAG, "Invalid input to AbstructCompatWrapper");
}
mObj = obj;
}
public Object getOriginalObject() {
return mObj;
}
}

View File

@ -18,8 +18,15 @@ package com.android.inputmethod.compat;
import android.content.Intent;
import android.text.TextUtils;
import android.util.Log;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
public class CompatUtils {
private static final String TAG = CompatUtils.class.getSimpleName();
private static final String EXTRA_INPUT_METHOD_ID = "input_method_id";
// TODO: Can these be constants instead of literal String constants?
private static final String INPUT_METHOD_SUBTYPE_SETTINGS =
@ -48,4 +55,53 @@ public class CompatUtils {
}
return intent;
}
public static Class<?> getClass(String className) {
try {
return Class.forName(className);
} catch (ClassNotFoundException e) {
return null;
}
}
public static Method getMethod(Class<?> targetClass, String name,
Class<?>... parameterTypes) {
try {
return targetClass.getMethod(name, parameterTypes);
} catch (SecurityException e) {
// ignore
return null;
} catch (NoSuchMethodException e) {
// ignore
return null;
}
}
public static Object invoke(
Object receiver, Object defaultValue, Method method, Object... args) {
if (receiver == null || method == null) return defaultValue;
try {
return method.invoke(receiver, args);
} catch (IllegalArgumentException e) {
Log.e(TAG, "Exception in invoke: IllegalArgmentException");
return defaultValue;
} catch (IllegalAccessException e) {
Log.e(TAG, "Exception in invoke: IllegalAccessException");
return defaultValue;
} catch (InvocationTargetException e) {
Log.e(TAG, "Exception in invoke: IllegalTargetException");
return defaultValue;
}
}
public static List<InputMethodSubtypeCompatWrapper> copyInputMethodSubtypeListToWrappler(
Object listObject) {
if (!(listObject instanceof List<?>)) return null;
final List<InputMethodSubtypeCompatWrapper> subtypes =
new ArrayList<InputMethodSubtypeCompatWrapper>();
for (Object o: (List<?>)listObject) {
subtypes.add(new InputMethodSubtypeCompatWrapper(o));
}
return subtypes;
}
}

View File

@ -0,0 +1,115 @@
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.inputmethod.compat;
import android.content.Context;
import android.os.IBinder;
import android.util.Log;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
// TODO: Override this class with the concrete implementation if we need to take care of the
// performance.
public class InputMethodManagerCompatWrapper {
private static final String TAG = InputMethodManagerCompatWrapper.class.getSimpleName();
private static final Method METHOD_getCurrentInputMethodSubtype =
CompatUtils.getMethod(InputMethodManager.class, "getCurrentInputMethodSubtype");
private static final Method METHOD_getEnabledInputMethodSubtypeList =
CompatUtils.getMethod(InputMethodManager.class, "getEnabledInputMethodSubtypeList",
InputMethodInfo.class, boolean.class);
private static final Method METHOD_getShortcutInputMethodsAndSubtypes =
CompatUtils.getMethod(InputMethodManager.class, "getShortcutInputMethodsAndSubtypes");
private static final Method METHOD_setInputMethodAndSubtype =
CompatUtils.getMethod(
InputMethodManager.class, "setInputMethodAndSubtype", IBinder.class,
String.class, InputMethodSubtypeCompatWrapper.CLASS_InputMethodSubtype);
private static final InputMethodManagerCompatWrapper sInstance =
new InputMethodManagerCompatWrapper();
private InputMethodManager mImm;
private InputMethodManagerCompatWrapper() {
}
public static InputMethodManagerCompatWrapper getInstance(Context context) {
if (sInstance.mImm == null) {
sInstance.init(context);
}
return sInstance;
}
private synchronized void init(Context context) {
mImm = (InputMethodManager) context.getSystemService(
Context.INPUT_METHOD_SERVICE);
}
public InputMethodSubtypeCompatWrapper getCurrentInputMethodSubtype() {
return new InputMethodSubtypeCompatWrapper(
CompatUtils.invoke(mImm, null, METHOD_getCurrentInputMethodSubtype));
}
public List<InputMethodSubtypeCompatWrapper> getEnabledInputMethodSubtypeList(
InputMethodInfo imi, boolean allowsImplicitlySelectedSubtypes) {
Object retval = CompatUtils.invoke(mImm, null, METHOD_getEnabledInputMethodSubtypeList,
imi, allowsImplicitlySelectedSubtypes);
return CompatUtils.copyInputMethodSubtypeListToWrappler((List<?>)retval);
}
public Map<InputMethodInfo, List<InputMethodSubtypeCompatWrapper>>
getShortcutInputMethodsAndSubtypes() {
Object retval = CompatUtils.invoke(mImm, null, METHOD_getShortcutInputMethodsAndSubtypes);
if (!(retval instanceof Map)) return null;
Map<InputMethodInfo, List<InputMethodSubtypeCompatWrapper>> shortcutMap =
new HashMap<InputMethodInfo, List<InputMethodSubtypeCompatWrapper>>();
final Map<?, ?> retvalMap = (Map<?, ?>)retval;
for (Object key: retvalMap.keySet()) {
if (!(key instanceof InputMethodInfo)) {
Log.e(TAG, "Class type error.");
return null;
}
shortcutMap.put((InputMethodInfo)key, CompatUtils.copyInputMethodSubtypeListToWrappler(
retvalMap.get(key)));
}
return shortcutMap;
}
public void setInputMethodAndSubtype(
IBinder token, String id, InputMethodSubtypeCompatWrapper subtype) {
CompatUtils.invoke(mImm, null, METHOD_setInputMethodAndSubtype,
token, id, subtype.getOriginalObject());
}
public boolean switchToLastInputMethod(IBinder token) {
if (mImm == null) return false;
return mImm.switchToLastInputMethod(token);
}
public List<InputMethodInfo> getEnabledInputMethodList() {
if (mImm == null) return null;
return mImm.getEnabledInputMethodList();
}
public void showInputMethodPicker() {
if (mImm == null) return;
mImm.showInputMethodPicker();
}
}

View File

@ -0,0 +1,93 @@
/*
* Copyright (C) 2011 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.inputmethod.compat;
import com.android.inputmethod.latin.LatinImeLogger;
import android.util.Log;
import java.lang.reflect.Method;
// TODO: Override this class with the concrete implementation if we need to take care of the
// performance.
public final class InputMethodSubtypeCompatWrapper extends AbstractCompatWrapper {
private static final boolean DBG = LatinImeLogger.sDBG;
private static final String TAG = InputMethodSubtypeCompatWrapper.class.getSimpleName();
public static final Class<?> CLASS_InputMethodSubtype =
CompatUtils.getClass("android.view.inputmethod.InputMethodSubtype");
private static final Method METHOD_getNameResId =
CompatUtils.getMethod(CLASS_InputMethodSubtype, "getNameResId");
private static final Method METHOD_getIconResId =
CompatUtils.getMethod(CLASS_InputMethodSubtype, "getIconResId");
private static final Method METHOD_getLocale =
CompatUtils.getMethod(CLASS_InputMethodSubtype, "getLocale");
private static final Method METHOD_getMode =
CompatUtils.getMethod(CLASS_InputMethodSubtype, "getMode");
private static final Method METHOD_getExtraValue =
CompatUtils.getMethod(CLASS_InputMethodSubtype, "getExtraValue");
private static final Method METHOD_containsExtraValueKey =
CompatUtils.getMethod(CLASS_InputMethodSubtype, "containsExtraValueKey", String.class);
private static final Method METHOD_getExtraValueOf =
CompatUtils.getMethod(CLASS_InputMethodSubtype, "getExtraValueOf", String.class);
public InputMethodSubtypeCompatWrapper(Object subtype) {
super(CLASS_InputMethodSubtype.isInstance(subtype) ? subtype : null);
if (DBG) {
Log.d(TAG, "CreateInputMethodSubtypeCompatWrapper");
}
}
public int getNameResId() {
return (Integer)CompatUtils.invoke(mObj, 0, METHOD_getNameResId);
}
public int getIconResId() {
return (Integer)CompatUtils.invoke(mObj, 0, METHOD_getIconResId);
}
public String getLocale() {
return (String)CompatUtils.invoke(mObj, null, METHOD_getLocale);
}
public String getMode() {
return (String)CompatUtils.invoke(mObj, null, METHOD_getMode);
}
public String getExtraValue() {
return (String)CompatUtils.invoke(mObj, null, METHOD_getExtraValue);
}
public boolean containsExtraValueKey(String key) {
return (Boolean)CompatUtils.invoke(mObj, null, METHOD_containsExtraValueKey, key);
}
public String getExtraValueOf(String key) {
return (String)CompatUtils.invoke(mObj, null, METHOD_getExtraValueOf, key);
}
@Override
public boolean equals(Object o) {
if (o instanceof InputMethodSubtypeCompatWrapper) {
InputMethodSubtypeCompatWrapper subtype = (InputMethodSubtypeCompatWrapper)o;
return mObj.equals(subtype.getOriginalObject());
} else {
return mObj.equals(o);
}
}
}

View File

@ -16,6 +16,7 @@
package com.android.inputmethod.deprecated;
import com.android.inputmethod.compat.InputMethodManagerCompatWrapper;
import com.android.inputmethod.deprecated.voice.FieldContext;
import com.android.inputmethod.deprecated.voice.Hints;
import com.android.inputmethod.deprecated.voice.SettingsUtil;
@ -60,7 +61,6 @@ import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.ExtractedTextRequest;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
import android.widget.TextView;
import java.util.ArrayList;
@ -99,7 +99,7 @@ public class VoiceConnector implements VoiceInput.UiListener {
private boolean mVoiceButtonOnPrimary;
private boolean mVoiceInputHighlighted;
private InputMethodManager mImm;
private InputMethodManagerCompatWrapper mImm;
private LatinIME mService;
private AlertDialog mVoiceWarningDialog;
private VoiceInput mVoiceInput;
@ -123,7 +123,7 @@ public class VoiceConnector implements VoiceInput.UiListener {
private void initInternal(LatinIME service, SharedPreferences prefs, UIHandler h) {
mService = service;
mHandler = h;
mImm = (InputMethodManager) service.getSystemService(Context.INPUT_METHOD_SERVICE);
mImm = InputMethodManagerCompatWrapper.getInstance(service);
mSubtypeSwitcher = SubtypeSwitcher.getInstance();
if (VOICE_INSTALLED) {
mVoiceInput = new VoiceInput(service, this);

View File

@ -16,6 +16,7 @@
package com.android.inputmethod.keyboard;
import com.android.inputmethod.compat.InputMethodManagerCompatWrapper;
import com.android.inputmethod.latin.LatinIME;
import com.android.inputmethod.latin.LatinImeLogger;
import com.android.inputmethod.latin.R;
@ -29,7 +30,6 @@ import android.content.res.Resources;
import android.util.Log;
import android.view.InflateException;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import java.lang.ref.SoftReference;
import java.util.HashMap;
@ -752,8 +752,7 @@ public class KeyboardSwitcher implements SharedPreferences.OnSharedPreferenceCha
if (settingsKeyMode.equals(resources.getString(SETTINGS_KEY_MODE_ALWAYS_SHOW))
|| (settingsKeyMode.equals(resources.getString(SETTINGS_KEY_MODE_AUTO))
&& Utils.hasMultipleEnabledIMEsOrSubtypes(
((InputMethodManager) context.getSystemService(
Context.INPUT_METHOD_SERVICE))))) {
(InputMethodManagerCompatWrapper.getInstance(context))))) {
return true;
}
return false;

View File

@ -17,6 +17,8 @@
package com.android.inputmethod.latin;
import com.android.inputmethod.compat.CompatUtils;
import com.android.inputmethod.compat.InputMethodManagerCompatWrapper;
import com.android.inputmethod.compat.InputMethodSubtypeCompatWrapper;
import com.android.inputmethod.deprecated.VoiceConnector;
import com.android.inputmethod.keyboard.Keyboard;
import com.android.inputmethod.keyboard.KeyboardActionListener;
@ -67,7 +69,6 @@ import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.ExtractedText;
import android.view.inputmethod.ExtractedTextRequest;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.InputMethodSubtype;
import android.widget.FrameLayout;
import android.widget.HorizontalScrollView;
@ -147,7 +148,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
private AlertDialog mOptionsDialog;
private InputMethodManager mImm;
private InputMethodManagerCompatWrapper mImm;
private Resources mResources;
private SharedPreferences mPrefs;
private String mInputMethodId;
@ -380,7 +381,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
super.onCreate();
mImm = ((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE));
mImm = InputMethodManagerCompatWrapper.getInstance(this);
mInputMethodId = Utils.getInputMethodId(mImm, getPackageName());
mSubtypeSwitcher = SubtypeSwitcher.getInstance();
mKeyboardSwitcher = KeyboardSwitcher.getInstance();
@ -2341,6 +2342,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
@Override
public void onCurrentInputMethodSubtypeChanged(InputMethodSubtype subtype) {
SubtypeSwitcher.getInstance().updateSubtype(subtype);
SubtypeSwitcher.getInstance().updateSubtype(new InputMethodSubtypeCompatWrapper(subtype));
}
}

View File

@ -17,14 +17,13 @@
package com.android.inputmethod.latin;
import com.android.inputmethod.compat.CompatUtils;
import com.android.inputmethod.compat.InputMethodManagerCompatWrapper;
import com.android.inputmethod.deprecated.VoiceConnector;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.backup.BackupManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Vibrator;
@ -40,7 +39,6 @@ import android.text.AutoText;
import android.text.TextUtils;
import android.text.method.LinkMovementMethod;
import android.util.Log;
import android.view.inputmethod.InputMethodManager;
import android.widget.TextView;
import java.util.Locale;
@ -225,8 +223,7 @@ public class Settings extends PreferenceActivity
public boolean onPreferenceClick(Preference pref) {
if (pref == mInputLanguageSelection) {
startActivity(CompatUtils.getInputLanguageSelectionIntent(
Utils.getInputMethodId(
(InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE),
Utils.getInputMethodId(InputMethodManagerCompatWrapper.getInstance(this),
getApplicationInfo().packageName), 0));
return true;
}

View File

@ -16,6 +16,8 @@
package com.android.inputmethod.latin;
import com.android.inputmethod.compat.InputMethodManagerCompatWrapper;
import com.android.inputmethod.compat.InputMethodSubtypeCompatWrapper;
import com.android.inputmethod.deprecated.VoiceConnector;
import com.android.inputmethod.keyboard.KeyboardSwitcher;
import com.android.inputmethod.keyboard.LatinKeyboard;
@ -33,8 +35,6 @@ import android.os.IBinder;
import android.text.TextUtils;
import android.util.Log;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.InputMethodSubtype;
import java.util.ArrayList;
import java.util.Arrays;
@ -57,12 +57,13 @@ public class SubtypeSwitcher {
private static final SubtypeSwitcher sInstance = new SubtypeSwitcher();
private /* final */ LatinIME mService;
private /* final */ SharedPreferences mPrefs;
private /* final */ InputMethodManager mImm;
private /* final */ InputMethodManagerCompatWrapper mImm;
private /* final */ Resources mResources;
private /* final */ ConnectivityManager mConnectivityManager;
private /* final */ boolean mConfigUseSpacebarLanguageSwitcher;
private final ArrayList<InputMethodSubtype> mEnabledKeyboardSubtypesOfCurrentInputMethod =
new ArrayList<InputMethodSubtype>();
private final ArrayList<InputMethodSubtypeCompatWrapper>
mEnabledKeyboardSubtypesOfCurrentInputMethod =
new ArrayList<InputMethodSubtypeCompatWrapper>();
private final ArrayList<String> mEnabledLanguagesOfCurrentInputMethod = new ArrayList<String>();
/*-----------------------------------------------------------*/
@ -70,9 +71,9 @@ public class SubtypeSwitcher {
private boolean mNeedsToDisplayLanguage;
private boolean mIsSystemLanguageSameAsInputLanguage;
private InputMethodInfo mShortcutInputMethodInfo;
private InputMethodSubtype mShortcutSubtype;
private List<InputMethodSubtype> mAllEnabledSubtypesOfCurrentInputMethod;
private InputMethodSubtype mCurrentSubtype;
private InputMethodSubtypeCompatWrapper mShortcutSubtype;
private List<InputMethodSubtypeCompatWrapper> mAllEnabledSubtypesOfCurrentInputMethod;
private InputMethodSubtypeCompatWrapper mCurrentSubtype;
private Locale mSystemLocale;
private Locale mInputLocale;
private String mInputLocaleStr;
@ -100,7 +101,7 @@ public class SubtypeSwitcher {
mService = service;
mPrefs = prefs;
mResources = service.getResources();
mImm = (InputMethodManager) service.getSystemService(Context.INPUT_METHOD_SERVICE);
mImm = InputMethodManagerCompatWrapper.getInstance(service);
mConnectivityManager = (ConnectivityManager) service.getSystemService(
Context.CONNECTIVITY_SERVICE);
mEnabledKeyboardSubtypesOfCurrentInputMethod.clear();
@ -148,7 +149,7 @@ public class SubtypeSwitcher {
null, true);
mEnabledLanguagesOfCurrentInputMethod.clear();
mEnabledKeyboardSubtypesOfCurrentInputMethod.clear();
for (InputMethodSubtype ims: mAllEnabledSubtypesOfCurrentInputMethod) {
for (InputMethodSubtypeCompatWrapper ims: mAllEnabledSubtypesOfCurrentInputMethod) {
final String locale = ims.getLocale();
final String mode = ims.getMode();
mLocaleSplitter.setString(locale);
@ -182,10 +183,10 @@ public class SubtypeSwitcher {
+ ", " + mShortcutSubtype.getMode())));
}
// TODO: Update an icon for shortcut IME
Map<InputMethodInfo, List<InputMethodSubtype>> shortcuts =
Map<InputMethodInfo, List<InputMethodSubtypeCompatWrapper>> shortcuts =
mImm.getShortcutInputMethodsAndSubtypes();
for (InputMethodInfo imi: shortcuts.keySet()) {
List<InputMethodSubtype> subtypes = shortcuts.get(imi);
List<InputMethodSubtypeCompatWrapper> subtypes = shortcuts.get(imi);
// TODO: Returns the first found IMI for now. Should handle all shortcuts as
// appropriate.
mShortcutInputMethodInfo = imi;
@ -204,7 +205,7 @@ public class SubtypeSwitcher {
}
// Update the current subtype. LatinIME.onCurrentInputMethodSubtypeChanged calls this function.
public void updateSubtype(InputMethodSubtype newSubtype) {
public void updateSubtype(InputMethodSubtypeCompatWrapper newSubtype) {
final String newLocale;
final String newMode;
final String oldMode = getCurrentSubtypeMode();
@ -306,7 +307,7 @@ public class SubtypeSwitcher {
return;
}
final String imiId = mShortcutInputMethodInfo.getId();
final InputMethodSubtype subtype = mShortcutSubtype;
final InputMethodSubtypeCompatWrapper subtype = mShortcutSubtype;
new Thread("SwitchToShortcutIME") {
@Override
public void run() {
@ -319,7 +320,7 @@ public class SubtypeSwitcher {
return getSubtypeIcon(mShortcutInputMethodInfo, mShortcutSubtype);
}
private Drawable getSubtypeIcon(InputMethodInfo imi, InputMethodSubtype subtype) {
private Drawable getSubtypeIcon(InputMethodInfo imi, InputMethodSubtypeCompatWrapper subtype) {
final PackageManager pm = mService.getPackageManager();
if (imi != null) {
final String imiPackageName = imi.getPackageName();
@ -359,8 +360,9 @@ public class SubtypeSwitcher {
if (mShortcutSubtype == null)
return true;
final boolean allowsImplicitlySelectedSubtypes = true;
for (final InputMethodSubtype enabledSubtype : mImm.getEnabledInputMethodSubtypeList(
mShortcutInputMethodInfo, allowsImplicitlySelectedSubtypes)) {
for (final InputMethodSubtypeCompatWrapper enabledSubtype :
mImm.getEnabledInputMethodSubtypeList(
mShortcutInputMethodInfo, allowsImplicitlySelectedSubtypes)) {
if (enabledSubtype.equals(mShortcutSubtype))
return true;
}

View File

@ -16,6 +16,7 @@
package com.android.inputmethod.latin;
import com.android.inputmethod.compat.InputMethodManagerCompatWrapper;
import com.android.inputmethod.keyboard.KeyboardId;
import android.content.res.Resources;
@ -29,7 +30,6 @@ import android.text.format.DateUtils;
import android.util.Log;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
import java.io.BufferedReader;
import java.io.File;
@ -101,14 +101,14 @@ public class Utils {
}
}
public static boolean hasMultipleEnabledIMEsOrSubtypes(InputMethodManager imm) {
public static boolean hasMultipleEnabledIMEsOrSubtypes(InputMethodManagerCompatWrapper imm) {
return imm.getEnabledInputMethodList().size() > 1
// imm.getEnabledInputMethodSubtypeList(null, false) will return the current IME's enabled
// input method subtype (The current IME should be LatinIME.)
|| imm.getEnabledInputMethodSubtypeList(null, false).size() > 1;
}
public static String getInputMethodId(InputMethodManager imm, String packageName) {
public static String getInputMethodId(InputMethodManagerCompatWrapper imm, String packageName) {
for (final InputMethodInfo imi : imm.getEnabledInputMethodList()) {
if (imi.getPackageName().equals(packageName))
return imi.getId();