IntentResolverpublic class IntentResolver extends Object
Fields Summary |
---|
private static final String | TAG | private static final boolean | DEBUG | private static final boolean | localLOGV | private static final Comparator | mResolvePrioritySorter | private final HashSet | mFiltersAll filters that have been registered. | private final HashMap | mTypeToFilterAll of the MIME types that have been registered, such as "image/jpeg",
"image/*", or "{@literal *}/*". | private final HashMap | mBaseTypeToFilterThe base names of all of all fully qualified MIME types that have been
registered, such as "image" or "*". Wild card MIME types such as
"image/*" will not be here. | private final HashMap | mWildTypeToFilterThe base names of all of the MIME types with a sub-type wildcard that
have been registered. For example, a filter with "image/*" will be
included here as "image" but one with "image/jpeg" will not be
included here. This also includes the "*" for the "{@literal *}/*"
MIME type. | private final HashMap | mSchemeToFilterAll of the URI schemes (such as http) that have been registered. | private final HashMap | mActionToFilterAll of the actions that have been registered, but only those that did
not specify data. | private final HashMap | mTypedActionToFilterAll of the actions that have been registered and specified a MIME type. |
Methods Summary |
---|
public void | addFilter(F f)
if (localLOGV) {
Log.v(TAG, "Adding filter: " + f);
f.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
Log.v(TAG, " Building Lookup Maps:");
}
mFilters.add(f);
int numS = register_intent_filter(f, f.schemesIterator(),
mSchemeToFilter, " Scheme: ");
int numT = register_mime_types(f, " Type: ");
if (numS == 0 && numT == 0) {
register_intent_filter(f, f.actionsIterator(),
mActionToFilter, " Action: ");
}
if (numT != 0) {
register_intent_filter(f, f.actionsIterator(),
mTypedActionToFilter, " TypedAction: ");
}
| protected boolean | allowFilterResult(F filter, java.util.List dest)Control whether the given filter is allowed to go into the result
list. Mainly intended to prevent adding multiple filters for the
same target object.
return true;
| private void | buildResolveList(android.content.Intent intent, boolean debug, boolean defaultOnly, java.lang.String resolvedType, java.lang.String scheme, java.util.List src, java.util.List dest)
Set<String> categories = intent.getCategories();
final int N = src != null ? src.size() : 0;
boolean hasNonDefaults = false;
int i;
for (i=0; i<N; i++) {
F filter = src.get(i);
int match;
if (debug) Log.v(TAG, "Matching against filter " + filter);
// Do we already have this one?
if (!allowFilterResult(filter, dest)) {
if (debug) {
Log.v(TAG, " Filter's target already added");
}
continue;
}
match = filter.match(
intent.getAction(), resolvedType, scheme, intent.getData(), categories, TAG);
if (match >= 0) {
if (debug) Log.v(TAG, " Filter matched! match=0x" +
Integer.toHexString(match));
if (!defaultOnly || filter.hasCategory(Intent.CATEGORY_DEFAULT)) {
final R oneResult = newResult(filter, match);
if (oneResult != null) {
dest.add(oneResult);
}
} else {
hasNonDefaults = true;
}
} else {
if (debug) {
String reason;
switch (match) {
case IntentFilter.NO_MATCH_ACTION: reason = "action"; break;
case IntentFilter.NO_MATCH_CATEGORY: reason = "category"; break;
case IntentFilter.NO_MATCH_DATA: reason = "data"; break;
case IntentFilter.NO_MATCH_TYPE: reason = "type"; break;
default: reason = "unknown reason"; break;
}
Log.v(TAG, " Filter did not match: " + reason);
}
}
}
if (dest.size() == 0 && hasNonDefaults) {
Log.w(TAG, "resolveIntent failed: found match, but none with Intent.CATEGORY_DEFAULT");
}
| public void | dump(android.util.Printer out, java.lang.String prefix)
out.println(prefix + "Full MIME Types:");
dumpMap(out, prefix+" ", mTypeToFilter);
out.println(prefix);
out.println(prefix + "Base MIME Types:");
dumpMap(out, prefix+" ", mBaseTypeToFilter);
out.println(prefix);
out.println(prefix + "Wild MIME Types:");
dumpMap(out, prefix+" ", mWildTypeToFilter);
out.println(prefix);
out.println(prefix + "Schemes:");
dumpMap(out, prefix+" ", mSchemeToFilter);
out.println(prefix);
out.println(prefix + "Non-Data Actions:");
dumpMap(out, prefix+" ", mActionToFilter);
out.println(prefix);
out.println(prefix + "MIME Typed Actions:");
dumpMap(out, prefix+" ", mTypedActionToFilter);
| protected void | dumpFilter(android.util.Printer out, java.lang.String prefix, F filter)
out.println(prefix + filter);
| void | dumpMap(android.util.Printer out, java.lang.String prefix, java.util.Map map)
String eprefix = prefix + " ";
String fprefix = prefix + " ";
for (Map.Entry<String, ArrayList<F>> e : map.entrySet()) {
out.println(eprefix + e.getKey() + ":");
ArrayList<F> a = e.getValue();
final int N = a.size();
for (int i=0; i<N; i++) {
dumpFilter(out, fprefix, a.get(i));
}
}
| public java.util.Iterator | filterIterator()Returns an iterator allowing filters to be removed.
return new IteratorWrapper(mFilters.iterator());
| public java.util.Set | filterSet()Returns a read-only set of the filters.
return Collections.unmodifiableSet(mFilters);
| protected R | newResult(F filter, int match)
return (R)filter;
| public java.util.List | queryIntent(android.content.ContentResolver resolver, android.content.Intent intent, java.lang.String resolvedType, boolean defaultOnly)
String scheme = intent.getScheme();
ArrayList<R> finalList = new ArrayList<R>();
final boolean debug = localLOGV ||
((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0);
if (debug) Log.v(
TAG, "Resolving type " + resolvedType + " scheme " + scheme
+ " of intent " + intent);
ArrayList<F> firstTypeCut = null;
ArrayList<F> secondTypeCut = null;
ArrayList<F> thirdTypeCut = null;
ArrayList<F> schemeCut = null;
// If the intent includes a MIME type, then we want to collect all of
// the filters that match that MIME type.
if (resolvedType != null) {
int slashpos = resolvedType.indexOf('/");
if (slashpos > 0) {
final String baseType = resolvedType.substring(0, slashpos);
if (!baseType.equals("*")) {
if (resolvedType.length() != slashpos+2
|| resolvedType.charAt(slashpos+1) != '*") {
// Not a wild card, so we can just look for all filters that
// completely match or wildcards whose base type matches.
firstTypeCut = mTypeToFilter.get(resolvedType);
if (debug) Log.v(TAG, "First type cut: " + firstTypeCut);
secondTypeCut = mWildTypeToFilter.get(baseType);
if (debug) Log.v(TAG, "Second type cut: " + secondTypeCut);
} else {
// We can match anything with our base type.
firstTypeCut = mBaseTypeToFilter.get(baseType);
if (debug) Log.v(TAG, "First type cut: " + firstTypeCut);
secondTypeCut = mWildTypeToFilter.get(baseType);
if (debug) Log.v(TAG, "Second type cut: " + secondTypeCut);
}
// Any */* types always apply, but we only need to do this
// if the intent type was not already */*.
thirdTypeCut = mWildTypeToFilter.get("*");
if (debug) Log.v(TAG, "Third type cut: " + thirdTypeCut);
} else if (intent.getAction() != null) {
// The intent specified any type ({@literal *}/*). This
// can be a whole heck of a lot of things, so as a first
// cut let's use the action instead.
firstTypeCut = mTypedActionToFilter.get(intent.getAction());
if (debug) Log.v(TAG, "Typed Action list: " + firstTypeCut);
}
}
}
// If the intent includes a data URI, then we want to collect all of
// the filters that match its scheme (we will further refine matches
// on the authority and path by directly matching each resulting filter).
if (scheme != null) {
schemeCut = mSchemeToFilter.get(scheme);
if (debug) Log.v(TAG, "Scheme list: " + schemeCut);
}
// If the intent does not specify any data -- either a MIME type or
// a URI -- then we will only be looking for matches against empty
// data.
if (resolvedType == null && scheme == null && intent.getAction() != null) {
firstTypeCut = mActionToFilter.get(intent.getAction());
if (debug) Log.v(TAG, "Action list: " + firstTypeCut);
}
if (firstTypeCut != null) {
buildResolveList(intent, debug, defaultOnly,
resolvedType, scheme, firstTypeCut, finalList);
}
if (secondTypeCut != null) {
buildResolveList(intent, debug, defaultOnly,
resolvedType, scheme, secondTypeCut, finalList);
}
if (thirdTypeCut != null) {
buildResolveList(intent, debug, defaultOnly,
resolvedType, scheme, thirdTypeCut, finalList);
}
if (schemeCut != null) {
buildResolveList(intent, debug, defaultOnly,
resolvedType, scheme, schemeCut, finalList);
}
sortResults(finalList);
if (debug) {
Log.v(TAG, "Final result list:");
for (R r : finalList) {
Log.v(TAG, " " + r);
}
}
return finalList;
| private final int | register_intent_filter(F filter, java.util.Iterator i, java.util.HashMap dest, java.lang.String prefix)
if (i == null) {
return 0;
}
int num = 0;
while (i.hasNext()) {
String name = i.next();
num++;
if (localLOGV) Log.v(TAG, prefix + name);
ArrayList<F> array = dest.get(name);
if (array == null) {
//Log.v(TAG, "Creating new array for " + name);
array = new ArrayList<F>();
dest.put(name, array);
}
array.add(filter);
}
return num;
| private final int | register_mime_types(F filter, java.lang.String prefix)
final Iterator<String> i = filter.typesIterator();
if (i == null) {
return 0;
}
int num = 0;
while (i.hasNext()) {
String name = (String)i.next();
num++;
if (localLOGV) Log.v(TAG, prefix + name);
String baseName = name;
final int slashpos = name.indexOf('/");
if (slashpos > 0) {
baseName = name.substring(0, slashpos).intern();
} else {
name = name + "/*";
}
ArrayList<F> array = mTypeToFilter.get(name);
if (array == null) {
//Log.v(TAG, "Creating new array for " + name);
array = new ArrayList<F>();
mTypeToFilter.put(name, array);
}
array.add(filter);
if (slashpos > 0) {
array = mBaseTypeToFilter.get(baseName);
if (array == null) {
//Log.v(TAG, "Creating new array for " + name);
array = new ArrayList<F>();
mBaseTypeToFilter.put(baseName, array);
}
array.add(filter);
} else {
array = mWildTypeToFilter.get(baseName);
if (array == null) {
//Log.v(TAG, "Creating new array for " + name);
array = new ArrayList<F>();
mWildTypeToFilter.put(baseName, array);
}
array.add(filter);
}
}
return num;
| public void | removeFilter(F f)
removeFilterInternal(f);
mFilters.remove(f);
| void | removeFilterInternal(F f)
if (localLOGV) {
Log.v(TAG, "Removing filter: " + f);
f.dump(new LogPrinter(Log.VERBOSE, TAG), " ");
Log.v(TAG, " Cleaning Lookup Maps:");
}
int numS = unregister_intent_filter(f, f.schemesIterator(),
mSchemeToFilter, " Scheme: ");
int numT = unregister_mime_types(f, " Type: ");
if (numS == 0 && numT == 0) {
unregister_intent_filter(f, f.actionsIterator(),
mActionToFilter, " Action: ");
}
if (numT != 0) {
unregister_intent_filter(f, f.actionsIterator(),
mTypedActionToFilter, " TypedAction: ");
}
| private final boolean | remove_all_objects(java.util.List list, java.lang.Object object)
if (list != null) {
int N = list.size();
for (int idx=0; idx<N; idx++) {
if (list.get(idx) == object) {
list.remove(idx);
idx--;
N--;
}
}
return N > 0;
}
return false;
| protected void | sortResults(java.util.List results)
Collections.sort(results, mResolvePrioritySorter);
| private final int | unregister_intent_filter(F filter, java.util.Iterator i, java.util.HashMap dest, java.lang.String prefix)
if (i == null) {
return 0;
}
int num = 0;
while (i.hasNext()) {
String name = i.next();
num++;
if (localLOGV) Log.v(TAG, prefix + name);
if (!remove_all_objects(dest.get(name), filter)) {
dest.remove(name);
}
}
return num;
| private final int | unregister_mime_types(F filter, java.lang.String prefix)
final Iterator<String> i = filter.typesIterator();
if (i == null) {
return 0;
}
int num = 0;
while (i.hasNext()) {
String name = (String)i.next();
num++;
if (localLOGV) Log.v(TAG, prefix + name);
String baseName = name;
final int slashpos = name.indexOf('/");
if (slashpos > 0) {
baseName = name.substring(0, slashpos).intern();
} else {
name = name + "/*";
}
if (!remove_all_objects(mTypeToFilter.get(name), filter)) {
mTypeToFilter.remove(name);
}
if (slashpos > 0) {
if (!remove_all_objects(mBaseTypeToFilter.get(baseName), filter)) {
mBaseTypeToFilter.remove(baseName);
}
} else {
if (!remove_all_objects(mWildTypeToFilter.get(baseName), filter)) {
mWildTypeToFilter.remove(baseName);
}
}
}
return num;
|
|