美文网首页
Intent和IntentFilter

Intent和IntentFilter

作者: 董成鹏 | 来源:发表于2019-12-12 11:40 被阅读0次

    Intent分为显示Intent和隐式Intent.

    注意, 为了安全性, 系统只允许通过显示Intent去启动Service, 而且不允许为Service指定IntentFilter.

    对于Intent来说, setAction中的字符串, 建议使用包名做为前缀, 但是没有强制要求.

    可以通过setData(Uri)来给Intent设置数据, 这个数据是要交给Intent的处理者来处理的, 比如一个Intent要ACTION_EDIT, 那么这个数据就应该是要包含待处理的文档的URI. 不仅要给Intent设置Uri, 一般还要通过setType来给Intent设置MIME type.

    注意,如果我们想要同时设置URL和MIME, 请调用setDataAndType方法, 不要单独调用setData和setType方法, 因为这两个方法会相互抵消掉彼此的值.

    Intent在解析的时候, Extra不影响Intent的解析, 也就是说两个Intent其他部分一样, 但是Extra不一样, 也会被认为是同一个Intent来处理. 可以使用putExtra和putExtras来添加Extra. Extra的键也应该由包名开始.

    对于隐私Intent而已, 可能没有任何一个应用可以处理这个Intent, 这时候我们的应用就会崩溃, 所以在发送隐式Intent之前, 我们应该调用resolveActivity来判断是否有应用可以处理这个Intent, 如果结果为空, 我们就不应该发送这个Intent. 比如

    Intent intent = new Intent();
    intent.setAction(Intent.ACTION_SEND);
    intent.putExtra(Intent.EXTRA_TEXT,"hello world");
    intent.setType("text/plain");
    
    if(intent.resolveActivity(getPackageManager) != null){
      startActivity(intent);
    }
    

    如果有多个Activity可以处理这个Intent, 默认情况下会弹出一个对话框让用户选择, 用户还可以选择把某一个应用做为默认处理这个Intent的应用.
    但是在某些情况下, 我们不希望用户采用默认的这个应用, 比如分享一个图片, 这个时候我们就需要使用 对话框选择器.

    通过createChooser()来创建的Intent会始终调用出来选择对话框.

    比如

    Intent intent = new Intent(Intent.ACTION_SEND);
    
    //设置选择对话框的标题
    String title = getResource().getString(R.string.title);
    
    //看起来是又包装了一层的
    Intent chooser = Intent.createChooser(intent, title);
    
    if(intent.resolveActivity(getPackageManager) != null){
      startActivity(chooser);
    }
    

    这样就会始终弹出对话框让用户选择应用.

    Activity生命接收隐式Intent

    通过IntentFilter来声明. <intent-filter>有三个元素.

    <action>,<data>把一个Uri才分为各个方面(scheme, host, port, path, mime),<category>,
    为了能够接受隐私Intent, <category>中必须包含CATEGORY_DEFAULT.
    比如

    <activity android:name="ShareActivity">
        <intent-filter>
            <action android:name="android.intent.action.SEND"/>
            <category android:name="android.intent.category.DEFAULT"/>
            <data android:mimeType="text/plain"/>
        </intent-filter>
    </activity>
    

    一个Intent必须都通过<action>,<data>,<categroy>三部分的测试, 才会被传递给这个Activity.

    由于一个<intent-filter>可能有多个<action>,<data>,<category>标签, 我们看一下这个测试的规则.

        <intent-filter>
            <action android:name="android.intent.action.SEND"/>
            <action android:name="android.intent.action.SEND_MULTIPLE"/>
            <category android:name="android.intent.category.DEFAULT"/>
            <data android:mimeType="application/vnd.google.panorama360+jpg"/>
            <data android:mimeType="image/*"/>
            <data android:mimeType="video/*"/>
        </intent-filter>
    

    对于<action>来说, 只要有一个<action>匹配上了, 就通过action测试. 如果这个<intent-filter>没有<action>, 则任何包含了action的Intent都无法通过测试, 只有不包含action的Intent可以通过测试.

    对于<category>来说, 如果<intent-filter>中包含了多个<category>, 比如五个, 但是Intent中只有三个category, 只要这三个category都包含在那五个<category>中, 就可以通过测试. 也就是说Intent声明的每一个category都能在<intent-filter>中找到, 就可以通过测试. 如果Intent没有声明category, 则可以通过所有的category测试.

    <data>测试稍微复杂一点, <data>包含了Uri和MIME, uri又被分为scheme, host, port, path四部分, 比如

        <data android:mimeType="video/mpeg" android:scheme="http" ... />
        <data android:mimeType="audio/mpeg" android:scheme="http" ... />
    

    这四部分存在线性依赖关系, 比如scheme://host:port/path.

    如果没有指定scheme, 会忽略host
    如果没有指定host, 会忽略port.
    如果没有指定scheme和host, 会忽略path.

    如果Intent可以匹配<intent-filter>中的任何一个<data>, 则会通过data测试.

    data匹配包含两部分, 一部分是MIME匹配, 一部分是URI匹配. 会先进行MIME匹配, 通过MIME匹配后在进行URI匹配, 两种都匹配通过才算是通过.

    MIME匹配规则如下:
    <intent-filter>中不包含<data>, 那么Intent中也不能包含data, 如果包含了就不通过匹配.
    <data>中不包含MIME, Intent中也不包含MIME, 才会通过MIME匹配.
    <data>中包含MIME, 只有当Intent中的MIME一样的时候, 才会通过MIME匹配

    通过MIME匹配之后, 还要通过Uri匹配, URI匹配规则如下:

    URI的匹配原则是拿Intent中的data和<intent-filter>中的对比, 能匹配上就可以, 所以<intent-filter>中的内容可以比Intent中data的内容多. 也就是说Intent中的URI信息必须都包含在<intent-filter>中才会通过URI匹配(类似于categroy匹配)

    如果Intent中包含了scheme, 它就会和<intent-filter>中的scheme对比, 一样的话就通过测试.

    如果Intent中包含了scheme和host, 则会和<intent-filter>中的scheme,host进行对比, 都一样就通过测试.

    如果Intent中包含了scheme,host, path, 则<intent-filter>中的scheme,host, path一样才会通过测试. 注意<intent-filter>中的path可以使用通配符*.

    系统假定所有的<intent-filter>都支持content:file:这两个scheme, 所以如果Intent中的Uri是以content和file开头的, 如果已经MIME匹配上了, 但是<intent-filter>中没有指定Uri, 则该Intent自动通过URI匹配.

    相关文章

      网友评论

          本文标题:Intent和IntentFilter

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