吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1917|回复: 2
收起左侧

[其他转载] Android 开发艺术探索读书笔记(二)

[复制链接]
andorxor 发表于 2018-7-23 19:52

1.3 节主要讲 IntentFilter 的匹配规则。
顾名思义,IntentFilter 就是 Intent 的过滤器。我们都知道,Android 系统中启动 Activity 的方式有两种,显式调用和隐式调用,显式调用就是调用指定名称的 Activity,而隐式调用就需要 IntentFilter 的配合了。通过 IntentFilter 我们可以调用具有指定功能的 Activity,如果有多个 Activity 符合条件,那么系统就会列出所有可用的 Activity 供我们选择。IntentFilter 不仅用于启动 Activity ,还可以用于启动服务和发送广播,但这里我们只关注 Activity 部分。
IntentFilter 中有三种过滤方式,分别为 action、category 和 data,其中 action 表示接受的操作,category 表示接受的类别,data 用来指定 URI 和 MIME 类型,先来个示例:

<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>

上面的代码声明了一个使用 IntentFilter 的 ShareActivity,这样我们就可以使用对应的 Intent 来启动此 Activity。
为了匹配过滤列表,需要同时匹配列表中的 action、category、data 信息,否则匹配失败,一个 Activity 可以有多个 IntentFilter,一个 Intent 只要能匹配任意一个 IntentFilter 即可成功启动 Activity。下面分别介绍一下 action、category 和 data 的匹配规则。

action 的匹配规则

action 是一个字符串,Android 系统中预定义了一些 action,我们也可以自定义 action。一个 Intent 中必须包含 action,action 的匹配规则是 Intent 中的 action 和 过滤列表中任意一个 action 完全匹配(区分大小写),否则匹配失败。

category 的匹配规则

category 也是一个字符串,系统也预定义了一些 category 供我们使用,同时我们也可以自定义 category。Intent 中可以没有 category,但如果有,则 Intent 中的 category 必须和一个 IntentFilter 中的每一个 category 匹配,否则匹配失败。
上面说 Intent 中可以没有 category,其原因是系统在调用 startActivity() 或 startActivityForResult() 的时候会默认帮我们加上 android.intent.category.DEFAULT 这个 category,同时,我们的 Activity 如果想要接收隐式调用,就必须在 IntentFilter 中指定 android.intent.category.DEFAULT。

data 的匹配规则

data 由两部分组成,URI 和 mimeType,语法如下:

<data android:scheme="string"
android:host="string"
android:port="string"
android:path="string"
android:pathPattern="string"
android:pathPrefix="string"
android:mimeType="string" />

其中 URI 的结构为:<scheme>://<host>:<port>[<path>|<pathPrefix>|<pathPattern>],如:

http://www.example.com:80/test/etc

scheme 表示 URI 的模式,host 和 post 分别表示 URI 的主机名和端口号,path 表示一个完整的路径,pathPattern 也表示一个完整的路径,但它可以接收通配符,如 “” 和 "." 等,pathPrefix 表示一个路径的前缀。
URI 格式的这些属性是可选的,但也是相互依赖的,如果 scheme 未指定,则忽略所有其他 URI 属性,即这个 URI 是无效的;如果 host 未指定,则 port 和 path 部分将被忽略,这也意味着这个 URI 是无效的。
data 中如果只有 mimeType 而没有 URI,则 URI 的默认 scheme 属性为 content 和 file,data 的匹配规则和 action 类似,只要和 IntentFilter 中的任意一个 data 完全匹配即可,否则匹配失败。
说完了 IntentFilter 的匹配规则,下面来看一个示例吧:

private void testIntentFilter() {
    Intent intent = new Intent(Intent.ACTION_SEND);
    intent.setDataAndType(Uri.parse("file://abc"), "image/png");
    startActivity(intent);
}

这里要注意一下,如果要为 Intent 指定完整的 data,必须要调用 setDataAndType() 方法,不能分开调用 setData() 和 setType() 方法,因为这两个方法会彼此清除对方的值。
还有一个问题,当我们隐式启动一个 Activity 的时候,如果系统中没有符合条件的 Activity,那么就会出现错误,这通常会导致 app 崩溃,并弹出一个错误对话框,类似 Windows 上的“很抱歉,xxx 已停止运行”,这个讨厌的提示想必大家都见过,Android 中的错误对话框同样令人讨厌,因为没有人喜欢错误。
为了避免错误对话框,我们需要解决这个潜在的问题,在 Intent 类中有一个方法叫 resolveActivity(PackageManager pm),此方法返回最符合 Intent 要求的一个 Activity,如果没有,则返回 null,我们可以根据这个方法的返回值是否为 null 来判断系统中是否有符合要求的 Activity,代码如下:

private void testIntentFilter() {
    Intent intent = new Intent(Intent.ACTION_SEND);
    intent.setDataAndType(Uri.parse("file://abc"), "image/png");
    if (intent.resolveActivity(getPackageManager()) != null) {
        startActivity(intent);
    } else {
        // TODO
    }
}

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
nio + 1 + 1 我很赞同!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

15237633705 发表于 2018-7-23 20:59
thanks a lot ~
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-15 17:41

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表