文章目录
- Intent的用途
- Intent的类型
- 显式的Intent
- 隐式的Intent
- Intent的组成
- Component name(组件名)
- Action(操作)
- Data(数据)
- Category (类别)
- Extras
- Flags (标志)
- 隐式Intent使用示例
- 强制用户使用应用选择器
- Intent对象与Intent Filter过滤匹配过程
- Action测试
- intent对象设置了action
- intent对象没有设置action
- 总结
- Category测试
- intent对象至少有一个category
- intent对象不包含任何category
- 总结
- Data测试
- intent对象不包含URI和MIME类型
- intent对象包含URI但不包含MIME类型
- intent对象包含MIME类型但不包含URI
- intent对象同时包含URI和MIME类型
官方文档: https://developer.android.google.cn/guide/components/intents-filters
Intent的用途
- 以
startActivity()或startActivityForResult()方法启动Activity,Intent对象包含了要启动的Activity的信息及其他必要的数据。 - 以
startService()或bindService()方法启动Service,Intent对象包含了要启动的Service的信息及其他必要的数据。 - 以
sendBroadcast()或sendOrderedBroadcast()或sendStickyBroadcast()方法发送广播。
Intent的类型
显式的Intent
如果Intent中明确包含了要启动的组件的完整类名(包名及类名),那么这个Intent就是显式的。
隐式的Intent
反之就是隐式的, 一般,隐式intent不会指定特定的组件,而是声明要执行的常规操作,从而允许其他应用中的组件来处理它。
例如,你想在地图上给用户显示一个位置,但是你的App又不支持地图展示,这时候你可以将位置信息放入到一个Intent中,然后给它指定相应的action,通过这样隐式的Intent请求其他地图类型的App(例如Google Map、百度地图等)来在地图中展示一个指定的位置。
模块解藕示例:https://www.cnblogs.com/xjx22/p/5551034.html
当创建了一个隐式Intent时,Android系统会将该隐式Intent所包含的信息与设备上其他所有App中AndroidManifest.xml中的<intent-filter>进行对比过滤,从中找出满足能够接收处理该隐式Intent的App和对应的组件。如果有多个App中的某个组件都符合条件,那么Android会弹出一个对话框让用户选择需要启动哪个App。
其实同样可以理解为监听者模式, 而隐式Intent的调用就是一个广播查找调用。
Intent的组成
Android可以根据Intent所携带的信息去查找要启动的组件,启动的组件根据Intent携带的一些数据信息做相应的处理。
Intent由6部分信息组成:Component Name、Action、Data、Category、Extras、Flags。
Component Name、Action、Data、Category、决定了Android会启动哪个组件,其中Component Name用于显式Intent。Intent,Action、Data、Category、Extras、Flags用于在隐式Intent。Extras里面包含了具体的用于组件实际处理的数据信息。Flags是Intent的元数据,决定了Android对其操作的一些行为。
Component name(组件名)
要启动的组件名称。如果你想使用显式的Intent,那么你就必须指定该参数,一旦设置了component name,Android会直接将Intent传递给组件名所指定的组件去启动它。
需要注意的是,当启动
Service的时候,你应该总是指定Component Name。否则,你不确定最终哪个App的哪个组件被启动了,并且用户也看不到哪个Service启动了。
component name在Intent中对应的field是ComponentName对象,你可以通过要启动的组件的完整类名(包括应用的包名)指定该值,例如com.example.ExampleActivity。你可以通过Intent的setComponent()方法、setClass()方法、setClassName()方法或Intent的构造函数指定component name。
Action(操作)
表示了要执行操作的字符串。比如查看或选择,其对应着<intent-filter>中的<action />标签.
预定义的具有通用意义的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 android:name="com.demoBActivity.action" />。
你可以指定你独有的action以便于你的App中的Intent使用或其他App中通过Intent调用你的App中的组件。
你可以通过调用intent的setAction()方法或在Intent的构造函数中指定intent的action。
Data(数据)
此处所说的Intent中的data指的是Uri对象和数据的MIME类型,对应着<intent-filter>中的<data />标签。
一个完整的Uri由scheme、host、port、path组成,格式是<scheme>://<host>:<port>/<path>。例如content://com.example.project:200/folder/subfolder/etc。
Uri就像一个数据链接,组件可以根据此Uri获得最终的数据来源。通常将Uri和action结合使用,比如我们将action设置为ACTION_VIEW,我们应该提供将要被编辑修改的文档的Uri。
当创建了一个Intent对象的时候,除了指定Uri之外,指定数据的MIME类型也很重要。
例如,一个Activity能够显示图片,但是不能够播放视频,显示图片的Uri和播放视频的Uri可能很类似,为了不让Android误将一个含有视频Uri的Intent对象传递给一个只能显示图片的Activity,我们需要在该Activity的<intent-filter>中指定MIME类型为图片(例如<data android:mimeType="image/*" ... />)并且还要给Intent对象设置对应的图片类型的MIME,这样Android就会基于Uri和MIME类型将Intent传递给符合条件的组件。
有个特例,如果Uri使用的是content:协议,那么这就说明Uri所提供的数据将来自于本地设备,即数据由ContentProvider提供,这种情况下Android会根据Uri自动推断出MIME类型,此种情况我们无需再自己指定MIME类型。
需要注意的是,如果你想要同时设置数据的Uri和MIME类型,不要先后调用Intent对象的setData()方法和setType()方法,因为setData()方法和setType()是互斥的,即如果调用了setData()方法,会将Intent中已经通过setType()方法设置的MIME类型重置为空。如果调用了setType()方法,会将Intent中已经通过setData()方法设置的Uri重置为空。所以在需要同时设置数据的Uri和MIME类型的时候,一定要调用Intent对象的setDataAndType()方法,而不是分别调用setData()方法和setType()方法。
Category (类别)
category包含了关于组件如何处理Intent的一些其他信息,虽然可以在Intent中加入任意数量的category,但是大多数的Intent其实不需要category。
以下是一些常见的category:
CATEGORY_BROWSABLE目标Activity允许本身通过网络浏览器启动,以显示链接引用的数据,如图像或电子邮件。CATEGORY_LAUNCHER用于标识Activity是某个App的入口Activity。
Extras
extras,顾名思义,就是额外的数据信息,Intent中有一个Bundle对象存储着各种键值对,接收该Intent的组件可以从中读取出所需要的信息以便完成相应的工作。有的Intent需要靠Uri携带数据,有的Intent是靠extras携带数据信息。
你可以通过调用Intent对象的各种重载的putExtra(key, value)方法向Intent中加入各种键值对形式的额外数据。你也可以直接创建一个Bundle对象,向该Bundle对象传入很多键值对,然后通过调用Intent对象的putExtras(Bundle)方法将其设置给Intent对象中去。
例如,你创建了一个action为ACTION_SEND用于发送电子邮件的 Intent 时,
用Intent.EXTRA_EMAIL 指定“目标”收件人,用Intent.EXTRA_SUBJECT 指定“主题”。
Intent 类将为标准化的数据类型指定多个 EXTRA_* 常量。如需声明自己的 extra 键(对于应用接收的 Intent),请确保将应用的软件包名称作为前缀。 例如::static final String EXTRA_GIGAWATTS = "com.example.EXTRA_GIGAWATTS";
Flags (标志)
在 Intent 类中定义的、充当 Intent 元数据的标志。 标志可以指示 Android 系统如何启动 Activity(例如,Activity 应属于哪个任务),以及启动之后如何处理(例如,它是否属于最近的 Activity 列表)。。更多信息可参见Intent的setFlags()方法。
隐式Intent使用示例
例如,你有一段文本信息,想通过其他App分享出去,示例代码如下:
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对象。我们设置了action的值为Intent.ACTION_SEND,action对隐式Intent来说是非常重要的。然后我们将intent的数据的MIME类型设置为纯文本类型(“text/plain”),告知Android我们的Intent持有的是文本类型的数据。最后我们将实际的文本数据通过putExtra()方法作为额外数据设置进去。
需要注意的是,在构建好了Intent对象之后,我们没有立即执行startActivity(sendIntent)方法,而是将sendIntent作为参数传递给了PackageManager的resolveActivity()方法中,该方法会让Android根据该sendIntent找到潜在的适合启动的组件的信息,并以ResolveInfo类的对象的形式返回结果,如果返回null,表示当前系统中没有任何组件可以接收并处理该sendIntent。如果返回不是null,就表明系统中至少存在一个组件可以接收并处理该sendIntent,只有在这种情况下,我们才会执行代码startActivity(sendIntent),在通过intent启动组件之前先判断要启动的组件存不存在是个良好的编程习惯,因为如果系统中不存在支持你的intent的组件,那么当你调用startActivity()、startService()、bindService()等方法的时候,Android就会抛出异常。
强制用户使用应用选择器
如果有多个应用响应隐式 Intent,则用户可以选择要使用的应用,并将其设置为该操作的默认选项。 如果用户可能希望今后一直使用相同的应用执行某项操作(例如,打开网页时,用户往往倾向于仅使用一种网络浏览器),则这一点十分有用。
但是如果用户不想每次都用同一个默认App处理这样的情形怎么办呢?这时候我们可以在代码中明确地使用App选择对话框,比如我们的App执行一个action为ACTION_SEND的分享功能时,我们想让用户分享自己数据的代码,但是我们不确定用户想通过哪个App去分享,我们想每次都弹出App选择对话框让用户决定想通过哪个App分享,示例代码如下所示:
Intent sendIntent = new Intent(Intent.ACTION_SEND);
...
String title = "请选择想通过哪个App分享数据";
// 验证是否有App能够接收并处理sendIntent
if (sendIntent.resolveActivity(getPackageManager()) != null) {
// 根据sendIntent创建一个需要显示App选择对话框的intent对象
Intent chooserIntent = Intent.createChooser(sendIntent, title);
// 我们使用chooserIntent作为startActivity()方法的参数,而非sendIntent
startActivity(chooserIntent);
}
首先我们创建了我们原始的sendIntent,并对其设置action等相关信息,然后我们将sendIntent传递给了Intent.createChooser()方法中,创建了另一个chooserIntent。后面我们通过调用Intent.resolveActivity(PackageManager)方法判断系统中是否有App能够接收并处理sendIntent,该方法与上面之前提到过的PackageManager的resolveActivity()方法是等价的。最后我们使用chooserIntent作为startActivity()方法的参数,而非sendIntent,chooserIntent会让Android系统强制显示用户选择App处理Intent的界面。
Intent对象与Intent Filter过滤匹配过程
当Android系统接收到一个隐式Intent要启动一个Activity(或其他组件)时,Android会根据以下三个信息比较Intent的信息与注册的组件的<intent-filter>的信息,从而为该Intent选择出最匹配的Activity(或其他组件):
- intent中的action
- intent中的category
- intent中的data(包含Uri以及data的MIME类型)
如果隐式intent对象同时通过了某个组件的中<intent-filter>的action测试、category测试以及data测试,那么该组件就可以被intent对象所启动。反之无法启动。下面我们依次看一下如何才能通过这三个测试。
Action测试
为了指定能够接收并处理的Intent的类型,组件可以在<intent-filter>中声明其支持0个或多个action,例如:
<intent-filter>
<action android:name="com.ispring.action.ACTION_TEST1" />
<action android:name="com.ispring.action.ACTION_TEST2" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
intent对象可以通过setAction()方法设置唯一的一个action值。对于action测试,需要分两种情况:
intent对象设置了action
如果intent对象通过调用setAction()方法设置了action的值,那么只有当组件的<intent-filter>中包含了intent对象中的action值的时候,action测试才通过,否则无法通过。
举个例子,假设我们的<intent-filter>如下所示:
<intent-filter>
<action android:name="com.ispring.action.ACTION_TEST1" />
<action android:name="com.ispring.action.ACTION_TEST2" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="ispring" android:host="blog.csdn.net" />
</intent-filter>
1.下面的intent对象可以通过上面<intent-filter>里面的action测试:
Intent intent = new Intent();
intent.setAction("com.ispring.action.ACTION_TEST1");
Uri uri = Uri.parse("ispring://blog.csdn.net/sunqunsunqun");
intent.setData(uri);
该intent之所以能通过action测试是因为<intent-filter>中包含该intent的action值com.ispring.action.ACTION_TEST1。
2.下面的intent对象无法通过上面<intent-filter>里面的action测试:
Intent intent = new Intent();
intent.setAction("com.ispring.action.ACTION_TEST3");
Uri uri = Uri.parse("ispring://blog.csdn.net/sunqunsunqun");
intent.setData(uri);
该intent之所以无法通过action测试是因为<intent-filter>中不包含该intent的action值com.ispring.action.ACTION_TEST3。
intent对象没有设置action
如果intent对象没有调用setAction()方法设置action的值,那么如果<intent-filter>至少有一个任意的action的值,该intent对象就可以通过该<intent-filter>的action测试,反之,如果<intent-filter>中没有定义任何的action,那么该intent无法通过该<intent-filter>的action测试。
举个例子,假设我们的intent对象如下所示:
Intent intent = new Intent();
//不设置action值
//intent.setAction("com.ispring.action.ACTION_TEST1");
Uri uri = Uri.parse("ispring://blog.csdn.net/sunqunsunqun");
intent.setData(uri);
1.上面的intent对象可以通过如下的<intent-filter>:
<intent-filter>
<action android:name="com.csdn.action.ACTION_XXX" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="ispring" android:host="blog.csdn.net" />
</intent-filter>
2.上面的intent对象无法通过如下的<intent-filter>:
<intent-filter>
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="ispring" android:host="blog.csdn.net" />
</intent-filter>
总结
总结起来有两点结论:
- 要想让
intent对象通过action测试,那么<intent-filter>中声明的action不能为空且要包含intent对象中的action值(如果intent的action值不为空的话)。 - 如果
<intent-filter>没有声明任何action,那么所有的intent的对象(即无论intent如何配置)都无法通过<intent-filter>的action测试。
Category测试
为了指定能够接收并处理的Intent的类型,组件可以在<intent-filter>中声明其支持0个或多个category,例如:
<intent-filter>
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
...
</intent-filter>
intent对象有addCategory()方法,也就是说一个intent对象也可以关联多个category。为了能让intent对象通过<intent-filter>的category测试,intent对象中的所有category都要在<intent-filter>中找到对应项。
intent对象至少有一个category
这种情况下,假设intent对象有N个category(N >=1),那么<intent-filter>中必须要包含这N个category,intent对象才能通过category测试,否则无法通过测试。如果用intent对象启动Activity,还有其他限制条件,会在后面详细说明。
举个例子,假设我们的<intent-filter>如下所示:
<intent-filter>
<action android:name="com.ispring.action.ACTION_TEST1" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="com.ispring.category.TEST1" />
<category android:name="com.ispring.category.TEST2" />
</intent-filter>
1.以下intent对象能够通过category测试
Intent intent = new Intent();
intent.setAction("com.ispring.action.ACTION_TEST1");
intent.addCategory("com.ispring.category.TEST1");
intent.addCategory("com.ispring.category.TEST2");
该intent对象之所以可以通过category测试是因为<intent-filter>包含了该intent中所有的category值:com.ispring.category.TEST1和com.ispring.category.TEST2。
2.以下intent对象无法通过category测试
Intent intent = new Intent();
intent.setAction("com.ispring.action.ACTION_TEST1");
intent.addCategory("com.ispring.category.TEST1");
intent.addCategory("com.ispring.category.TEST3");
该intent之所以无法通过上面的<intent-filter>的category测试是因为<intent-filter>只包含了该intent中值为com.ispring.category.TEST1的category,而并未包含值为com.ispring.category.TEST3的category。
intent对象不包含任何category
如果intent对象没有调用过addCategory()方法,那么intent对象就不包含任何的category。这种情形下,如果该intent不是用来启动Activity的话,那么无论<intent-filter>中category中如何配置,intent对象总是能通过<intent-filter>的category测试,即便<intent-filter>中没有声明任何的category,intent都能通过category测试。此处强调了该intent不是用来启动Activity这种条件,会在下面详细解释。
此处需要特别说明的是,我们在上面所有的示例中,都给Activity的<intent-filter>添加了值为android.intent.category.DEFAULT的category,这是因为当我们把一个隐式的intent传递给startActivity()或startActivityForResult()方法时,Android会自动给该隐式intent添加值为android.intent.category.DEFAULT的category,所以为了能让<intent-filter>包含intent中全部的category,我们就需要在Activity的<intent-filter>中添加该category,在使用时需要特别注意。
总结
根据上面我们的几个示例,我们总结如下:
- 如果
intent对象不包含任何category,并且该intent不是用来启动Activity的,那么该intent对象总是能通过所有任意的<intent-filter>的category测试; - 如果
intent对象包含category(至少一个),那么只有当<intent-filter>中声明的category全部包含intent对象中的所有category的时候才通过category测试。 - 如果允许
Activity被隐式的Intent启动,那么我们必须在该Activity的<intent-filter>中声明值为android.intent.category.DEFAULT的category。
Data测试
为了指定可以接收的Intent的data,<intent-filter>需要声明0个或多个<data />标签,例如:
<intent-filter>
<data android:mimeType="video/mpeg" android:scheme="http" ... />
<data android:mimeType="audio/mpeg" android:scheme="http" ... />
...
</intent-filter>
每个<data />标签都可以指定一个URI结构以及data的MIME类型。一个完整的URI由scheme、host、port和path组成,其结构如下所示:<scheme>://<host>:<port>/<path>
其中scheme既可以是Android中常见的协议,也可以是我们自定义的协议。Android中常见的协议包括content协议、http协议、file协议等,自定义协议可以使用自定义的字符串。
如下是一个content协议的URI:
content://com.example.project:200/folder/subfolder/etc
在该URI中,scheme是content,host是com.example.project,port是200,path是folder/subfolder/etc。
如下是一个自定义协议的URI:
ispring://blog.csdn.net/hgy
在该URI中,scheme是ispring,host是blog.csdn.net,没有明确设定port,path是hgy。
组成URI的这些属性在<data />标签中都是可选的 ,但存在如下的依赖关系:
- 如果没有指定
scheme,那么host参数会被忽略 - 如果没有指定
host,那么port参数会被忽略 - 如果
scheme和host都没有指定,path参数会被忽略
当我们将intent对象中的Uri参数与<intent-filter>中的<data />标签指定的URI格式进行对别时,我们我们只对比<intent-filter>的<data />标签指定的部分,例如:
- 如果
<intent-filter>中只指定了scheme,那么所有带有该sheme的URI都能匹配到该<intent-filter>。 - 如果
<intent-filter>中只指定了scheme和authority(authority包括host和port两部分)而没有指定path,那么所有具有相同scheme和authority的URI都能匹配到该<intent-filter>,而不用考虑path为何值。 - 如果
<intent-filter>中同时指定了scheme、authority和path,那么只有具有相同scheme、authority和path的URI才能匹配到该<intent-filter>。
需要注意的是,<intent-filter>的<data />标签在指定path的值时,可以在里面使用通配符*,起到部分匹配的效果。
data测试需要同时将intent对象中的URI、MIME类型与<intent-filter>的<data />标签中指定的URI、MIME类型进行对比。
我们知道一个<intent-filter>下可以有多个<data />标签,intent对象无需通过所有的<data />标签测试,一般情况下,我们的intent对象只需通过了其中一个<data />标签的测试并满足某些特定情形下的一些条件,那么该intent对象就通过了该<intent-filter>的data测试。
进行对比的规则分以下几种情况:
intent对象不包含URI和MIME类型
这种情况下,只有当<intent-filter>也没有指定任何URI和MIME类型的时候才能通过data测试。
例如我们有如下intent对象:
Intent intent = new Intent();
intent.setAction("com.ispring.action.ACTION_TEST1");
1.上面的intent对象可以通过下面的<intent-filter>的data测试:
<intent-filter>
<action android:name="com.ispring.action.ACTION_TEST1" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
2.上面的intent对象无法通过下面的<intent-filter>测试:
<intent-filter>
<action android:name="com.ispring.action.ACTION_TEST1" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="ispring" />
</intent-filter>
intent对象包含URI但不包含MIME类型
这种情况下,只有当intent对象的URI匹配到了<intent-filter>中的URI格式,并且<intent-filter>没有指定MIME类型的时候才能通过data测试。需要注意的是,这里所说的<intent-filter>没有指定MIME类型的情形指的是<intent-filter>中所有的<data />标签都没有指定MIME类型,即整个<intent-filter>中完全没有android:mimeType这几个字,理解这点很重要,大家在下面的几个示例中可以体会到这点。
例如有如下intent对象:
Intent intent = new Intent();
intent.setAction("com.ispring.action.ACTION_TEST1");
Uri uri = Uri.parse("ispring://blog.csdn.net/hgy413");
intent.setData(uri);
1.上面的intent能通过如下的<intent-filter>的data测试:
<intent-filter>
<action android:name="com.ispring.action.ACTION_TEST1" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="ispring" android:host="blog.csdn.net" />
</intent-filter>
2.上面的intent对象可以通过以下<intent-filter>的data测试:
<intent-filter>
<action android:name="com.ispring.action.ACTION_TEST1" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="ispring" android:host="blog.csdn.net" />
<data android:scheme="hgy" android:host="8080" />
</intent-filter>
intent对象虽然不能通过scheme为hgy的<data />标签测试,但是可以通过scheme为ispring的data标签测试,且intent对象和<intent-filter>中的两个<data />标签都没有指定MIME,所以上面的intent对象可以通过该<intent-filter>测试。
3.上面的intent对象无法通过以下<intent-filter>的<data />标签测试:
<intent-filter>
<action android:name="com.ispring.action.ACTION_TEST1" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" android:scheme="ispring" android:host="blog.csdn.net" />
</intent-filter>
上面的intent对象之所以不能通过<intent-filter>中唯一的一个<data />标签测试是因为我们的intent对象没有指定MIME类型,但是上面的<data />标签通过android:mimeType="text/plain"设置了MIME类型。
4.上面的intent对象无法通过以下<intent-filter>的data测试:
<intent-filter>
<action android:name="com.ispring.action.ACTION_TEST1" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="ispring" android:host="blog.csdn.net" />
<data android:mimeType="text/plain" />
</intent-filter>
上面的intent对象之所以无法通过该<intent-filter>中的data测试,是因为intent对象没有设置MIME类型,但是<intent-filter>中第二个data标签通过android:mimeType="text/plain"设置了MIME类型。
intent对象包含MIME类型但不包含URI
这种情况下,只有当intent中的MIME类型与<intent-filter>中列出的MIME类型相同,并且<intent-filter>没有指定任何的URI格式的时候才能通过data测试。需要注意的是,这里所说的<intent-filter>没有指定任何的URI格式的情形指的是<intent-filter>中所有<data />标签都没有指定URI,即整个<intent-filter>中完全没有android:scheme、android:host、android:port以及android:path,理解这点很重要,大家在下面的几个示例中可以体会到这点。
例如有如下intent对象:
Intent intent = new Intent();
intent.setAction("com.ispring.action.ACTION_TEST1");
intent.setType("text/plain");
1.上面的intent对象可以通过以下<intent-filter>的data测试:
<intent-filter>
<action android:name="com.ispring.action.ACTION_TEST1" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
2.上面的intent对象可以通过以下<intent-filter>的data测试:
<intent-filter>
<action android:name="com.ispring.action.ACTION_TEST1" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
<data android:mimeType="text/plain" />
</intent-filter>
上面的intent对象虽然没有通过MIME类型为image/*的第一个data标签测试,但能通过第二个data标签测试,并且intent对象和<intent-filter>都没有指定任何的URI格式。
3.上面的intent对象不能通过以下<intent-filter>中的data测试:
<intent-filter>
<action android:name="com.ispring.action.ACTION_TEST1" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" android:scheme="ispring" />
</intent-filter>
上面的intent对象中没有设置URI信息,但是在该<intent-filter>中设置了URI中的scheme值,所以intent无法通过<intent-filter>的data测试。
4.上面的intent对象无法通过以下<intent-filter>中的data测试:
<intent-filter>
<action android:name="com.ispring.action.ACTION_TEST1" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain"
/>
<data android:scheme="ispring" />
</intent-filter>
上面的intent对象没有指定URI信息,但是上面的<intent-filter>中第二个<data />标签设置了URI中的scheme信息,所以intent对象无法通过该<intent-filter>的data测试。
intent对象同时包含URI和MIME类型
这种情况下,要分别测试URI以及MIME类型测试是否通过,只有URI以及MIME测试都通过了,data测试才能通过。
- 对于MIME测试:如果
intent的MIME类型能够匹配<intent-filter>中列出的某一个<data />标签中的MIME类型值,那么MIME类型测试就通过了。 - 对于URI测试:
又细分两种情况,满足下面的任何一种情况都可以通过URI测试。
(1).如果intent的URI格式能够匹配<intent-filter>中列出的某一个<data />中的URI,那么URI测试就通过了。
(2). 如果intent的URI是content:协议或file:协议,并且整个<intent-filter>的所有<data />标签中都没有指定URI,那么该intent也能通过URI测试。换句话说,如果一个<intent-filter>只列出了MIME类型,没有列出任何URI相关的格式的话,那么这个<intent-filter>就默认是支持content:协议或file:协议的。
下面举几个例子大家自己体会一下。
假设有如下协议为自定义协议ispring:的intent对象:
Intent intent = new Intent();
intent.setAction("com.ispring.action.ACTION_TEST1");
Uri uri = Uri.parse("ispring://blog.csdn.net/hgy");
String type = "text/plain";
intent.setDataAndType(uri, type);
1.上面的intent对象可以通过下面的<intent-filter>的data测试:
<intent-filter>
<action android:name="com.ispring.action.ACTION_TEST1" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="ispring" android:host="blog.csdn.net" />
<data android:mimeType="text/plain"
/>
</intent-filter>
2.上面的intent对象无法通过下面的<intent-filter>的data测试:
<intent-filter>
<action android:name="com.ispring.action.ACTION_TEST1" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="ispring" android:host="blog.csdn.net" android:port="8080" />
<data android:mimeType="text/plain"
/>
</intent-filter>
port不满足,URI测试不通过,导致data测试失败。
3.上面的intent对象无法通过下面的<intent-filter>的data测试:
<intent-filter>
<action android:name="com.ispring.action.ACTION_TEST1" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="ispring" android:host="blog.csdn.net" />
<data android:mimeType="image/*"
/>
</intent-filter>
android:mimeType不满足,MIME类型测试不通过,导致data测试失败。
假设有如下协议为content:的intent对象:
Intent intent = new Intent();
intent.setAction("com.ispring.action.ACTION_TEST1");
Uri uri = Uri.parse("content://com.ispring.test");
String type = "text/plain";
intent.setDataAndType(uri, type);
1.上面的intent对象无法通过下面的<intent-filter>的data测试:
<intent-filter>
<action android:name="com.ispring.action.ACTION_TEST1" />
<category android:name="android.intent.category.DEFAULT" />
<data android:scheme="ispring" />
<data android:mimeType="text/plain"
/>
</intent-filter>
URI中的scheme不匹配,导致URI测试不通过,导致data测试失败。
2.上面的intent对象可以通过下面的<intent-filter>的data测试:
<intent-filter>
<action android:name="com.ispring.action.ACTION_TEST1" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain"
/>
</intent-filter>
intent中使用的是content:协议,并且整个<intent-filter>中都没有定义URI格式,所以URI测试是可以通过的,并且MIME类型能找到匹配项,所以可以通过data测试。
参考:
https://developer.android.google.cn/guide/components/intents-filters
https://blog.csdn.net/iispring/article/details/48481793
最后
以上就是鳗鱼白羊最近收集整理的关于Android-0.Intent及Intent Filter简介的全部内容,更多相关Android-0.Intent及Intent内容请搜索靠谱客的其他文章。
发表评论 取消回复