summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorsatok <satok@google.com>2011-08-03 17:36:14 +0900
committersatok <satok@google.com>2011-08-08 19:29:26 +0900
commit03b2ea1102d9e3e9f189173878706ab04533eea3 (patch)
treeaf4cb040c8fda99e7993b53c3acc412ce1ff23ca /core
parent7d608423b721e0153f37bfd5eba78fcd2489562d (diff)
downloadframeworks_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.java134
-rw-r--r--core/java/android/view/textservice/SpellCheckerSubtype.aidl19
-rw-r--r--core/java/android/view/textservice/SpellCheckerSubtype.java159
-rwxr-xr-xcore/res/res/values/attrs.xml28
-rw-r--r--core/res/res/values/public.xml3
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" />