Android之Intent
Android中的Intent是一个非常重要且常用的类,可以用来在一个组件中启动App中的另一个组件(显示Intent)或者是启动另一个App的组件(隐式Intent),这里所说的组件指的是Activity、Service以及Broadcast
Intent的作用
- Starting an activity
可以将Intent对象传递给startActivity()方法或startActivityForResult()方法以启动一个Activity,该Intent对象包含了要启动的Activity的信息及其他必要的数据
- Starting a service
可以将Intent对象传递给startService()方法或bindService()方法以启动一个Service,该Intent对象包含了要启动的Service的信息及其他必要的数据
- Delivering a broadcast
广播是一种所有App都可以接收的信息。Android系统会发布各种类型的广播,比如发布开机广播或手机充电广播等。我们也可以给其他的App发送广播,可以将Intent对象传递给sendBroadcast()方法或sendOrderedBroadcast()方法或sendStickyBroadcast()方法以发送自定义广播
Intent的分类
以上这个图描述了如何使用intent实现一个Activity启动另一个Activity,也就是Activity的跳转
1.显示Intent
通过指定Intent组件名称来实现的,它一般用在知道目标组件名称的前提下,去调用Intent.setComponent()、Intent.setClassName()或Intent.setClass()方法或者在new Intent(A.this,B.class)指明需要转向到的Activity,显式意图明确指定了要激活的组件是哪个组件,一般是在应用程序内部使用。
具体的示例代码如下:
Intent intent = new Intent(MainActivity.this , SecondActivity.class); startActivity(intent);
2.隐式Intent
如上图所示,对于隐式Intent,Android系统会根据AndroidMainfest.xml文件中的IntentFilter进行过滤匹配,如果只有一个匹配,启动对应的组件,如果多个匹配,则系统显示可以让用户选择的界面
Android系统会根据隐式意图中设置的动作(action)、类别(category)、数据(URI和数据类型)找到最合适的组件来处理这个意图。一般是用于在不同应用程序之间且没有明确指出目标组件名称,如果想隐式intent不可以被跨应用启动只需要在AndroidManifest.xml对应的activity中配置android:exported="false"即可。
step1:
Activiry中配置intent对象
Intent sendIntent = new Intent(); sendIntent.setAction(Intent.ACTION_SEND); sendIntent.putExtra(Intent.EXTRA_TEXT,"This is my text to send."); sendIntent.setType("text/plain"); startActivity(sendIntent);
step2:
AndroidMainfest.xml文件中使用IntentFilter配置
3.区别
- 显示intent:在应用程序内部执行(不能跨应用),并且需要指定具体的组件名
- 隐式intent:没有明确指出目标组件名,通过Intent的属性设置进行过滤,并可以在不同的应用程序内部执行
Intent的组成
intent有很多属性,其中重点介绍以下几个主要属性
1.Component name
要启动的组件的名称。如果你想使用显式的Intent,那么你就必须指定该参数,一旦设置了component name,Android会直接将Intent传递给组件名所指定的组件去启动它
2.action
2.1 类型
以下是一些用于启动Activity的常见的action:
- Intent.ACTION_VIEW
其值为 “android.intent.action.VIEW”,当你有一些信息想让通过其他Activity展示给用户的时候,你就可以将Intent的action指定为ACTION_VIEW,比如在一个图片应用中查看一张图片,或者在一个地图应用中展现一个位置。
- Intent.ACTION_SEND
其值为”android.intent.action.SEND”,该action常用来做“分享”使用,当你有一些数据想通过其他的App(例如QQ、微信、百度云等)分享出去的时候,就可以使用此action构建Intent对象,并将其传递给startActivity()方法,由于手机上可能有多个App的Activity均支持ACTION_SEND这一action,所以很有可能会出现如下的图片所示的情形让用户具体选择要通过哪个App分享你的数据
- 自定义action:
自定义action,请务必将你的App的包名作为该action的前缀,例如:
static final String ACTION_TIMETRAVEL = "com.example.action.TIMETRAVEL";
2.2 如何设置
使用方法setAction进行设置
Intent sendIntent = new Intent(); sendIntent.setAction(Intent.ACTION_SEND);
2.3 总结
-
要想让intent对象通过action测试,那么intent-filter中声明的action不能为空且要包含intent对象中的action值(如果intent的action值不为空的话)
-
如果intent-filter没有声明任何action,那么所有的intent的对象(即无论intent如何配置)都无法通过intent-filter的action测试
3.data
3.1 URI
一个完整的URI由scheme、host、port和path组成,其结构如下所示:
其中scheme既可以是Android中常见的协议,也可以是我们自定义的协议
- Android中常见的协议(content协议、http协议、file协议)
content://com.example.project:200/folder/subfolder/etc
在该URI中,scheme是content,host是com.example.project,port是200,path是folder/subfolder/etc。
- 自定义协议的URI:
test://blog.csdn.net/nihaonihao
在该URI中,scheme是test,host是blog.csdn.net,没有明确设定port,nihoanihao。
- 总结
如果没有指定scheme,那么host参数会被忽略
如果没有指定host,那么port参数会被忽略
如果scheme和host都没有指定,path参数会被忽略
3.2 类型
data指的是Uri对象和数据的MIME类型,其对应着Intent Filter中的data标签
- URI
详细见上面
- MIME
...
3.3 如何设置
- setType
只设置数据的MIME类型,需要调用Intent对象的setType()方法
- setData
只设置数据的Uri,需要调用Intent对象的setData()方法
- setDataAndType
由于setData()方法和setType()是互斥的,即如果调用了setData()方法,会将Intent中已经通过setType()方法设置的MIME类型重置为空。如果调用了setType()方法,会将Intent中已经通过setData()方法设置的Uri重置为空。
所以在需要同时设置数据的Uri和MIME类型的时候,一定要调用Intent对象的setDataAndType()方法
3.4 总结
- intent对象包含URI但不包含MIME类型
当intent对象的URI匹配到了intent-filter中的URI格式,并且intent-filter没有指定MIME类型(整个intent-filter中完全没有android:mimeType)的时候才能通过data测试
- intent对象包含MIME类型但不包含URI
当intent中的MIME类型与intent-filter中列出的MIME类型相同,并且intent-filter没有指定任何的URI格式(即整个intent-filter中完全没有android:scheme、android:host、android:port以及android:path)的时候才能通过data测试
- intent对象同时包含URI和MIME类型
Intent-filter同时包含URI和MIME类型才能匹配:
如果intent的URI是content:协议或file:协议,并且整个intent-filter的所有
标签中都没有指定URI,那么该intent也能通过URI测试(原因是如果一个intent-filter只列出了MIME类型,没有列出任何URI相关的格式的话,那么这个intent-filter就默认是支持content:协议或file:协议的)
intent-filter> ...
4.category
4.1 类型
- CATEGORY_BROWSABLE
目标组件会允许自己通过一个链接被一个Web浏览器启动,该链接可能是一个图片链接或e-mail信息等。
- CATEGORY_LAUNCHER
用于标识Activity是某个App的入口Activity。
4.2 如何设置
- addCategory
intent.addCategory("aaa");
4.3 总结
-
如果隐式意图启动的是Activity,则无论Intent对象有没有使用addCategory定义category,都需要在AndroidMainfest文件的Intent-filter中声明值为android.intent.category.DEFAULT的category
-
如果intent对象不包含任何category,并且该intent不是用来启动Activity的,那么该intent对象总是能通过所有任意的intent-filter的category测试
-
如果intent对象包含category(至少一个),那么只有当intent-filter中声明的category全部包含intent对象中的所有category的时候才通过category测试。
[外链图片转存失败(img-PssxfBNF-1567667725965)(pic/category.png)]
5.总结
其中Component Name用于在显式Intent中使用,Action、Data、Category、Extras、Flags用于在隐式Intent中使用
Intent sendIntent = new Intent();// 设置action, action对隐式Intent来说是非常重要的sendIntent.setAction(Intent.ACTION_SEND);// 设置数据的MIME类型为纯文本类型sendIntent.setType("text/plain");// 设置额外的数据sendIntent.putExtra(Intent.EXTRA_TEXT, textMessage);// 获取包管理器PackageManager pm = getPackageManager();// 先判断系统中有没有潜在的App的Activity支持对该sendIntent的接收与处理if (pm.resolveActivity(sendIntent, 0) != null) { startActivity(sendIntent);}
通过intent启动组件之前先判断要启动的组件存不存在是个良好的编程习惯,因为如果系统中不存在支持你的intent的组件,那么当你调用startActivity()、startService()、bindService()等方法的时候,Android就会抛出异常。
6.其他属性
Extras为一类,里面包含了具体的用于组件实际处理的数据信息。
- MainAcrivity
MainAcrivity跳转到SecondActivity时,向SecondActivity中putExtra发送数据
Intent intent = new Intent(MainActivity.this , SecondActivity.class); String data = "hello SecondActivity"; intent.putExtra("extra_data",data); startActivity(intent);
- SecondActivity
SecondActivity调用getStringExtra接收数据
//获取前一个Activity传递过来的数据getStringExtra Intent getintent = getIntent(); String getdata = getintent.getStringExtra("extra_data");
- 总结
putExtra(key, value)方法向Intent中加入各种键值对形式的额外数据
7.参考资料
参考资料:Android中Intent对象与Intent Filter过滤匹配过程详解
更多相关文章
- 浅谈Java中Collections.sort对List排序的两种方法
- 类和 Json对象
- Python list sort方法的具体使用
- python list.sort()根据多个关键字排序的方法实现
- android上一些方法的区别和用法的注意事项
- android实现字体闪烁动画的方法
- Android中dispatchDraw分析
- Android四大基本组件介绍与生命周期
- Android(安卓)MediaPlayer 常用方法介绍