diff options
Diffstat (limited to 'java/src/com/android/inputmethod/compat')
11 files changed, 224 insertions, 221 deletions
diff --git a/java/src/com/android/inputmethod/compat/AudioManagerCompatWrapper.java b/java/src/com/android/inputmethod/compat/AudioManagerCompatWrapper.java deleted file mode 100644 index 40eed91f2..000000000 --- a/java/src/com/android/inputmethod/compat/AudioManagerCompatWrapper.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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.media.AudioManager; - -import java.lang.reflect.Method; - -public final class AudioManagerCompatWrapper { - private static final Method METHOD_isWiredHeadsetOn = CompatUtils.getMethod( - AudioManager.class, "isWiredHeadsetOn"); - private static final Method METHOD_isBluetoothA2dpOn = CompatUtils.getMethod( - AudioManager.class, "isBluetoothA2dpOn"); - - private final AudioManager mManager; - - public AudioManagerCompatWrapper(AudioManager manager) { - mManager = manager; - } - - /** - * Checks whether audio routing to the wired headset is on or off. - * - * @return true if audio is being routed to/from wired headset; - * false if otherwise - */ - public boolean isWiredHeadsetOn() { - return (Boolean) CompatUtils.invoke(mManager, false, METHOD_isWiredHeadsetOn); - } - - /** - * Checks whether A2DP audio routing to the Bluetooth headset is on or off. - * - * @return true if A2DP audio is being routed to/from Bluetooth headset; - * false if otherwise - */ - public boolean isBluetoothA2dpOn() { - return (Boolean) CompatUtils.invoke(mManager, false, METHOD_isBluetoothA2dpOn); - } -} diff --git a/java/src/com/android/inputmethod/compat/CompatUtils.java b/java/src/com/android/inputmethod/compat/CompatUtils.java index ffed6ecb1..660029baf 100644 --- a/java/src/com/android/inputmethod/compat/CompatUtils.java +++ b/java/src/com/android/inputmethod/compat/CompatUtils.java @@ -16,7 +16,6 @@ package com.android.inputmethod.compat; -import android.content.Intent; import android.text.TextUtils; import android.util.Log; @@ -26,26 +25,12 @@ import java.lang.reflect.Method; public final 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 = - "android.settings.INPUT_METHOD_SUBTYPE_SETTINGS"; - public static Intent getInputLanguageSelectionIntent(String inputMethodId, - int flagsForSubtypeSettings) { - // Refer to android.provider.Settings.ACTION_INPUT_METHOD_SUBTYPE_SETTINGS - final String action = INPUT_METHOD_SUBTYPE_SETTINGS; - final Intent intent = new Intent(action); - if (!TextUtils.isEmpty(inputMethodId)) { - intent.putExtra(EXTRA_INPUT_METHOD_ID, inputMethodId); - } - if (flagsForSubtypeSettings > 0) { - intent.setFlags(flagsForSubtypeSettings); - } - return intent; + private CompatUtils() { + // This utility class is not publicly instantiable. } - public static Class<?> getClass(String className) { + public static Class<?> getClass(final String className) { try { return Class.forName(className); } catch (ClassNotFoundException e) { @@ -53,8 +38,8 @@ public final class CompatUtils { } } - public static Method getMethod(Class<?> targetClass, String name, - Class<?>... parameterTypes) { + public static Method getMethod(final Class<?> targetClass, final String name, + final Class<?>... parameterTypes) { if (targetClass == null || TextUtils.isEmpty(name)) return null; try { return targetClass.getMethod(name, parameterTypes); @@ -66,7 +51,7 @@ public final class CompatUtils { return null; } - public static Field getField(Class<?> targetClass, String name) { + public static Field getField(final Class<?> targetClass, final String name) { if (targetClass == null || TextUtils.isEmpty(name)) return null; try { return targetClass.getField(name); @@ -78,7 +63,8 @@ public final class CompatUtils { return null; } - public static Constructor<?> getConstructor(Class<?> targetClass, Class<?> ... types) { + public static Constructor<?> getConstructor(final Class<?> targetClass, + final Class<?> ... types) { if (targetClass == null || types == null) return null; try { return targetClass.getConstructor(types); @@ -90,43 +76,44 @@ public final class CompatUtils { return null; } - public static Object newInstance(Constructor<?> constructor, Object ... args) { + public static Object newInstance(final Constructor<?> constructor, final Object ... args) { if (constructor == null) return null; try { return constructor.newInstance(args); } catch (Exception e) { - Log.e(TAG, "Exception in newInstance: " + e.getClass().getSimpleName()); + Log.e(TAG, "Exception in newInstance", e); } return null; } - public static Object invoke( - Object receiver, Object defaultValue, Method method, Object... args) { + public static Object invoke(final Object receiver, final Object defaultValue, + final Method method, final Object... args) { if (method == null) return defaultValue; try { return method.invoke(receiver, args); } catch (Exception e) { - Log.e(TAG, "Exception in invoke: " + e.getClass().getSimpleName()); + Log.e(TAG, "Exception in invoke", e); } return defaultValue; } - public static Object getFieldValue(Object receiver, Object defaultValue, Field field) { + public static Object getFieldValue(final Object receiver, final Object defaultValue, + final Field field) { if (field == null) return defaultValue; try { return field.get(receiver); } catch (Exception e) { - Log.e(TAG, "Exception in getFieldValue: " + e.getClass().getSimpleName()); + Log.e(TAG, "Exception in getFieldValue", e); } return defaultValue; } - public static void setFieldValue(Object receiver, Field field, Object value) { + public static void setFieldValue(final Object receiver, final Field field, final Object value) { if (field == null) return; try { field.set(receiver, value); } catch (Exception e) { - Log.e(TAG, "Exception in setFieldValue: " + e.getClass().getSimpleName()); + Log.e(TAG, "Exception in setFieldValue", e); } } } diff --git a/java/src/com/android/inputmethod/compat/EditorInfoCompatUtils.java b/java/src/com/android/inputmethod/compat/EditorInfoCompatUtils.java index 210058bec..7eefa221a 100644 --- a/java/src/com/android/inputmethod/compat/EditorInfoCompatUtils.java +++ b/java/src/com/android/inputmethod/compat/EditorInfoCompatUtils.java @@ -21,23 +21,23 @@ import android.view.inputmethod.EditorInfo; import java.lang.reflect.Field; public final class EditorInfoCompatUtils { - // EditorInfo.IME_FLAG_FORCE_ASCII has been introduced since API#16 (JellyBean). + // Note that EditorInfo.IME_FLAG_FORCE_ASCII has been introduced + // in API level 16 (Build.VERSION_CODES.JELLY_BEAN). private static final Field FIELD_IME_FLAG_FORCE_ASCII = CompatUtils.getField( EditorInfo.class, "IME_FLAG_FORCE_ASCII"); - private static final Integer OBJ_IME_FLAG_FORCE_ASCII = (Integer) CompatUtils - .getFieldValue(null, null, FIELD_IME_FLAG_FORCE_ASCII); + private static final Integer OBJ_IME_FLAG_FORCE_ASCII = (Integer) CompatUtils.getFieldValue( + null /* receiver */, null /* defaultValue */, FIELD_IME_FLAG_FORCE_ASCII); private EditorInfoCompatUtils() { // This utility class is not publicly instantiable. } - public static boolean hasFlagForceAscii(int imeOptions) { - if (OBJ_IME_FLAG_FORCE_ASCII == null) - return false; + public static boolean hasFlagForceAscii(final int imeOptions) { + if (OBJ_IME_FLAG_FORCE_ASCII == null) return false; return (imeOptions & OBJ_IME_FLAG_FORCE_ASCII) != 0; } - public static String imeActionName(int imeOptions) { + public static String imeActionName(final int imeOptions) { final int actionId = imeOptions & EditorInfo.IME_MASK_ACTION; switch (actionId) { case EditorInfo.IME_ACTION_UNSPECIFIED: @@ -61,7 +61,7 @@ public final class EditorInfoCompatUtils { } } - public static String imeOptionsName(int imeOptions) { + public static String imeOptionsName(final int imeOptions) { final String action = imeActionName(imeOptions); final StringBuilder flags = new StringBuilder(); if ((imeOptions & EditorInfo.IME_FLAG_NO_ENTER_ACTION) != 0) { diff --git a/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java b/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java index ab7bd4914..a80c3fefe 100644 --- a/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java +++ b/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java @@ -19,61 +19,23 @@ package com.android.inputmethod.compat; import android.content.Context; import android.os.IBinder; import android.view.inputmethod.InputMethodManager; -import android.view.inputmethod.InputMethodSubtype; - -import com.android.inputmethod.latin.ImfUtils; 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 InputMethodManagerCompatWrapper { - private static final String TAG = InputMethodManagerCompatWrapper.class.getSimpleName(); + // Note that InputMethodManager.switchToNextInputMethod() has been introduced + // in API level 16 (Build.VERSION_CODES.JELLY_BEAN). private static final Method METHOD_switchToNextInputMethod = CompatUtils.getMethod( InputMethodManager.class, "switchToNextInputMethod", IBinder.class, Boolean.TYPE); - private static final InputMethodManagerCompatWrapper sInstance = - new InputMethodManagerCompatWrapper(); - - private InputMethodManager mImm; - - private InputMethodManagerCompatWrapper() { - // This wrapper class is not publicly instantiable. - } - - public static InputMethodManagerCompatWrapper getInstance() { - if (sInstance.mImm == null) { - throw new RuntimeException(TAG + ".getInstance() is called before initialization"); - } - return sInstance; - } - - public static void init(Context context) { - sInstance.mImm = ImfUtils.getInputMethodManager(context); - } - - public InputMethodSubtype getCurrentInputMethodSubtype() { - return mImm.getCurrentInputMethodSubtype(); - } - - public InputMethodSubtype getLastInputMethodSubtype() { - return mImm.getLastInputMethodSubtype(); - } - - public boolean switchToLastInputMethod(IBinder token) { - return mImm.switchToLastInputMethod(token); - } - - public boolean switchToNextInputMethod(IBinder token, boolean onlyCurrentIme) { - return (Boolean)CompatUtils.invoke(mImm, false, METHOD_switchToNextInputMethod, token, - onlyCurrentIme); - } + public final InputMethodManager mImm; - public void setInputMethodAndSubtype(IBinder token, String id, InputMethodSubtype subtype) { - mImm.setInputMethodAndSubtype(token, id, subtype); + public InputMethodManagerCompatWrapper(final Context context) { + mImm = (InputMethodManager)context.getSystemService(Context.INPUT_METHOD_SERVICE); } - public void showInputMethodPicker() { - mImm.showInputMethodPicker(); + public boolean switchToNextInputMethod(final IBinder token, final boolean onlyCurrentIme) { + return (Boolean)CompatUtils.invoke(mImm, false /* defaultValue */, + METHOD_switchToNextInputMethod, token, onlyCurrentIme); } } diff --git a/java/src/com/android/inputmethod/compat/InputMethodServiceCompatUtils.java b/java/src/com/android/inputmethod/compat/InputMethodServiceCompatUtils.java index 8eea31ed2..14ee654f3 100644 --- a/java/src/com/android/inputmethod/compat/InputMethodServiceCompatUtils.java +++ b/java/src/com/android/inputmethod/compat/InputMethodServiceCompatUtils.java @@ -21,6 +21,8 @@ import android.inputmethodservice.InputMethodService; import java.lang.reflect.Method; public final class InputMethodServiceCompatUtils { + // Note that InputMethodService.enableHardwareAcceleration() has been introduced + // in API level 17 (Build.VERSION_CODES.JELLY_BEAN_MR1). private static final Method METHOD_enableHardwareAcceleration = CompatUtils.getMethod(InputMethodService.class, "enableHardwareAcceleration"); @@ -28,7 +30,8 @@ public final class InputMethodServiceCompatUtils { // This utility class is not publicly instantiable. } - public static boolean enableHardwareAcceleration(InputMethodService ims) { - return (Boolean)CompatUtils.invoke(ims, false, METHOD_enableHardwareAcceleration); + public static boolean enableHardwareAcceleration(final InputMethodService ims) { + return (Boolean)CompatUtils.invoke(ims, false /* defaultValue */, + METHOD_enableHardwareAcceleration); } } diff --git a/java/src/com/android/inputmethod/compat/IntentCompatUtils.java b/java/src/com/android/inputmethod/compat/IntentCompatUtils.java new file mode 100644 index 000000000..df2e22fe8 --- /dev/null +++ b/java/src/com/android/inputmethod/compat/IntentCompatUtils.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2013 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.Intent; + +public final class IntentCompatUtils { + // Note that Intent.ACTION_USER_INITIALIZE have been introduced in API level 17 + // (Build.VERSION_CODE.JELLY_BEAN_MR1). + public static final String ACTION_USER_INITIALIZE = + (String)CompatUtils.getFieldValue(null, null, + CompatUtils.getField(Intent.class, "ACTION_USER_INITIALIZE")); + + private IntentCompatUtils() { + // This utility class is not publicly instantiable. + } + + public static boolean has_ACTION_USER_INITIALIZE(final Intent intent) { + return ACTION_USER_INITIALIZE != null && intent != null + && ACTION_USER_INITIALIZE.equals(intent.getAction()); + } +} diff --git a/java/src/com/android/inputmethod/compat/SettingsSecureCompatUtils.java b/java/src/com/android/inputmethod/compat/SettingsSecureCompatUtils.java index db5abd0fe..cfaf7ec77 100644 --- a/java/src/com/android/inputmethod/compat/SettingsSecureCompatUtils.java +++ b/java/src/com/android/inputmethod/compat/SettingsSecureCompatUtils.java @@ -19,6 +19,8 @@ package com.android.inputmethod.compat; import java.lang.reflect.Field; public final class SettingsSecureCompatUtils { + // Note that Settings.Secure.ACCESSIBILITY_SPEAK_PASSWORD has been introduced + // in API level 15 (Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1). private static final Field FIELD_ACCESSIBILITY_SPEAK_PASSWORD = CompatUtils.getField( android.provider.Settings.Secure.class, "ACCESSIBILITY_SPEAK_PASSWORD"); @@ -30,5 +32,5 @@ public final class SettingsSecureCompatUtils { * Whether to speak passwords while in accessibility mode. */ public static final String ACCESSIBILITY_SPEAK_PASSWORD = (String) CompatUtils.getFieldValue( - null, null, FIELD_ACCESSIBILITY_SPEAK_PASSWORD); + null /* receiver */, null /* defaultValue */, FIELD_ACCESSIBILITY_SPEAK_PASSWORD); } diff --git a/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java b/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java index 159f43650..141e08a8d 100644 --- a/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java +++ b/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java @@ -21,58 +21,29 @@ import android.text.Spannable; import android.text.SpannableString; import android.text.Spanned; import android.text.TextUtils; -import android.util.Log; +import android.text.style.SuggestionSpan; import com.android.inputmethod.latin.CollectionUtils; import com.android.inputmethod.latin.LatinImeLogger; import com.android.inputmethod.latin.SuggestedWords; import com.android.inputmethod.latin.SuggestionSpanPickedNotificationReceiver; -import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.util.ArrayList; -import java.util.Locale; public final class SuggestionSpanUtils { private static final String TAG = SuggestionSpanUtils.class.getSimpleName(); - // TODO: Use reflection to get field values - public static final String ACTION_SUGGESTION_PICKED = - "android.text.style.SUGGESTION_PICKED"; - public static final String SUGGESTION_SPAN_PICKED_AFTER = "after"; - public static final String SUGGESTION_SPAN_PICKED_BEFORE = "before"; - public static final String SUGGESTION_SPAN_PICKED_HASHCODE = "hashcode"; - public static final boolean SUGGESTION_SPAN_IS_SUPPORTED; - private static final Class<?> CLASS_SuggestionSpan = CompatUtils - .getClass("android.text.style.SuggestionSpan"); - private static final Class<?>[] INPUT_TYPE_SuggestionSpan = new Class<?>[] { - Context.class, Locale.class, String[].class, int.class, Class.class }; - private static final Constructor<?> CONSTRUCTOR_SuggestionSpan = CompatUtils - .getConstructor(CLASS_SuggestionSpan, INPUT_TYPE_SuggestionSpan); - public static final Field FIELD_FLAG_EASY_CORRECT = - CompatUtils.getField(CLASS_SuggestionSpan, "FLAG_EASY_CORRECT"); - public static final Field FIELD_FLAG_MISSPELLED = - CompatUtils.getField(CLASS_SuggestionSpan, "FLAG_MISSPELLED"); - public static final Field FIELD_FLAG_AUTO_CORRECTION = - CompatUtils.getField(CLASS_SuggestionSpan, "FLAG_AUTO_CORRECTION"); - public static final Field FIELD_SUGGESTIONS_MAX_SIZE - = CompatUtils.getField(CLASS_SuggestionSpan, "SUGGESTIONS_MAX_SIZE"); - public static final Integer OBJ_FLAG_EASY_CORRECT = (Integer) CompatUtils - .getFieldValue(null, null, FIELD_FLAG_EASY_CORRECT); - public static final Integer OBJ_FLAG_MISSPELLED = (Integer) CompatUtils - .getFieldValue(null, null, FIELD_FLAG_MISSPELLED); - public static final Integer OBJ_FLAG_AUTO_CORRECTION = (Integer) CompatUtils - .getFieldValue(null, null, FIELD_FLAG_AUTO_CORRECTION); - public static final Integer OBJ_SUGGESTIONS_MAX_SIZE = (Integer) CompatUtils - .getFieldValue(null, null, FIELD_SUGGESTIONS_MAX_SIZE); + // Note that SuggestionSpan.FLAG_AUTO_CORRECTION has been introduced + // in API level 15 (Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1). + public static final Field FIELD_FLAG_AUTO_CORRECTION = CompatUtils.getField( + SuggestionSpan.class, "FLAG_AUTO_CORRECTION"); + public static final Integer OBJ_FLAG_AUTO_CORRECTION = (Integer) CompatUtils.getFieldValue( + null /* receiver */, null /* defaultValue */, FIELD_FLAG_AUTO_CORRECTION); static { - SUGGESTION_SPAN_IS_SUPPORTED = - CLASS_SuggestionSpan != null && CONSTRUCTOR_SuggestionSpan != null; if (LatinImeLogger.sDBG) { - if (SUGGESTION_SPAN_IS_SUPPORTED - && (OBJ_FLAG_AUTO_CORRECTION == null || OBJ_SUGGESTIONS_MAX_SIZE == null - || OBJ_FLAG_MISSPELLED == null || OBJ_FLAG_EASY_CORRECT == null)) { + if (OBJ_FLAG_AUTO_CORRECTION == null) { throw new RuntimeException("Field is accidentially null."); } } @@ -83,49 +54,34 @@ public final class SuggestionSpanUtils { } public static CharSequence getTextWithAutoCorrectionIndicatorUnderline( - Context context, CharSequence text) { - if (TextUtils.isEmpty(text) || CONSTRUCTOR_SuggestionSpan == null - || OBJ_FLAG_AUTO_CORRECTION == null || OBJ_SUGGESTIONS_MAX_SIZE == null - || OBJ_FLAG_MISSPELLED == null || OBJ_FLAG_EASY_CORRECT == null) { + final Context context, final String text) { + if (TextUtils.isEmpty(text) || OBJ_FLAG_AUTO_CORRECTION == null) { return text; } - final Spannable spannable = text instanceof Spannable - ? (Spannable) text : new SpannableString(text); - final Object[] args = - { context, null, new String[] {}, (int)OBJ_FLAG_AUTO_CORRECTION, - (Class<?>) SuggestionSpanPickedNotificationReceiver.class }; - final Object ss = CompatUtils.newInstance(CONSTRUCTOR_SuggestionSpan, args); - if (ss == null) { - Log.w(TAG, "Suggestion span was not created."); - return text; - } - spannable.setSpan(ss, 0, text.length(), + final Spannable spannable = new SpannableString(text); + final SuggestionSpan suggestionSpan = new SuggestionSpan(context, null /* locale */, + new String[] {} /* suggestions */, (int)OBJ_FLAG_AUTO_CORRECTION, + SuggestionSpanPickedNotificationReceiver.class); + spannable.setSpan(suggestionSpan, 0, text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE | Spanned.SPAN_COMPOSING); return spannable; } - public static CharSequence getTextWithSuggestionSpan(Context context, - CharSequence pickedWord, SuggestedWords suggestedWords, boolean dictionaryAvailable) { - if (!dictionaryAvailable || TextUtils.isEmpty(pickedWord) - || CONSTRUCTOR_SuggestionSpan == null - || suggestedWords == null || suggestedWords.size() == 0 - || suggestedWords.mIsPrediction || suggestedWords.mIsPunctuationSuggestions - || OBJ_SUGGESTIONS_MAX_SIZE == null) { + public static CharSequence getTextWithSuggestionSpan(final Context context, + final String pickedWord, final SuggestedWords suggestedWords, + final boolean dictionaryAvailable) { + if (!dictionaryAvailable || TextUtils.isEmpty(pickedWord) || suggestedWords.isEmpty() + || suggestedWords.mIsPrediction || suggestedWords.mIsPunctuationSuggestions) { return pickedWord; } - final Spannable spannable; - if (pickedWord instanceof Spannable) { - spannable = (Spannable) pickedWord; - } else { - spannable = new SpannableString(pickedWord); - } + final Spannable spannable = new SpannableString(pickedWord); final ArrayList<String> suggestionsList = CollectionUtils.newArrayList(); for (int i = 0; i < suggestedWords.size(); ++i) { - if (suggestionsList.size() >= OBJ_SUGGESTIONS_MAX_SIZE) { + if (suggestionsList.size() >= SuggestionSpan.SUGGESTIONS_MAX_SIZE) { break; } - final CharSequence word = suggestedWords.getWord(i); + final String word = suggestedWords.getWord(i); if (!TextUtils.equals(pickedWord, word)) { suggestionsList.add(word.toString()); } @@ -133,14 +89,10 @@ public final class SuggestionSpanUtils { // TODO: We should avoid adding suggestion span candidates that came from the bigram // prediction. - final Object[] args = - { context, null, suggestionsList.toArray(new String[suggestionsList.size()]), 0, - (Class<?>) SuggestionSpanPickedNotificationReceiver.class }; - final Object ss = CompatUtils.newInstance(CONSTRUCTOR_SuggestionSpan, args); - if (ss == null) { - return pickedWord; - } - spannable.setSpan(ss, 0, pickedWord.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + final SuggestionSpan suggestionSpan = new SuggestionSpan(context, null /* locale */, + suggestionsList.toArray(new String[suggestionsList.size()]), 0 /* flags */, + SuggestionSpanPickedNotificationReceiver.class); + spannable.setSpan(suggestionSpan, 0, pickedWord.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); return spannable; } } diff --git a/java/src/com/android/inputmethod/compat/SuggestionsInfoCompatUtils.java b/java/src/com/android/inputmethod/compat/SuggestionsInfoCompatUtils.java index 8314212c9..d8d2be04c 100644 --- a/java/src/com/android/inputmethod/compat/SuggestionsInfoCompatUtils.java +++ b/java/src/com/android/inputmethod/compat/SuggestionsInfoCompatUtils.java @@ -21,10 +21,13 @@ import android.view.textservice.SuggestionsInfo; import java.lang.reflect.Field; public final class SuggestionsInfoCompatUtils { - private static final Field FIELD_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS = CompatUtils.getField( - SuggestionsInfo.class, "RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS"); - private static final Integer OBJ_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS = (Integer) CompatUtils - .getFieldValue(null, null, FIELD_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS); + // Note that SuggestionsInfo.RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS has been introduced + // in API level 15 (Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1). + private static final Field FIELD_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS = + CompatUtils.getField(SuggestionsInfo.class, "RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS"); + private static final Integer OBJ_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS = + (Integer) CompatUtils.getFieldValue(null /* receiver */, null /* defaultValue */, + FIELD_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS); private static final int RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS = OBJ_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS != null ? OBJ_RESULT_ATTR_HAS_RECOMMENDED_SUGGESTIONS : 0; diff --git a/java/src/com/android/inputmethod/compat/TextViewCompatUtils.java b/java/src/com/android/inputmethod/compat/TextViewCompatUtils.java new file mode 100644 index 000000000..d4f1ea830 --- /dev/null +++ b/java/src/com/android/inputmethod/compat/TextViewCompatUtils.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2013 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.graphics.drawable.Drawable; +import android.widget.TextView; + +import java.lang.reflect.Method; + +public final class TextViewCompatUtils { + // Note that TextView.setCompoundDrawablesRelative(Drawable,Drawable,Drawable,Drawable) has + // been introduced in API level 17 (Build.VERSION_CODE.JELLY_BEAN_MR1). + private static final Method METHOD_setCompoundDrawablesRelative = CompatUtils.getMethod( + TextView.class, "setCompoundDrawablesRelative", + Drawable.class, Drawable.class, Drawable.class, Drawable.class); + + private TextViewCompatUtils() { + // This utility class is not publicly instantiable. + } + + public static void setCompoundDrawablesRelative(final TextView textView, final Drawable start, + final Drawable top, final Drawable end, final Drawable bottom) { + if (METHOD_setCompoundDrawablesRelative == null) { + textView.setCompoundDrawables(start, top, end, bottom); + return; + } + CompatUtils.invoke(textView, null, METHOD_setCompoundDrawablesRelative, + start, top, end, bottom); + } +} diff --git a/java/src/com/android/inputmethod/compat/ViewCompatUtils.java b/java/src/com/android/inputmethod/compat/ViewCompatUtils.java new file mode 100644 index 000000000..a8fab8855 --- /dev/null +++ b/java/src/com/android/inputmethod/compat/ViewCompatUtils.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2013 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.view.View; + +import java.lang.reflect.Method; + +public final class ViewCompatUtils { + // Note that View.LAYOUT_DIRECTION_LTR and View.LAYOUT_DIRECTION_RTL have been introduced in + // API level 17 (Build.VERSION_CODE.JELLY_BEAN_MR1). + public static final int LAYOUT_DIRECTION_LTR = (Integer)CompatUtils.getFieldValue(null, 0x0, + CompatUtils.getField(View.class, "LAYOUT_DIRECTION_LTR")); + public static final int LAYOUT_DIRECTION_RTL = (Integer)CompatUtils.getFieldValue(null, 0x1, + CompatUtils.getField(View.class, "LAYOUT_DIRECTION_RTL")); + + // Note that View.getPaddingEnd(), View.setPaddingRelative(int,int,int,int), and + // View.getLayoutDirection() have been introduced in API level 17 + // (Build.VERSION_CODE.JELLY_BEAN_MR1). + private static final Method METHOD_getPaddingEnd = CompatUtils.getMethod( + View.class, "getPaddingEnd"); + private static final Method METHOD_setPaddingRelative = CompatUtils.getMethod( + View.class, "setPaddingRelative", + Integer.TYPE, Integer.TYPE, Integer.TYPE, Integer.TYPE); + private static final Method METHOD_getLayoutDirection = CompatUtils.getMethod( + View.class, "getLayoutDirection"); + + private ViewCompatUtils() { + // This utility class is not publicly instantiable. + } + + public static int getPaddingEnd(final View view) { + if (METHOD_getPaddingEnd == null) { + return view.getPaddingRight(); + } + return (Integer)CompatUtils.invoke(view, 0, METHOD_getPaddingEnd); + } + + public static void setPaddingRelative(final View view, final int start, final int top, + final int end, final int bottom) { + if (METHOD_setPaddingRelative == null) { + view.setPadding(start, top, end, bottom); + return; + } + CompatUtils.invoke(view, null, METHOD_setPaddingRelative, start, top, end, bottom); + } + + public static int getLayoutDirection(final View view) { + if (METHOD_getLayoutDirection == null) { + return LAYOUT_DIRECTION_LTR; + } + return (Integer)CompatUtils.invoke(view, 0, METHOD_getLayoutDirection); + } +} |