diff options
author | satok <satok@google.com> | 2011-08-03 17:36:14 +0900 |
---|---|---|
committer | satok <satok@google.com> | 2011-08-08 19:29:26 +0900 |
commit | 03b2ea1102d9e3e9f189173878706ab04533eea3 (patch) | |
tree | af4cb040c8fda99e7993b53c3acc412ce1ff23ca /core | |
parent | 7d608423b721e0153f37bfd5eba78fcd2489562d (diff) | |
download | frameworks_base-03b2ea1102d9e3e9f189173878706ab04533eea3.zip frameworks_base-03b2ea1102d9e3e9f189173878706ab04533eea3.tar.gz frameworks_base-03b2ea1102d9e3e9f189173878706ab04533eea3.tar.bz2 |
Support xml configuration file for the spell checker and add the spell checker subtype
Change-Id: I74715855525fc0a1282238d593ad37aefd42bfc3
Diffstat (limited to 'core')
-rw-r--r-- | core/java/android/view/textservice/SpellCheckerInfo.java | 134 | ||||
-rw-r--r-- | core/java/android/view/textservice/SpellCheckerSubtype.aidl | 19 | ||||
-rw-r--r-- | core/java/android/view/textservice/SpellCheckerSubtype.java | 159 | ||||
-rwxr-xr-x | core/res/res/values/attrs.xml | 28 | ||||
-rw-r--r-- | core/res/res/values/public.xml | 3 |
5 files changed, 340 insertions, 3 deletions
diff --git a/core/java/android/view/textservice/SpellCheckerInfo.java b/core/java/android/view/textservice/SpellCheckerInfo.java index d88a39f..89cb11c 100644 --- a/core/java/android/view/textservice/SpellCheckerInfo.java +++ b/core/java/android/view/textservice/SpellCheckerInfo.java @@ -16,30 +16,122 @@ package android.view.textservice; +import org.xmlpull.v1.XmlPullParser; +import org.xmlpull.v1.XmlPullParserException; + import android.content.ComponentName; import android.content.Context; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; +import android.content.pm.PackageManager.NameNotFoundException; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.content.res.XmlResourceParser; import android.graphics.drawable.Drawable; import android.os.Parcel; import android.os.Parcelable; +import android.util.AttributeSet; +import android.util.Slog; +import android.util.Xml; + +import java.io.IOException; +import java.util.ArrayList; /** * This class is used to specify meta information of an spell checker. */ public final class SpellCheckerInfo implements Parcelable { + private static final String TAG = SpellCheckerInfo.class.getSimpleName(); private final ResolveInfo mService; private final String mId; + private final int mLabel; + + /** + * The spell checker setting activity's name, used by the system settings to + * launch the setting activity. + */ + private final String mSettingsActivityName; + + /** + * The array of the subtypes. + */ + private final ArrayList<SpellCheckerSubtype> mSubtypes = new ArrayList<SpellCheckerSubtype>(); /** * Constructor. * @hide */ - public SpellCheckerInfo(Context context, ResolveInfo service) { + public SpellCheckerInfo(Context context, ResolveInfo service) + throws XmlPullParserException, IOException { mService = service; ServiceInfo si = service.serviceInfo; mId = new ComponentName(si.packageName, si.name).flattenToShortString(); + + final PackageManager pm = context.getPackageManager(); + int label = 0; + String settingsActivityComponent = null; + int isDefaultResId = 0; + + XmlResourceParser parser = null; + try { + parser = si.loadXmlMetaData(pm, SpellCheckerSession.SERVICE_META_DATA); + if (parser == null) { + throw new XmlPullParserException("No " + + SpellCheckerSession.SERVICE_META_DATA + " meta-data"); + } + + final Resources res = pm.getResourcesForApplication(si.applicationInfo); + final AttributeSet attrs = Xml.asAttributeSet(parser); + int type; + while ((type=parser.next()) != XmlPullParser.END_DOCUMENT + && type != XmlPullParser.START_TAG) { + } + + final String nodeName = parser.getName(); + if (!"spell-checker".equals(nodeName)) { + throw new XmlPullParserException( + "Meta-data does not start with spell-checker tag"); + } + + TypedArray sa = res.obtainAttributes(attrs, + com.android.internal.R.styleable.SpellChecker); + label = sa.getResourceId(com.android.internal.R.styleable.SpellChecker_label, 0); + settingsActivityComponent = sa.getString( + com.android.internal.R.styleable.SpellChecker_settingsActivity); + sa.recycle(); + + final int depth = parser.getDepth(); + // Parse all subtypes + while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth) + && type != XmlPullParser.END_DOCUMENT) { + if (type == XmlPullParser.START_TAG) { + final String subtypeNodeName = parser.getName(); + if (!"subtype".equals(subtypeNodeName)) { + throw new XmlPullParserException( + "Meta-data in spell-checker does not start with subtype tag"); + } + final TypedArray a = res.obtainAttributes( + attrs, com.android.internal.R.styleable.SpellChecker_Subtype); + SpellCheckerSubtype subtype = new SpellCheckerSubtype( + a.getResourceId(com.android.internal.R.styleable + .SpellChecker_Subtype_label, 0), + a.getString(com.android.internal.R.styleable + .SpellChecker_Subtype_subtypeLocale), + a.getString(com.android.internal.R.styleable + .SpellChecker_Subtype_subtypeExtraValue)); + mSubtypes.add(subtype); + } + } + } catch (Exception e) { + Slog.e(TAG, "Caught exception: " + e); + throw new XmlPullParserException( + "Unable to create context for: " + si.packageName); + } finally { + if (parser != null) parser.close(); + } + mLabel = label; + mSettingsActivityName = settingsActivityComponent; } /** @@ -47,8 +139,11 @@ public final class SpellCheckerInfo implements Parcelable { * @hide */ public SpellCheckerInfo(Parcel source) { + mLabel = source.readInt(); mId = source.readString(); + mSettingsActivityName = source.readString(); mService = ResolveInfo.CREATOR.createFromParcel(source); + source.readTypedList(mSubtypes, SpellCheckerSubtype.CREATOR); } /** @@ -69,7 +164,7 @@ public final class SpellCheckerInfo implements Parcelable { } /** - * Return the .apk package that implements this input method. + * Return the .apk package that implements this. */ public String getPackageName() { return mService.serviceInfo.packageName; @@ -83,8 +178,11 @@ public final class SpellCheckerInfo implements Parcelable { */ @Override public void writeToParcel(Parcel dest, int flags) { + dest.writeInt(mLabel); dest.writeString(mId); + dest.writeString(mSettingsActivityName); mService.writeToParcel(dest, flags); + dest.writeTypedList(mSubtypes); } @@ -110,7 +208,8 @@ public final class SpellCheckerInfo implements Parcelable { * @param pm Supply a PackageManager used to load the spell checker's resources. */ public CharSequence loadLabel(PackageManager pm) { - return mService.loadLabel(pm); + if (mLabel == 0 || pm == null) return ""; + return pm.getText(getPackageName(), mLabel, mService.serviceInfo.applicationInfo); } /** @@ -123,6 +222,35 @@ public final class SpellCheckerInfo implements Parcelable { } /** + * Return the class name of an activity that provides a settings UI. + * You can launch this activity be starting it with + * an {@link android.content.Intent} whose action is MAIN and with an + * explicit {@link android.content.ComponentName} + * composed of {@link #getPackageName} and the class name returned here. + * + * <p>A null will be returned if there is no settings activity. + */ + public String getSettingsActivity() { + return mSettingsActivityName; + } + + /** + * Return the count of the subtypes. + */ + public int getSubtypeCount() { + return mSubtypes.size(); + } + + /** + * Return the subtype at the specified index. + * + * @param index the index of the subtype to return. + */ + public SpellCheckerSubtype getSubtypeAt(int index) { + return mSubtypes.get(index); + } + + /** * Used to make this class parcelable. */ @Override diff --git a/core/java/android/view/textservice/SpellCheckerSubtype.aidl b/core/java/android/view/textservice/SpellCheckerSubtype.aidl new file mode 100644 index 0000000..1c790e7 --- /dev/null +++ b/core/java/android/view/textservice/SpellCheckerSubtype.aidl @@ -0,0 +1,19 @@ +/* + * 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 android.view.textservice; + +parcelable SpellCheckerSubtype; diff --git a/core/java/android/view/textservice/SpellCheckerSubtype.java b/core/java/android/view/textservice/SpellCheckerSubtype.java new file mode 100644 index 0000000..dbd3081 --- /dev/null +++ b/core/java/android/view/textservice/SpellCheckerSubtype.java @@ -0,0 +1,159 @@ +/* + * 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 android.view.textservice; + +import android.content.Context; +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; + +/** + * This class is used to specify meta information of a subtype contained in a spell checker. + * Subtype can describe locale (e.g. en_US, fr_FR...) used for settings. + */ +public final class SpellCheckerSubtype implements Parcelable { + + private final int mSubtypeHashCode; + private final int mSubtypeNameResId; + private final String mSubtypeLocale; + private final String mSubtypeExtraValue; + + /** + * Constructor + * @param nameId The name of the subtype + * @param locale The locale supported by the subtype + * @param extraValue The extra value of the subtype + */ + public SpellCheckerSubtype(int nameId, String locale, String extraValue) { + mSubtypeNameResId = nameId; + mSubtypeLocale = locale != null ? locale : ""; + mSubtypeExtraValue = extraValue != null ? extraValue : ""; + mSubtypeHashCode = hashCodeInternal(mSubtypeLocale, mSubtypeExtraValue); + } + + SpellCheckerSubtype(Parcel source) { + String s; + mSubtypeNameResId = source.readInt(); + s = source.readString(); + mSubtypeLocale = s != null ? s : ""; + s = source.readString(); + mSubtypeExtraValue = s != null ? s : ""; + mSubtypeHashCode = hashCodeInternal(mSubtypeLocale, mSubtypeExtraValue); + } + + /** + * @return the name of the subtype + */ + public int getNameResId() { + return mSubtypeNameResId; + } + + /** + * @return the locale of the subtype + */ + public String getLocale() { + return mSubtypeLocale; + } + + /** + * @return the extra value of the subtype + */ + public String getExtraValue() { + return mSubtypeExtraValue; + } + + @Override + public int hashCode() { + return mSubtypeHashCode; + } + + @Override + public boolean equals(Object o) { + if (o instanceof SpellCheckerSubtype) { + SpellCheckerSubtype subtype = (SpellCheckerSubtype) o; + return (subtype.hashCode() == hashCode()) + && (subtype.getNameResId() == getNameResId()) + && (subtype.getLocale().equals(getLocale())) + && (subtype.getExtraValue().equals(getExtraValue())); + } + return false; + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int parcelableFlags) { + dest.writeInt(mSubtypeNameResId); + dest.writeString(mSubtypeLocale); + dest.writeString(mSubtypeExtraValue); + } + + public static final Parcelable.Creator<SpellCheckerSubtype> CREATOR + = new Parcelable.Creator<SpellCheckerSubtype>() { + @Override + public SpellCheckerSubtype createFromParcel(Parcel source) { + return new SpellCheckerSubtype(source); + } + + @Override + public SpellCheckerSubtype[] newArray(int size) { + return new SpellCheckerSubtype[size]; + } + }; + + private static int hashCodeInternal(String locale, String extraValue) { + return Arrays.hashCode(new Object[] {locale, extraValue}); + } + + /** + * Sort the list of subtypes + * @param context Context will be used for getting localized strings + * @param flags Flags for the sort order + * @param sci SpellCheckerInfo of which subtypes are subject to be sorted + * @param subtypeList List which will be sorted + * @return Sorted list of subtypes + * @hide + */ + public static List<SpellCheckerSubtype> sort(Context context, int flags, SpellCheckerInfo sci, + List<SpellCheckerSubtype> subtypeList) { + if (sci == null) return subtypeList; + final HashSet<SpellCheckerSubtype> subtypesSet = new HashSet<SpellCheckerSubtype>( + subtypeList); + final ArrayList<SpellCheckerSubtype> sortedList = new ArrayList<SpellCheckerSubtype>(); + int N = sci.getSubtypeCount(); + for (int i = 0; i < N; ++i) { + SpellCheckerSubtype subtype = sci.getSubtypeAt(i); + if (subtypesSet.contains(subtype)) { + sortedList.add(subtype); + subtypesSet.remove(subtype); + } + } + // If subtypes in subtypesSet remain, that means these subtypes are not + // contained in sci, so the remaining subtypes will be appended. + for (SpellCheckerSubtype subtype: subtypesSet) { + sortedList.add(subtype); + } + return sortedList; + } +} diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml index eed41ea..63b49bd 100755 --- a/core/res/res/values/attrs.xml +++ b/core/res/res/values/attrs.xml @@ -2224,6 +2224,34 @@ <attr name="imeSubtypeExtraValue" format="string" /> </declare-styleable> + <!-- Use <code>spell-checker</code> as the root tag of the XML resource that + describes an + {@link android.service.textservice.SpellCheckerService} service, which is + referenced from its + {@link android.view.textservice.SpellCheckerSession#SERVICE_META_DATA} + meta-data entry. Described here are the attributes that can be + included in that tag. --> + <declare-styleable name="SpellChecker"> + <!-- The name of the spell checker. --> + <attr name="label" /> + <!-- Component name of an activity that allows the user to modify + the settings for this service. --> + <attr name="settingsActivity"/> + </declare-styleable> + + <!-- This is the subtype of the spell checker. Subtype can describe locales (e.g. en_US, fr_FR...) --> + <declare-styleable name="SpellChecker_Subtype"> + <!-- The name of the subtype. --> + <attr name="label" /> + <!-- The locale of the subtype. This string should be a locale (e.g. en_US, fr_FR...) + This is also used by the framework to know the supported locales + of the spell checker. --> + <attr name="subtypeLocale" format="string" /> + <!-- The extra value of the subtype. This string can be any string and will be passed to + the SpellChecker. --> + <attr name="subtypeExtraValue" format="string" /> + </declare-styleable> + <!-- Use <code>accessibility-service</code> as the root tag of the XML resource that describes an {@link android.accessibilityservice.AccessibilityService} service, which is referenced from its diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml index f85dd85..1ba54cf 100644 --- a/core/res/res/values/public.xml +++ b/core/res/res/values/public.xml @@ -1785,6 +1785,9 @@ <public type="attr" name="actionBarWidgetTheme" /> <public type="attr" name="uiOptions" /> + <public type="attr" name="subtypeLocale" /> + <public type="attr" name="subtypeExtraValue" /> + <public type="style" name="TextAppearance.SuggestionHighlight" /> <public type="style" name="Theme.Holo.Light.DarkActionBar" /> |