ComponentName
如果在intent中指定了组件名,一般称为显式调用。
Intent intent = new Intent(FullscreenActivity.this, SecondActivity.class);
startActivity(intent);
这段代码实际上是在Intent中创建了一个ComponentName。
public Intent(Context packageContext, Class<?> cls) {
mComponent = new ComponentName(packageContext, cls);
}
IntentFilter
我们使用隐式调用的时候需要注意,如果不指定Category,系统会默认给Intent加上一个DEFAULT类型的Category,所以最好在Manifest中声明这个Category。
<activity android:name=".SecondActivity">
<intent-filter>
<action android:name="android.intent.action.CALL"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
1.action
Intent intent = new Intent(Intent.ACTION_CALL);
startActivity(intent);
2.category
category跟action不同,action只要有一个匹配即可,但是category要求每一个都匹配。
<activity android:name=".SecondActivity">
<intent-filter>
<action android:name="android.intent.action.CALL"/>
<category android:name="com.one.new.world.category"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
Intent intent = new Intent();
intent.addCategory("com.one.new.world.category");
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setPackage(getPackageName());
startActivity(intent);
3.data
<activity android:name=".SecondActivity">
<intent-filter>
<action android:name="android.intent.action.CALL"/>
<category android:name="com.one.new.world.category"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="image/jpeg" />
</intent-filter>
</activity>
Intent intent = new Intent();
intent.setDataAndType(Uri.EMPTY, "image/jpeg");
intent.setPackage(getPackageName());
startActivity(intent);
IntentFilter.match
从源码可以看到Intent的匹配过程。
- 首先匹配action;只要匹配到其中一个action即可,不匹配直接返回;
- 然后通过matchData方法匹配data;
- 最后通过matchCategories方法匹配categories;
public final int match(String action, String type, String scheme,
Uri data, Set<String> categories, String logTag) {
if (action != null && !matchAction(action)) {//1
if (false) Log.v(
logTag, "No matching action " + action + " for " + this);
return NO_MATCH_ACTION;
}
int dataMatch = matchData(type, scheme, data);//2
if (dataMatch < 0) {
if (false) {
if (dataMatch == NO_MATCH_TYPE) {
Log.v(logTag, "No matching type " + type
+ " for " + this);
}
if (dataMatch == NO_MATCH_DATA) {
Log.v(logTag, "No matching scheme/path " + data
+ " for " + this);
}
}
return dataMatch;
}
String categoryMismatch = matchCategories(categories);//3
if (categoryMismatch != null) {
if (false) {
Log.v(logTag, "No matching category " + categoryMismatch + " for " + this);
}
return NO_MATCH_CATEGORY;
}
// It would be nice to treat container activities as more
// important than ones that can be embedded, but this is not the way...
if (false) {
if (categories != null) {
dataMatch -= mCategories.size() - categories.size();
}
}
return dataMatch;
}
接下来看看matchData方法:
public final int matchData(String type, String scheme, Uri data) {
final ArrayList<String> types = mDataTypes;
final ArrayList<String> schemes = mDataSchemes;
int match = MATCH_CATEGORY_EMPTY;
if (types == null && schemes == null) {
return ((type == null && data == null)
? (MATCH_CATEGORY_EMPTY+MATCH_ADJUSTMENT_NORMAL) : NO_MATCH_DATA);
}
if (schemes != null) {
if (schemes.contains(scheme != null ? scheme : "")) {
match = MATCH_CATEGORY_SCHEME;
} else {
return NO_MATCH_DATA;
}
final ArrayList<PatternMatcher> schemeSpecificParts = mDataSchemeSpecificParts;
if (schemeSpecificParts != null && data != null) {
match = hasDataSchemeSpecificPart(data.getSchemeSpecificPart())
? MATCH_CATEGORY_SCHEME_SPECIFIC_PART : NO_MATCH_DATA;
}
if (match != MATCH_CATEGORY_SCHEME_SPECIFIC_PART) {
// If there isn't any matching ssp, we need to match an authority.
final ArrayList<AuthorityEntry> authorities = mDataAuthorities;
if (authorities != null) {
int authMatch = matchDataAuthority(data);
if (authMatch >= 0) {
final ArrayList<PatternMatcher> paths = mDataPaths;
if (paths == null) {
match = authMatch;
} else if (hasDataPath(data.getPath())) {
match = MATCH_CATEGORY_PATH;
} else {
return NO_MATCH_DATA;
}
} else {
return NO_MATCH_DATA;
}
}
}
// If neither an ssp nor an authority matched, we're done.
if (match == NO_MATCH_DATA) {
return NO_MATCH_DATA;
}
} else {
// Special case: match either an Intent with no data URI,
// or with a scheme: URI. This is to give a convenience for
// the common case where you want to deal with data in a
// content provider, which is done by type, and we don't want
// to force everyone to say they handle content: or file: URIs.
if (scheme != null && !"".equals(scheme)
&& !"content".equals(scheme)
&& !"file".equals(scheme)) {
return NO_MATCH_DATA;
}
}
if (types != null) {
if (findMimeType(type)) {
match = MATCH_CATEGORY_TYPE;
} else {
return NO_MATCH_TYPE;
}
} else {
// If no MIME types are specified, then we will only match against
// an Intent that does not have a MIME type.
if (type != null) {
return NO_MATCH_TYPE;
}
}
return match + MATCH_ADJUSTMENT_NORMAL;
}
最后看下matchCategories,必须要所有category匹配才能成功匹配。
public final String matchCategories(Set<String> categories) {
if (categories == null) {
return null;
}
Iterator<String> it = categories.iterator();
if (mCategories == null) {
return it.hasNext() ? it.next() : null;
}
while (it.hasNext()) {
final String category = it.next();
if (!mCategories.contains(category)) {
return category;//1
}
}
return null;
}
网友评论