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