1 /* 2 * Copyright (C) 2007 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of 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, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.content.pm; 18 19 import android.content.IntentFilter; 20 import android.graphics.drawable.Drawable; 21 import android.os.Parcel; 22 import android.os.Parcelable; 23 import android.text.TextUtils; 24 import android.util.Printer; 25 26 import java.text.Collator; 27 import java.util.Comparator; 28 29 /** 30 * Information that is returned from resolving an intent 31 * against an IntentFilter. This partially corresponds to 32 * information collected from the AndroidManifest.xml's 33 * <intent> tags. 34 */ 35 public class ResolveInfo implements Parcelable { 36 /** 37 * The activity that corresponds to this resolution match, if this 38 * resolution is for an activity. One and only one of this and 39 * serviceInfo must be non-null. 40 */ 41 public ActivityInfo activityInfo; 42 43 /** 44 * The service that corresponds to this resolution match, if this 45 * resolution is for a service. One and only one of this and 46 * activityInfo must be non-null. 47 */ 48 public ServiceInfo serviceInfo; 49 50 /** 51 * The IntentFilter that was matched for this ResolveInfo. 52 */ 53 public IntentFilter filter; 54 55 /** 56 * The declared priority of this match. Comes from the "priority" 57 * attribute or, if not set, defaults to 0. Higher values are a higher 58 * priority. 59 */ 60 public int priority; 61 62 /** 63 * Order of result according to the user's preference. If the user 64 * has not set a preference for this result, the value is 0; higher 65 * values are a higher priority. 66 */ 67 public int preferredOrder; 68 69 /** 70 * The system's evaluation of how well the activity matches the 71 * IntentFilter. This is a match constant, a combination of 72 * {@link IntentFilter#MATCH_CATEGORY_MASK IntentFilter.MATCH_CATEGORY_MASK} 73 * and {@link IntentFilter#MATCH_ADJUSTMENT_MASK IntentFiler.MATCH_ADJUSTMENT_MASK}. 74 */ 75 public int match; 76 77 /** 78 * Only set when returned by 79 * {@link PackageManager#queryIntentActivityOptions}, this tells you 80 * which of the given specific intents this result came from. 0 is the 81 * first in the list, < 0 means it came from the generic Intent query. 82 */ 83 public int specificIndex = -1; 84 85 /** 86 * This filter has specified the Intent.CATEGORY_DEFAULT, meaning it 87 * would like to be considered a default action that the user can 88 * perform on this data. 89 */ 90 public boolean isDefault; 91 92 /** 93 * A string resource identifier (in the package's resources) of this 94 * match's label. From the "label" attribute or, if not set, 0. 95 */ 96 public int labelRes; 97 98 /** 99 * The actual string retrieve from <var>labelRes</var> or null if none 100 * was provided. 101 */ 102 public CharSequence nonLocalizedLabel; 103 104 /** 105 * A drawable resource identifier (in the package's resources) of this 106 * match's icon. From the "icon" attribute or, if not set, 0. 107 */ 108 public int icon; 109 110 /** 111 * Optional -- if non-null, the {@link #labelRes} and {@link #icon} 112 * resources will be loaded from this package, rather than the one 113 * containing the resolved component. 114 */ 115 public String resolvePackageName; 116 117 /** 118 * Retrieve the current textual label associated with this resolution. This 119 * will call back on the given PackageManager to load the label from 120 * the application. 121 * 122 * @param pm A PackageManager from which the label can be loaded; usually 123 * the PackageManager from which you originally retrieved this item. 124 * 125 * @return Returns a CharSequence containing the resolutions's label. If the 126 * item does not have a label, its name is returned. 127 */ 128 public CharSequence loadLabel(PackageManager pm) { 129 if (nonLocalizedLabel != null) { 130 return nonLocalizedLabel; 131 } 132 CharSequence label; 133 if (resolvePackageName != null && labelRes != 0) { 134 label = pm.getText(resolvePackageName, labelRes, null); 135 if (label != null) { 136 return label.toString().trim(); 137 } 138 } 139 ComponentInfo ci = activityInfo != null ? activityInfo : serviceInfo; 140 ApplicationInfo ai = ci.applicationInfo; 141 if (labelRes != 0) { 142 label = pm.getText(ci.packageName, labelRes, ai); 143 if (label != null) { 144 return label.toString().trim(); 145 } 146 } 147 148 CharSequence data = ci.loadLabel(pm); 149 // Make the data safe 150 if (data != null) data = data.toString().trim(); 151 return data; 152 } 153 154 /** 155 * Retrieve the current graphical icon associated with this resolution. This 156 * will call back on the given PackageManager to load the icon from 157 * the application. 158 * 159 * @param pm A PackageManager from which the icon can be loaded; usually 160 * the PackageManager from which you originally retrieved this item. 161 * 162 * @return Returns a Drawable containing the resolution's icon. If the 163 * item does not have an icon, the default activity icon is returned. 164 */ 165 public Drawable loadIcon(PackageManager pm) { 166 Drawable dr; 167 if (resolvePackageName != null && icon != 0) { 168 dr = pm.getDrawable(resolvePackageName, icon, null); 169 if (dr != null) { 170 return dr; 171 } 172 } 173 ComponentInfo ci = activityInfo != null ? activityInfo : serviceInfo; 174 ApplicationInfo ai = ci.applicationInfo; 175 if (icon != 0) { 176 dr = pm.getDrawable(ci.packageName, icon, ai); 177 if (dr != null) { 178 return dr; 179 } 180 } 181 return ci.loadIcon(pm); 182 } 183 184 /** 185 * Return the icon resource identifier to use for this match. If the 186 * match defines an icon, that is used; else if the activity defines 187 * an icon, that is used; else, the application icon is used. 188 * 189 * @return The icon associated with this match. 190 */ 191 public final int getIconResource() { 192 if (icon != 0) return icon; 193 if (activityInfo != null) return activityInfo.getIconResource(); 194 if (serviceInfo != null) return serviceInfo.getIconResource(); 195 return 0; 196 } 197 198 public void dump(Printer pw, String prefix) { 199 if (filter != null) { 200 pw.println(prefix + "Filter:"); 201 filter.dump(pw, prefix + " "); 202 } 203 pw.println(prefix + "priority=" + priority 204 + " preferredOrder=" + preferredOrder 205 + " match=0x" + Integer.toHexString(match) 206 + " specificIndex=" + specificIndex 207 + " isDefault=" + isDefault); 208 if (resolvePackageName != null) { 209 pw.println(prefix + "resolvePackageName=" + resolvePackageName); 210 } 211 if (labelRes != 0 || nonLocalizedLabel != null || icon != 0) { 212 pw.println(prefix + "labelRes=0x" + Integer.toHexString(labelRes) 213 + " nonLocalizedLabel=" + nonLocalizedLabel 214 + " icon=0x" + Integer.toHexString(icon)); 215 } 216 if (activityInfo != null) { 217 pw.println(prefix + "ActivityInfo:"); 218 activityInfo.dump(pw, prefix + " "); 219 } else if (serviceInfo != null) { 220 pw.println(prefix + "ServiceInfo:"); 221 serviceInfo.dump(pw, prefix + " "); 222 } 223 } 224 225 public ResolveInfo() { 226 } 227 228 public String toString() { 229 ComponentInfo ci = activityInfo != null ? activityInfo : serviceInfo; 230 return "ResolveInfo{" 231 + Integer.toHexString(System.identityHashCode(this)) 232 + " " + ci.name + " p=" + priority + " o=" 233 + preferredOrder + " m=0x" + Integer.toHexString(match) + "}"; 234 } 235 236 public int describeContents() { 237 return 0; 238 } 239 240 public void writeToParcel(Parcel dest, int parcelableFlags) { 241 if (activityInfo != null) { 242 dest.writeInt(1); 243 activityInfo.writeToParcel(dest, parcelableFlags); 244 } else if (serviceInfo != null) { 245 dest.writeInt(2); 246 serviceInfo.writeToParcel(dest, parcelableFlags); 247 } else { 248 dest.writeInt(0); 249 } 250 if (filter != null) { 251 dest.writeInt(1); 252 filter.writeToParcel(dest, parcelableFlags); 253 } else { 254 dest.writeInt(0); 255 } 256 dest.writeInt(priority); 257 dest.writeInt(preferredOrder); 258 dest.writeInt(match); 259 dest.writeInt(specificIndex); 260 dest.writeInt(labelRes); 261 TextUtils.writeToParcel(nonLocalizedLabel, dest, parcelableFlags); 262 dest.writeInt(icon); 263 dest.writeString(resolvePackageName); 264 } 265 266 public static final Creator<ResolveInfo> CREATOR 267 = new Creator<ResolveInfo>() { 268 public ResolveInfo createFromParcel(Parcel source) { 269 return new ResolveInfo(source); 270 } 271 public ResolveInfo[] newArray(int size) { 272 return new ResolveInfo[size]; 273 } 274 }; 275 276 private ResolveInfo(Parcel source) { 277 switch (source.readInt()) { 278 case 1: 279 activityInfo = ActivityInfo.CREATOR.createFromParcel(source); 280 serviceInfo = null; 281 break; 282 case 2: 283 serviceInfo = ServiceInfo.CREATOR.createFromParcel(source); 284 activityInfo = null; 285 break; 286 default: 287 activityInfo = null; 288 serviceInfo = null; 289 break; 290 } 291 if (source.readInt() != 0) { 292 filter = IntentFilter.CREATOR.createFromParcel(source); 293 } 294 priority = source.readInt(); 295 preferredOrder = source.readInt(); 296 match = source.readInt(); 297 specificIndex = source.readInt(); 298 labelRes = source.readInt(); 299 nonLocalizedLabel 300 = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source); 301 icon = source.readInt(); 302 resolvePackageName = source.readString(); 303 } 304 305 public static class DisplayNameComparator 306 implements Comparator<ResolveInfo> { 307 public DisplayNameComparator(PackageManager pm) { 308 mPM = pm; 309 } 310 311 public final int compare(ResolveInfo a, ResolveInfo b) { 312 CharSequence sa = a.loadLabel(mPM); 313 if (sa == null) sa = a.activityInfo.name; 314 CharSequence sb = b.loadLabel(mPM); 315 if (sb == null) sb = b.activityInfo.name; 316 317 return sCollator.compare(sa.toString(), sb.toString()); 318 } 319 320 private final Collator sCollator = Collator.getInstance(); 321 private PackageManager mPM; 322 } 323 } 324