Android Intent笔记

Android Inetnt的匹配规则

可以被用于Activity、Service和BroadcastReceiver。

Component Name:
Intent可以分为显性和隐性。显性:在Inetnt中特别指定了目标方的"Component Name"并且指定了它所在的PackageName,那么就会直接将这个Intent特定的应用,不需要做额外的匹配工作。

Category:
部分category解释:
CATEGORY_HOME: 这个应用程序是系统启动后的第一哥应用,即Launcher(桌面APP,如果有多个launcher,系统会询问启动哪一个程序)
CATEGORY_LAUNCHER:这个应用程序可以通过点击Launcher中的程序图标来启动
CATEGORY_BROWASBLE:目标放能解析并正确显示网页链接所指向的内容,如图片、Email等
CAREGORY_TEST:这个应用程序将被当成测试使用

action:表明要做什么,或者什么事情发生了。
部分Action:
ACTION_CALL:希望启动一个可以拨打电话的Activity
ACTION_EDIT:希望启动一个提供编辑功能的Activity,通常是和其他属性配合使用
ACTION_MAIN:启动的Activity是其应用程序的初始界面
ACTON_SYNC:启动的Activity可以与服务器进行数据同步
ACTION_SCREEN_on:屏幕开启时发出
ACTION_HEADSET_PLUG:当耳机插入或拔出时发出

Data:
对Action的数据补充。例如ACTION_CALL,电话号码是必须作为Data来传递的。

Extras:
它是对Data的补充,Data采用了类似scheme://uri的表达方式,而Extras则是一种键值对实现。
发送:putXX();获取:getXX()。
这些方法的内部会维护一个Bundle对象来保证进程间数据的准确传输

Flags:
与Launcher功能基本相同,规定了系统如何去启动一个Activity。

匹配规则:
一个组件可以同时声明多个Intent-filter。而在匹配过程中,只要它包含的任何一个filter通过了测试,它就会被选中。
Category:intent中的category需要在filter中找到完全匹配的项。如果不指定任何category,系统默认添加一个android.intent.category.DEFAULT。如果Filter里已经带有"MAIN"和"LACUNHER",就可以不用再另外书写DEFAULT。
Action:
1、如果filter没有任何action,那么所有inetent都无法通过测试
2、如果filter中的action不为空,那么intent中不带action的filter可以通过测试
3、如果filter中的aciton不为空,且intent中的action也不为空,那么后者必须是前者的子集才能通过测试。

Data:
分为两部分:
1、MIMI Type格式,知名某段数据是什么格式类型,以保证程序能正确解析处理
ex:
video: video/mp4、video/mpeg
application: application/zip、application/pdf
2、URI
格式: scheme:// | host: | port/ | path
URIAuthority
scheme:不仅仅包括了"http"网络协议,还有"content"标识本地ContentProvider所提供的数据
host:主机的名称
port:端口
path:文件的路劲
例子:content://com.google.provider,NotePad/notes

Intent匹配过程(API 29):
先matchAction,再matchData,最后matchCategory。

 public final int match(String action, String type, String scheme,
            Uri data, Set<String> categories, String logTag) {
        if (action != null && !matchAction(action)) {
            if (false) Log.v(
                logTag, "No matching action " + action + " for " + this);
            return NO_MATCH_ACTION;
        }

        int dataMatch = matchData(type, scheme, data);
        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);
        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;
//复数为filter参数。当filter没有数据类型和scheme要求,inetnt也不能有。否则匹配失败
        if (types == null && schemes == null) {
            return ((type == null && data == null)
                ? (MATCH_CATEGORY_EMPTY+MATCH_ADJUSTMENT_NORMAL) : NO_MATCH_DATA);
        }

        if (schemes != null) {
        //匹配scheme
            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) {
                //匹配Authority
                    int authMatch = matchDataAuthority(data);
                    if (authMatch >= 0) {
                        final ArrayList<PatternMatcher> paths = mDataPaths;
                        if (paths == null) {
                            match = authMatch;
                            //匹配PATH
                        } 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 {
        //如果filter没有声明scheme,系统默认支持"content"和"file"的scheme
            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;
    }

数据类型可以从URI中推断出:
Type的推断早在execStartActivity(),接着执行ContentResolver的resolveType(),URI中的scheme必须是"content"的才能推断出来类型。

  @Override
        public String getType(Uri uri) {
            // getCallingPackage() isn't available in getType(), as the javadoc states.
            uri = validateIncomingUri(uri);
            uri = maybeGetUriWithoutUserId(uri);
            Trace.traceBegin(TRACE_TAG_DATABASE, "getType");
            try {
                return mInterface.getType(uri);
            } catch (RemoteException e) {
                throw e.rethrowAsRuntimeException();
            } finally {
                Trace.traceEnd(TRACE_TAG_DATABASE);
            }
        }

后面的源码暂时未找到,根据书籍介绍,首页根据URI在AMS中找到对应的Content Provider,接着根据匹配到的provider实现的getType(Uri uri)解析获得类型。

参考:
《深入理解Android内核设计思想》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值