blob: 471b6d4322f73b33b1bcdace5f745d84e95cf601 [file] [log] [blame]
satok988323c2011-06-22 16:38:13 +09001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License. You may obtain a copy of
6 * the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations under
14 * the License.
15 */
16
17package android.view.textservice;
18
satok03b2ea12011-08-03 17:36:14 +090019import org.xmlpull.v1.XmlPullParser;
20import org.xmlpull.v1.XmlPullParserException;
21
satok988323c2011-06-22 16:38:13 +090022import android.content.ComponentName;
23import android.content.Context;
satok562ab582011-07-25 10:12:21 +090024import android.content.pm.PackageManager;
satok988323c2011-06-22 16:38:13 +090025import android.content.pm.ResolveInfo;
26import android.content.pm.ServiceInfo;
satok03b2ea12011-08-03 17:36:14 +090027import android.content.res.Resources;
28import android.content.res.TypedArray;
29import android.content.res.XmlResourceParser;
satok562ab582011-07-25 10:12:21 +090030import android.graphics.drawable.Drawable;
satok988323c2011-06-22 16:38:13 +090031import android.os.Parcel;
32import android.os.Parcelable;
satok03b2ea12011-08-03 17:36:14 +090033import android.util.AttributeSet;
34import android.util.Slog;
35import android.util.Xml;
36
37import java.io.IOException;
38import java.util.ArrayList;
satok988323c2011-06-22 16:38:13 +090039
40/**
Ken Wakasaf76a50c2012-03-09 19:56:35 +090041 * This class is used to specify meta information of a spell checker.
satok988323c2011-06-22 16:38:13 +090042 */
43public final class SpellCheckerInfo implements Parcelable {
satok03b2ea12011-08-03 17:36:14 +090044 private static final String TAG = SpellCheckerInfo.class.getSimpleName();
satok988323c2011-06-22 16:38:13 +090045 private final ResolveInfo mService;
46 private final String mId;
satok03b2ea12011-08-03 17:36:14 +090047 private final int mLabel;
48
49 /**
50 * The spell checker setting activity's name, used by the system settings to
51 * launch the setting activity.
52 */
53 private final String mSettingsActivityName;
54
55 /**
Ken Wakasaf76a50c2012-03-09 19:56:35 +090056 * The array of subtypes.
satok03b2ea12011-08-03 17:36:14 +090057 */
58 private final ArrayList<SpellCheckerSubtype> mSubtypes = new ArrayList<SpellCheckerSubtype>();
satok988323c2011-06-22 16:38:13 +090059
60 /**
61 * Constructor.
62 * @hide
63 */
satok03b2ea12011-08-03 17:36:14 +090064 public SpellCheckerInfo(Context context, ResolveInfo service)
65 throws XmlPullParserException, IOException {
satok988323c2011-06-22 16:38:13 +090066 mService = service;
67 ServiceInfo si = service.serviceInfo;
68 mId = new ComponentName(si.packageName, si.name).flattenToShortString();
satok03b2ea12011-08-03 17:36:14 +090069
70 final PackageManager pm = context.getPackageManager();
71 int label = 0;
72 String settingsActivityComponent = null;
satok03b2ea12011-08-03 17:36:14 +090073
74 XmlResourceParser parser = null;
75 try {
76 parser = si.loadXmlMetaData(pm, SpellCheckerSession.SERVICE_META_DATA);
77 if (parser == null) {
78 throw new XmlPullParserException("No "
79 + SpellCheckerSession.SERVICE_META_DATA + " meta-data");
80 }
81
82 final Resources res = pm.getResourcesForApplication(si.applicationInfo);
83 final AttributeSet attrs = Xml.asAttributeSet(parser);
84 int type;
85 while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
86 && type != XmlPullParser.START_TAG) {
87 }
88
89 final String nodeName = parser.getName();
90 if (!"spell-checker".equals(nodeName)) {
91 throw new XmlPullParserException(
92 "Meta-data does not start with spell-checker tag");
93 }
94
95 TypedArray sa = res.obtainAttributes(attrs,
96 com.android.internal.R.styleable.SpellChecker);
97 label = sa.getResourceId(com.android.internal.R.styleable.SpellChecker_label, 0);
98 settingsActivityComponent = sa.getString(
99 com.android.internal.R.styleable.SpellChecker_settingsActivity);
100 sa.recycle();
101
102 final int depth = parser.getDepth();
103 // Parse all subtypes
104 while (((type = parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth)
105 && type != XmlPullParser.END_DOCUMENT) {
106 if (type == XmlPullParser.START_TAG) {
107 final String subtypeNodeName = parser.getName();
108 if (!"subtype".equals(subtypeNodeName)) {
109 throw new XmlPullParserException(
110 "Meta-data in spell-checker does not start with subtype tag");
111 }
112 final TypedArray a = res.obtainAttributes(
113 attrs, com.android.internal.R.styleable.SpellChecker_Subtype);
114 SpellCheckerSubtype subtype = new SpellCheckerSubtype(
115 a.getResourceId(com.android.internal.R.styleable
116 .SpellChecker_Subtype_label, 0),
117 a.getString(com.android.internal.R.styleable
118 .SpellChecker_Subtype_subtypeLocale),
119 a.getString(com.android.internal.R.styleable
Yohei Yukawa868d19b2015-12-07 15:58:57 -0800120 .SpellChecker_Subtype_languageTag),
121 a.getString(com.android.internal.R.styleable
Yohei Yukawa08943192015-12-04 16:16:47 -0800122 .SpellChecker_Subtype_subtypeExtraValue),
123 a.getInt(com.android.internal.R.styleable
124 .SpellChecker_Subtype_subtypeId, 0));
satok03b2ea12011-08-03 17:36:14 +0900125 mSubtypes.add(subtype);
126 }
127 }
128 } catch (Exception e) {
129 Slog.e(TAG, "Caught exception: " + e);
130 throw new XmlPullParserException(
131 "Unable to create context for: " + si.packageName);
132 } finally {
133 if (parser != null) parser.close();
134 }
135 mLabel = label;
136 mSettingsActivityName = settingsActivityComponent;
satok988323c2011-06-22 16:38:13 +0900137 }
138
139 /**
140 * Constructor.
141 * @hide
142 */
143 public SpellCheckerInfo(Parcel source) {
satok03b2ea12011-08-03 17:36:14 +0900144 mLabel = source.readInt();
satok988323c2011-06-22 16:38:13 +0900145 mId = source.readString();
satok03b2ea12011-08-03 17:36:14 +0900146 mSettingsActivityName = source.readString();
satok988323c2011-06-22 16:38:13 +0900147 mService = ResolveInfo.CREATOR.createFromParcel(source);
satok03b2ea12011-08-03 17:36:14 +0900148 source.readTypedList(mSubtypes, SpellCheckerSubtype.CREATOR);
satok988323c2011-06-22 16:38:13 +0900149 }
150
151 /**
152 * Return a unique ID for this spell checker. The ID is generated from
153 * the package and class name implementing the method.
154 */
155 public String getId() {
156 return mId;
157 }
158
satokf6710612012-03-30 18:31:36 +0900159 /**
satok988323c2011-06-22 16:38:13 +0900160 * Return the component of the service that implements.
161 */
162 public ComponentName getComponent() {
163 return new ComponentName(
164 mService.serviceInfo.packageName, mService.serviceInfo.name);
165 }
166
167 /**
satok03b2ea12011-08-03 17:36:14 +0900168 * Return the .apk package that implements this.
satok988323c2011-06-22 16:38:13 +0900169 */
170 public String getPackageName() {
171 return mService.serviceInfo.packageName;
172 }
173
174 /**
175 * Used to package this object into a {@link Parcel}.
176 *
177 * @param dest The {@link Parcel} to be written.
178 * @param flags The flags used for parceling.
179 */
180 @Override
181 public void writeToParcel(Parcel dest, int flags) {
satok03b2ea12011-08-03 17:36:14 +0900182 dest.writeInt(mLabel);
satok988323c2011-06-22 16:38:13 +0900183 dest.writeString(mId);
satok03b2ea12011-08-03 17:36:14 +0900184 dest.writeString(mSettingsActivityName);
satok988323c2011-06-22 16:38:13 +0900185 mService.writeToParcel(dest, flags);
satok03b2ea12011-08-03 17:36:14 +0900186 dest.writeTypedList(mSubtypes);
satok988323c2011-06-22 16:38:13 +0900187 }
188
189
190 /**
191 * Used to make this class parcelable.
192 */
193 public static final Parcelable.Creator<SpellCheckerInfo> CREATOR
194 = new Parcelable.Creator<SpellCheckerInfo>() {
195 @Override
196 public SpellCheckerInfo createFromParcel(Parcel source) {
197 return new SpellCheckerInfo(source);
198 }
199
200 @Override
201 public SpellCheckerInfo[] newArray(int size) {
202 return new SpellCheckerInfo[size];
203 }
204 };
205
206 /**
satok562ab582011-07-25 10:12:21 +0900207 * Load the user-displayed label for this spell checker.
208 *
209 * @param pm Supply a PackageManager used to load the spell checker's resources.
210 */
211 public CharSequence loadLabel(PackageManager pm) {
satok03b2ea12011-08-03 17:36:14 +0900212 if (mLabel == 0 || pm == null) return "";
213 return pm.getText(getPackageName(), mLabel, mService.serviceInfo.applicationInfo);
satok562ab582011-07-25 10:12:21 +0900214 }
215
216 /**
217 * Load the user-displayed icon for this spell checker.
218 *
219 * @param pm Supply a PackageManager used to load the spell checker's resources.
220 */
221 public Drawable loadIcon(PackageManager pm) {
222 return mService.loadIcon(pm);
223 }
224
satok2388a7b2011-08-26 14:35:09 +0900225
226 /**
227 * Return the raw information about the Service implementing this
228 * spell checker. Do not modify the returned object.
229 */
230 public ServiceInfo getServiceInfo() {
231 return mService.serviceInfo;
232 }
233
satok562ab582011-07-25 10:12:21 +0900234 /**
satok03b2ea12011-08-03 17:36:14 +0900235 * Return the class name of an activity that provides a settings UI.
236 * You can launch this activity be starting it with
237 * an {@link android.content.Intent} whose action is MAIN and with an
238 * explicit {@link android.content.ComponentName}
239 * composed of {@link #getPackageName} and the class name returned here.
240 *
241 * <p>A null will be returned if there is no settings activity.
242 */
243 public String getSettingsActivity() {
244 return mSettingsActivityName;
245 }
246
247 /**
248 * Return the count of the subtypes.
249 */
250 public int getSubtypeCount() {
251 return mSubtypes.size();
252 }
253
254 /**
255 * Return the subtype at the specified index.
256 *
257 * @param index the index of the subtype to return.
258 */
259 public SpellCheckerSubtype getSubtypeAt(int index) {
260 return mSubtypes.get(index);
261 }
262
263 /**
satok988323c2011-06-22 16:38:13 +0900264 * Used to make this class parcelable.
265 */
266 @Override
267 public int describeContents() {
268 return 0;
269 }
270}