美文网首页
2020-04-08-Android Intent的显式调用和隐

2020-04-08-Android Intent的显式调用和隐

作者: 耿望 | 来源:发表于2020-04-11 10:42 被阅读0次

    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的匹配过程。

    1. 首先匹配action;只要匹配到其中一个action即可,不匹配直接返回;
    2. 然后通过matchData方法匹配data;
    3. 最后通过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;
        }
    

    相关文章

      网友评论

          本文标题:2020-04-08-Android Intent的显式调用和隐

          本文链接:https://www.haomeiwen.com/subject/edvxmhtx.html