Intent Filter

我们都知道,Intent 可以分为两种类型,分别为显式和隐式。

显示的调用也就是常使用的:

Intent intent = new Intent(context,Activity.class);
startActivity(intent);

而隐式调用我们却很少用到,这是因为在我们自己的项目中,我们能够精准的控制可以跳转到的页面,所有的跳转都可以通过显式的Intent来完成,那么,当我们想要启动一个系统的界面,而我们又不知道这个系统界面的名称的时候,这个时候我们就会用到IntentFilter。

IntentFilter的意思就是意图过滤器,当我们隐式的启动系统组件的时候,就会根据IntentFilter来筛选出合适的进行启动。

Android系统会根据我们配置的Intent Filter(意图过滤器),来进行匹配测试。匹配的时候,只会考虑三个方面:动作、数据(URI以及数据类型)和类别。也就是说Android系统会进行“动作测试”,“数据测试”,“类别测试”,来寻找可以响应隐式意图的组件或服务。

另外,当对其他App程序开放组件和服务的时候也需要配置Intent Filter(意图过滤器),一个Activity可以配置多个。

如果组件的 IntentFilter 与 Intent 中的 IntentFilter 正好匹配,系统就会启动该组件,并把 Intent 传递给它。如果有多个组件同时匹配到了,系统则会弹出一个选择框,让用户选择使用哪个应用去处理这个 Intent,比如有时候点击一个网页链接,会弹出多个应用,让用户选择用哪个浏览器去打开该链接,就是这种情况。

本篇文章将从InstallStart这个具体示例出发,分析IntentFilter的使用。


在学习PMS时,我们通常以一个应用程序和安装或升级来作为切入点,在实际应用过程中,我们通常通过如下代码安装apk。

// 创建Intent意图
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// 设置Uri和类型
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { // 7.0+ 以上版本
    Uri apkUri = FileProvider.getUriForFile(mContext, AppConstants.CONTENT_FILE_PROVIDER_AUTHORITY, new File(downloadPath));
    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
} else {
    intent.setDataAndType(Uri.fromFile(new File(downloadPath)), "application/vnd.android.package-archive");
}
//执行意图进行安装
mContext.startActivity(intent);

我们发现,如上的代码Intent并没有指定一个具体的activity,而是隐式的启动了一个Activity。

这个activity是一个能够被 application/vnd.android.package-archive 响应的Activity,通过对android源码的全局搜索,我们定位到了一个名为PackageInstaller项目的InstallStart的Activity中。

经过查阅,PackageInstaller实际上是Android系统默认安装的一个应用程序,该程序会处理程序安装的一系列动作(例如在应用市场安装完软件后的确认安装界面即为该程序的PackageInstallActivity),InstallStart为该程序的launchActivity,他在Manifest中的定义如下:

<activity
    android:name=".InstallStart"
    android:exported="true"
    android:excludeFromRecents="true">
    <intent-filter android:priority="1">
        <action android:name="android.intent.action.VIEW" />
        <action android:name="android.intent.action.INSTALL_PACKAGE" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:scheme="file" />
        <data android:scheme="content" />
        <data android:mimeType="application/vnd.android.package-archive" />
    </intent-filter>
    <intent-filter android:priority="1">
        <action android:name="android.intent.action.INSTALL_PACKAGE" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:scheme="file" />
        <data android:scheme="package" />
        <data android:scheme="content" />
    </intent-filter>
    <intent-filter android:priority="1">
        <action android:name="android.content.pm.action.CONFIRM_PERMISSIONS" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

如上代码,InstallStart中一共配置了3个intentFilter,intentFilter中有 action,category和adata三个配置项可以配置。

action
该配置项用来表示意图的行动,例如上面代码端中的vINSTALL_PACKAGE就表示该intent想要安装package。
在IntentFilter中可以有1~n个action,Intent可以有0~1个action。
IntentFilter中不能没有action,因为这样无论什么Intent请求都无法和这条IntentFilter匹配;
如果Intent中没有action,且IntentFilter中有action,那么就表示一定会通过action检测;
如果IntentFilter中有多条action规则,那么Intent中的action是IntentFilter中的其中一个action即可。
(简单的说来,Intent中action规则需要是IntentFilter中规则的真子集即可完成action检测)

category
该配置项用于声明接受的Intent类别。
在IntentFilter中可以有多个category,Intent也可以有多个。与action相同的,Intent中category规则需要是IntentFilter中规则的真子集即可完成category检测。
特别的,Android把所有传给startActivity()的隐式意图当作他们包含至少一个类别:“android.intent.category.DEFAULT” 。 因此,想要接收隐式意图的活动必须在它们的意图过滤器中包含"android.intent.category.DEFAULT"。

data
该配置项根据设置的数据匹配,通常为Uri类型。
IntentFilter可以有多个data,Intent最多能有1个。与action相同的,Intent中data规则需要是IntentFilter中规则的真子集即可完成data检测。
data元素指定了可以接受的Intent传过来的数据URI和数据类型,当一个意图对象中的URI被用来和一个过滤器中的URI比较时,比较的是URL的各个组成部分。

   <data android:mimeType="text/plain"
      android:host="www.mathiasluo.com"      
      android:path="/myfolder/my.txt"
      android:pathPattern="/myfolder/*" 
      android:port="80"
      android:scheme="http" />

一个data主要包括的就是URI和mimeType。mimeType表示媒体类型,其余都属于URI。在Intent中可以设置这两部分的数据,比如:intent.setDataAndType(Uri, “text/plain”)
IntentFilter和Intent中的data必须完全匹配才能通过,当然,一个过滤器中的路径规格可以包含通配符,这样只需要部分匹配即可。

最后,有一点: 在同一个应用内,能使用显式意图,就尽量使用显式意图,增加程序的效率,隐式意图匹配规则是需要花时间寻找的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值