InputMethodInfo.java revision 20cb56e26e91df91bd64d4251222e0d421cdbe47
1/*
2 * Copyright (C) 2007-2008 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.inputmethod;
18
19import org.xmlpull.v1.XmlPullParser;
20import org.xmlpull.v1.XmlPullParserException;
21
22import android.content.ComponentName;
23import android.content.Context;
24import android.content.pm.ApplicationInfo;
25import android.content.pm.PackageManager;
26import android.content.pm.ResolveInfo;
27import android.content.pm.ServiceInfo;
28import android.content.pm.PackageManager.NameNotFoundException;
29import android.content.res.Resources;
30import android.content.res.TypedArray;
31import android.content.res.XmlResourceParser;
32import android.graphics.drawable.Drawable;
33import android.os.Parcel;
34import android.os.Parcelable;
35import android.util.AttributeSet;
36import android.util.Printer;
37import android.util.Xml;
38
39import java.io.IOException;
40
41/**
42 * This class is used to specify meta information of an input method.
43 */
44public final class InputMethodInfo implements Parcelable {
45    static final String TAG = "InputMethodInfo";
46
47    /**
48     * The Service that implements this input method component.
49     */
50    final ResolveInfo mService;
51
52    /**
53     * The unique string Id to identify the input method.  This is generated
54     * from the input method component.
55     */
56    final String mId;
57
58    /**
59     * The input method setting activity's name, used by the system settings to
60     * launch the setting activity of this input method.
61     */
62    final String mSettingsActivityName;
63
64    /**
65     * The resource in the input method's .apk that holds a boolean indicating
66     * whether it should be considered the default input method for this
67     * system.  This is a resource ID instead of the final value so that it
68     * can change based on the configuration (in particular locale).
69     */
70    final int mIsDefaultResId;
71
72    /**
73     * Constructor.
74     *
75     * @param context The Context in which we are parsing the input method.
76     * @param service The ResolveInfo returned from the package manager about
77     * this input method's component.
78     */
79    public InputMethodInfo(Context context, ResolveInfo service)
80            throws XmlPullParserException, IOException {
81        mService = service;
82        ServiceInfo si = service.serviceInfo;
83        mId = new ComponentName(si.packageName, si.name).flattenToShortString();
84
85        PackageManager pm = context.getPackageManager();
86        String settingsActivityComponent = null;
87        int isDefaultResId = 0;
88
89        XmlResourceParser parser = null;
90        try {
91            parser = si.loadXmlMetaData(pm, InputMethod.SERVICE_META_DATA);
92            if (parser == null) {
93                throw new XmlPullParserException("No "
94                        + InputMethod.SERVICE_META_DATA + " meta-data");
95            }
96
97            Resources res = pm.getResourcesForApplication(si.applicationInfo);
98
99            AttributeSet attrs = Xml.asAttributeSet(parser);
100
101            int type;
102            while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
103                    && type != XmlPullParser.START_TAG) {
104            }
105
106            String nodeName = parser.getName();
107            if (!"input-method".equals(nodeName)) {
108                throw new XmlPullParserException(
109                        "Meta-data does not start with input-method tag");
110            }
111
112            TypedArray sa = res.obtainAttributes(attrs,
113                    com.android.internal.R.styleable.InputMethod);
114            settingsActivityComponent = sa.getString(
115                    com.android.internal.R.styleable.InputMethod_settingsActivity);
116            isDefaultResId = sa.getResourceId(
117                    com.android.internal.R.styleable.InputMethod_isDefault, 0);
118            sa.recycle();
119        } catch (NameNotFoundException e) {
120            throw new XmlPullParserException(
121                    "Unable to create context for: " + si.packageName);
122        } finally {
123            if (parser != null) parser.close();
124        }
125
126        mSettingsActivityName = settingsActivityComponent;
127        mIsDefaultResId = isDefaultResId;
128    }
129
130    InputMethodInfo(Parcel source) {
131        mId = source.readString();
132        mSettingsActivityName = source.readString();
133        mIsDefaultResId = source.readInt();
134        mService = ResolveInfo.CREATOR.createFromParcel(source);
135    }
136
137    /**
138     * Temporary API for creating a built-in input method.
139     */
140    public InputMethodInfo(String packageName, String className,
141            CharSequence label, String settingsActivity) {
142        ResolveInfo ri = new ResolveInfo();
143        ServiceInfo si = new ServiceInfo();
144        ApplicationInfo ai = new ApplicationInfo();
145        ai.packageName = packageName;
146        ai.enabled = true;
147        si.applicationInfo = ai;
148        si.enabled = true;
149        si.packageName = packageName;
150        si.name = className;
151        si.exported = true;
152        si.nonLocalizedLabel = label;
153        ri.serviceInfo = si;
154        mService = ri;
155        mId = new ComponentName(si.packageName, si.name).flattenToShortString();
156        mSettingsActivityName = settingsActivity;
157        mIsDefaultResId = 0;
158    }
159
160    /**
161     * Return a unique ID for this input method.  The ID is generated from
162     * the package and class name implementing the method.
163     */
164    public String getId() {
165        return mId;
166    }
167
168    /**
169     * Return the .apk package that implements this input method.
170     */
171    public String getPackageName() {
172        return mService.serviceInfo.packageName;
173    }
174
175    /**
176     * Return the class name of the service component that implements
177     * this input method.
178     */
179    public String getServiceName() {
180        return mService.serviceInfo.name;
181    }
182
183    /**
184     * Return the raw information about the Service implementing this
185     * input method.  Do not modify the returned object.
186     */
187    public ServiceInfo getServiceInfo() {
188        return mService.serviceInfo;
189    }
190
191    /**
192     * Return the component of the service that implements this input
193     * method.
194     */
195    public ComponentName getComponent() {
196        return new ComponentName(mService.serviceInfo.packageName,
197                mService.serviceInfo.name);
198    }
199
200    /**
201     * Load the user-displayed label for this input method.
202     *
203     * @param pm Supply a PackageManager used to load the input method's
204     * resources.
205     */
206    public CharSequence loadLabel(PackageManager pm) {
207        return mService.loadLabel(pm);
208    }
209
210    /**
211     * Load the user-displayed icon for this input method.
212     *
213     * @param pm Supply a PackageManager used to load the input method's
214     * resources.
215     */
216    public Drawable loadIcon(PackageManager pm) {
217        return mService.loadIcon(pm);
218    }
219
220    /**
221     * Return the class name of an activity that provides a settings UI for
222     * the input method.  You can launch this activity be starting it with
223     * an {@link android.content.Intent} whose action is MAIN and with an
224     * explicit {@link android.content.ComponentName}
225     * composed of {@link #getPackageName} and the class name returned here.
226     *
227     * <p>A null will be returned if there is no settings activity associated
228     * with the input method.
229     */
230    public String getSettingsActivity() {
231        return mSettingsActivityName;
232    }
233
234    /**
235     * Return the resource identifier of a resource inside of this input
236     * method's .apk that determines whether it should be considered a
237     * default input method for the system.
238     */
239    public int getIsDefaultResourceId() {
240        return mIsDefaultResId;
241    }
242
243    public void dump(Printer pw, String prefix) {
244        pw.println(prefix + "mId=" + mId
245                + " mSettingsActivityName=" + mSettingsActivityName);
246        pw.println(prefix + "mIsDefaultResId=0x"
247                + Integer.toHexString(mIsDefaultResId));
248        pw.println(prefix + "Service:");
249        mService.dump(pw, prefix + "  ");
250    }
251
252    @Override
253    public String toString() {
254        return "InputMethodInfo{" + mId
255                + ", settings: "
256                + mSettingsActivityName + "}";
257    }
258
259    /**
260     * Used to test whether the given parameter object is an
261     * {@link InputMethodInfo} and its Id is the same to this one.
262     *
263     * @return true if the given parameter object is an
264     *         {@link InputMethodInfo} and its Id is the same to this one.
265     */
266    @Override
267    public boolean equals(Object o) {
268        if (o == this) return true;
269        if (o == null) return false;
270
271        if (!(o instanceof InputMethodInfo)) return false;
272
273        InputMethodInfo obj = (InputMethodInfo) o;
274        return mId.equals(obj.mId);
275    }
276
277    /**
278     * Used to package this object into a {@link Parcel}.
279     *
280     * @param dest The {@link Parcel} to be written.
281     * @param flags The flags used for parceling.
282     */
283    public void writeToParcel(Parcel dest, int flags) {
284        dest.writeString(mId);
285        dest.writeString(mSettingsActivityName);
286        dest.writeInt(mIsDefaultResId);
287        mService.writeToParcel(dest, flags);
288    }
289
290    /**
291     * Used to make this class parcelable.
292     */
293    public static final Parcelable.Creator<InputMethodInfo> CREATOR = new Parcelable.Creator<InputMethodInfo>() {
294        public InputMethodInfo createFromParcel(Parcel source) {
295            return new InputMethodInfo(source);
296        }
297
298        public InputMethodInfo[] newArray(int size) {
299            return new InputMethodInfo[size];
300        }
301    };
302
303    public int describeContents() {
304        return 0;
305    }
306}
307