Android 进阶3:Intent 与 IntentFilter 匹配规则

2024-06-02 07:18

本文主要是介绍Android 进阶3:Intent 与 IntentFilter 匹配规则,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

读完本文你将了解:

    • Intent
    • Intent 携带的信息
    • Intent 的类型
    • 隐式 Intent
    • Intent 过滤器 IntentFilter
    • IntentFilter 的匹配规则
      • action 的匹配规则
      • category 的匹配规则
      • data 的匹配规则
    • 总结过滤规则
    • 注意
    • Thanks

Intent

Intent 是一个消息传递对象,我们可以使用它启动其他应用组件完成特定的任务。

我们可以通过 Intent 来启动以下三个组件:

  1. Activity
    • public void startActivity(Intent intent)
  2. Service
    • public ComponentName startService(Intent service)
    • public boolean bindService(Intent service, ServiceConnection conn, int flags)
  3. BroadcastReceiver
    • public void sendBroadcast(Intent intent)
    • public void sendOrderedBroadcast(Intent intent, String receiverPermission)
    • sendStickyBroadcast(Intent intent)

Intent 携带的信息

Intent 携带的信息大概有以下几点:

intent

  • 组件名称 mComponent
    • 可以使用 setComponent()setClass()setClassName() 或 Intent 构造函数设置组件名称
    • 如果没有名称就是隐式的 Intent
  • 要进行的操作 mAction
    • 可以使用系统定义好的,也可以自定义
    • 可以使用 setAction() 或 Intent 构造函数为 Intent 指定操作
  • 数据 mData
    • 待操作数据或者数据的类型等信息
    • 要仅设置数据 URI,请调用 setData()
    • 要仅设置 MIME 类型,请调用 setType()
    • 如果同时设置以上两点,就使用 setDataAndType() 同时显式设置二者
  • 类别 mCategories
    • 表示 Intent 属于哪个类别
    • 一个 Intent 可以属于多个类别,如果不声明,就属于默认的类别 default
    • 可以使用 addCategory() 指定类别
  • 附加数据 mExtras
    • Intent 可以携带完成请求操作所需的数据,格式为键值对
    • 可以使用各种 putExtra() 方法添加数据
    • 也可以创建一个包含所有数据的 Bundle 对象,然后使用 putExtras() 将Bundle 插入 Intent 中
  • 标志位 mFlags
    • 标志位可以指示 Android 系统如何启动 Activity 以及启动之后如何处理
    • 可以使用 addFlags() 方法添加标志位

注:

1.启动 Service 时应该始终指定组件名称。 否则无法确定哪项服务会响应 Intent,且用户无法看到哪项服务已启动。
2.若要同时设置 URI 和 MIME 类型,请勿调用 setData() 和 setType(),因为它们会互相抵消彼此的值。
3.Intent 类将为标准化的数据类型指定多个 EXTRA_* 常量。例如,使用 ACTION_SEND 创建用于发送电子邮件的 Intent 时,可以使用 EXTRA_EMAIL 键指定“目标”收件人,并使用 EXTRA_SUBJECT 键指定“主题”。

Intent 的类型

Intent 分为两种类型:

  1. 显式 Intent
  2. 隐式 Intent

显式 Intent 就是直接指定要启动的组件的类名,一般用于应用内部组件调用,这里暂不赘述。

隐式 Intent

隐式 Intent 不直接指明要启动的组件,而是通过指定要进行的操作,让系统为我们找出匹配的组件,

比如这样:

Uri uri = Uri.parse("smsto:18789999999");
Intent intent = new Intent();
intent.setAction(Intent.ACTION_SENDTO);
intent.setData(uri);
intent.putExtra("sms_body", "Hello");
startActivity(intent);

上述代码构建了一个 Intent,然后为它设置了 action, data 和 extra 数据,然后调用了 startActivity()

接着系统将检查已安装的所有应用,确定哪些应用能够处理这种 Intent(在这里即:含 ACTION_SENDTO 操作并携带短信数据的 Intent ):

  • 如果只有一个应用能够处理,则该应用将立即打开并为其提供 Intent
  • 如果多个 Activity 接受 Intent,则系统将显示一个对话框,使用户能够选取要使用的应用

这里写图片描述

而在检查每个 Activity 能否处理 Intent 的过程中,需要访问 Intent 过滤器(IntentFilter)。

Intent 过滤器 IntentFilter

我们可以在 AndroidManifest.xml 中给 Activity 设置一个 IntentFilter 属性,比如这样:

<activity
    android:name=".activity.launchmode.SingleTaskActivity"android:alwaysRetainTaskState="true"android:label="singleTask"android:launchMode="singleTask"android:taskAffinity="top.shixinzhang.task2"><intent-filter><action android:name="top.shixinzhang.action.test"/><category android:name="top.shixinzhang.category.test"/><data android:mimeType="text/plain"/></intent-filter>
</activity>

IntentFilter 中可以设置 action, category 和 data 三种过滤信息,每一种信息都可以有多个。

一个 Activity 也可以有多个 IntentFilter,相当于多了几个过滤器,被筛选到的可能就更大了。


<activity
    android:name=".activity.launchmode.SingleTaskActivity"android:alwaysRetainTaskState="true"android:label="singleTask"android:launchMode="singleTask"android:taskAffinity="top.shixinzhang.task2"><intent-filter><action android:name="top.shixinzhang.action.test"/><category android:name="android.intent.category.DEFAULT"/><category android:name="top.shixinzhang.category.test"/><data android:mimeType="text/plain"/></intent-filter><intent-filter><action android:name="android.intent.action.VIEW"/><category android:name="android.intent.category.DEFAULT"/><category android:name="android.intent.category.BROWSABLE"/><data
            android:host="myapp.mycompany.com"android:scheme="myapp"/></intent-filter>
</activity>

上面的代码为该 Activity 多增加了一个过滤器,这使得在加载特定 URI 时,它可以被当做浏览器使用。

我们将分别介绍三种过滤信息的匹配规则。

IntentFilter 的匹配规则

1.action 的匹配规则

action 可以理解为一个组件具备功能、可以进行什么操作。系统为我们提供了很多内置的 action,当然也可以自定义。

一个 Intent-filter 中可以有多个 action,就好比一个人有多种才能。

<intent-filter><action android:name="android.intent.action.EDIT" /><action android:name="android.intent.action.VIEW" />...
</intent-filter>

Intent 中的 action 至少有一个与过滤器的匹配,才能调用这个过滤器所在的组件,否则无法命中。

以上述 intentFilter 为例,startActivity(intent) 中的 intent 至少要有 android.intent.action.EDITandroid.intent.action.VIEW 中的一个 action ,然后也可以有不匹配的 action。

注意:区分大小写。

列一些常用的系统内置 action 如下:

action 名称作用备注
android.intent.action.MAIN标识 Activity 为一个程序的开始
android.intent.action.CALL呼叫指定的电话号码
android.intent.action.DIAL用拨号面板
andriod.intent.action.ALL_APPS列出所有的应用
android.intent.action.ANSWER处理呼入的电话
android.intent.action.VIEW显示用户的数据通用,可以是电话、浏览器等
android.intent.action.SENDTO发送消息可以是短信、彩信、邮件等
android.intent.action.EDIT对给定数据以编辑的形式访问
android.intent.action.PICK从列表中选择信息一般用于选择联系人或者图片等
android.intent.action.CHOOSER显示一个Activity选择器比如常见的选择分享到哪里

注意:
1.android.intent.action.VIEW 根据 data 的数据类型打开相应的 Activity
比如 tel:13400010001 会打开拨号程序,http://www.baidu.com则会打开浏览器等
2.android.intent.action.SENDTO

更多 action 请见官方文档:https://developer.android.com/reference/android/content/Intent.html

2.category 的匹配规则

category 即分类,和 action 一样,一个过滤器可以包含多个分类:

<intent-filter><category android:name="android.intent.category.DEFAULT" /><category android:name="android.intent.category.BROWSABLE" />...
</intent-filter>

和 action 匹配规则(有一个匹配即可)不同的是,category 匹配时,要求你的 Intent 中的 category 必须和过滤器中声明的完全匹配。

以上述 intentFilter 为例,startActivity(intent) 中的 intent 的分类不能是 android.intent.category.DEFAULTandroid.intent.category.BROWSABLE 以外的。

注意:
Android 会自动将 android.intent.category.DEFAULT 类别传递给 startActivity()startActivityForResult() 的所有隐式 Intent。
因此即使 startActivity(intent) 中不传任何分类,也可以命中上述过滤器。

系统为我们提供了很多 category,同时我们也可以自定义。

注意:自定义分类时不要忘记在 AndroidManifest.xml 中添加 android.intent.category.DEFAULT,原因就是上面提到的,系统会为 startActivity() 中添加这个分类。

下面是一些系统提供的常见 category(图片转自:http://www.2cto.com/kf/201603/492421.html):

这里写图片描述

3.data 的匹配规则

data 表示该组件可以支持的数据格式与类型。

同样,一个过滤器也可以有多个 data:

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

一个 data 由两部分组成:

  • mimeType
  • scheme

mimeType 指的是支持的数据类型与格式,常见的有:

  • text/plain
  • image/jpeg
  • video/*
  • audio/*

/ 号前面的是数据类型,后面是具体格式。

scheme 就是常见的 URI 格式:

<scheme>://<host>:<port>/<path>

具体部分介绍及重要性如下:

  • scheme: 协议类型
    • 最重要,协议类型决定了如何访问数据,比如是本地还是网络
  • host: 主机
    • 第二重要,主机地址决定了具体 ip
  • port:端口
    • 第三重要,一个主机可能有多个网卡端口,有了端口后才能访问到具体
  • path:具体路径
    • 最后一级,表示要访问的文件夹路径

比如:

http://www.baidu.com:80/search/info
file://emulator/0/sdcard/shixinzhang

在 intent-filter 中,声明 scheme 必须从前往后,逐步缩小范围。

你可以只声明一个协议,这表示该协议下的所有数据你都可以处理;同样也可以只声明主机地址,这表示使用该协议,访问该主机下的所有数据你都可以处理。

scheme 和 mimeType 组成一个 data。而 data 的匹配规则就是:intent 中的 data 至少可以匹配过滤器中的一个

也就是说:

  • 如果 intent-filter 只声明了 scheme,那你的 intent 中必须只包含 scheme 并且至少和 intent-filter 中的一个 scheme 匹配才可以
  • 如果 intent-filter 只声明了 mimeType,那你的 intent 中除了 type 要和 intent-filter 一致,还需要额外包含 content 或者 file 的 scheme 才行,因为 intent-filter 默认包含这两个 scheme
  • 如果 intent-filter 同时声明了多个 scheme 和 mimeType,那你的 intent 至少要完全匹配其中的一组

注意 intent-filter 默认的 content 或者 file 的 scheme ,它表示默认组件能够从文件中或内容提供程序获得本地数据。

比如下面的 intent-filter,它表示该组件可以从内容提供商处获得并显示图像数据:

<intent-filter><data android:mimeType="image/*" />...
</intent-filter>

另一常见的配置是 scheme 只声明协议,同时声明数据类型的过滤器。

例如,下文中的 元素向 Android 指出,组件可从网络中检索视频数据以执行操作:

<intent-filter><data android:scheme="http" android:mimeType="video/*" />...
</intent-filter>

总结过滤规则

如果把组件比作一个安卓程序员,我们需要三个条件来筛选出我们想要的那位:

  1. 擅长什么开发,UI、网络、音视频? (对应 action)
    • 至少具备要求中的一条才可以
  2. 是哪类程序员,求知欲强、自我驱动?(对应 category )
    • 必须和要求完全一致才可以
  3. 使用什么工具开发,AS、Eclipse、记事本?(对应 data)
    • 至少具备要求中的一条才可以

注意

如果当前设备中没有能够匹配你发送到 startActivity() 的隐式 Intent,则调用将会失败,且应用会崩溃。

因此我们需要对 Intent 对象调用 resolveActivity():

  • 如果结果为非空,则至少有一个应用能够处理该 Intent,且可以安全调用 startActivity()
  • 如果结果为空,则不应使用该 Intent
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage);
sendIntent.setType("text/plain");//验证当前 Intent 是否可以被处理
if (sendIntent.resolveActivity(getPackageManager()) != null) {startActivity(sendIntent);
}

Thanks

《Android 开发艺术探索》
https://developer.android.com/reference/android/content/Intent.html
https://developer.android.com/guide/components/intents-filters.html?hl=zh-cn

这篇关于Android 进阶3:Intent 与 IntentFilter 匹配规则的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1023298

相关文章

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影

[MySQL表的增删改查-进阶]

🌈个人主页:努力学编程’ ⛅个人推荐: c语言从初阶到进阶 JavaEE详解 数据结构 ⚡学好数据结构,刷题刻不容缓:点击一起刷题 🌙心灵鸡汤:总有人要赢,为什么不能是我呢 💻💻💻数据库约束 🔭🔭🔭约束类型 not null: 指示某列不能存储 NULL 值unique: 保证某列的每行必须有唯一的值default: 规定没有给列赋值时的默认值.primary key:

hdu 3065 AC自动机 匹配串编号以及出现次数

题意: 仍旧是天朝语题。 Input 第一行,一个整数N(1<=N<=1000),表示病毒特征码的个数。 接下来N行,每行表示一个病毒特征码,特征码字符串长度在1—50之间,并且只包含“英文大写字符”。任意两个病毒特征码,不会完全相同。 在这之后一行,表示“万恶之源”网站源码,源码字符串长度在2000000之内。字符串中字符都是ASCII码可见字符(不包括回车)。

【Linux 从基础到进阶】Ansible自动化运维工具使用

Ansible自动化运维工具使用 Ansible 是一款开源的自动化运维工具,采用无代理架构(agentless),基于 SSH 连接进行管理,具有简单易用、灵活强大、可扩展性高等特点。它广泛用于服务器管理、应用部署、配置管理等任务。本文将介绍 Ansible 的安装、基本使用方法及一些实际运维场景中的应用,旨在帮助运维人员快速上手并熟练运用 Ansible。 1. Ansible的核心概念

二分最大匹配总结

HDU 2444  黑白染色 ,二分图判定 const int maxn = 208 ;vector<int> g[maxn] ;int n ;bool vis[maxn] ;int match[maxn] ;;int color[maxn] ;int setcolor(int u , int c){color[u] = c ;for(vector<int>::iter

Flutter 进阶:绘制加载动画

绘制加载动画:由小圆组成的大圆 1. 定义 LoadingScreen 类2. 实现 _LoadingScreenState 类3. 定义 LoadingPainter 类4. 总结 实现加载动画 我们需要定义两个类:LoadingScreen 和 LoadingPainter。LoadingScreen 负责控制动画的状态,而 LoadingPainter 则负责绘制动画。