android基础之IntentFilter匹配规则与隐式启动Activity
2015-08-02 15:35
726 查看
1 Intent Filter匹配规则
Intent解析机制主要是通过查找已注册在AndroidManifest.xml中的所有IntentFilter及其中定义的Intent,最终找到匹配的Intent。在这个解析过程中,Android是通过Intent的action/type/category这三个属性来进行匹配判断的。一个过滤列表中的action/type/category可以有多个,所有的action/type/category分别构成不同类别,同一类别信息共同约束当前类别的匹配过程。只有一个Intent同时匹配action/type/category这三个类别才算完全匹配,才能启动Activity。
另外一个组件若声明了多个Intent Filter,例如:多个action,只需要匹配任意一个即可启动该组件。例如:
<intent-filter> <action android:name="android.intent.action.VIEW"/> <category android:name="android.intent.category.DEFAULT"/> <data android:scheme="http"/> <data android:mimeType="image/*" /> </intent-filter>
2 action的匹配规则
action是一个字符串,如果Intent指明定了action,则目标组件的IntentFilter的action列表中就必须包含有这个action,否则不能匹配。一个Intent Filter中可声明多个action,Intent中的action与其中的任一个action在字符串形式上完全相同(注意:区分大小写),action方面才能匹配成功。<intent-filter> <action android:name="android.intent.action.SEND"/> <action android:name="android.intent.action.SEND_TO"/> </intent-filter>
只要Intent的action为“SEND”或“SEND_TO”,那么这个Intent在action方面就能和上面那个Activity匹配成功。
注意:Activity 间通过隐式 Intent 的跳转,在发出 Intent 之前必须通过 resolveActivity检查,避免找不到合适的调用组件,造成 ActivityNotFoundException 的异常。
Intent intent = new Intent("android.intent.action.SEND") ; if (getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY) != null) { try { startActivity(intent); } catch (ActivityNotFoundException e) { Log.e("TAG","activity not found for"); } }
Android系统预定义了许多action,这些action代表了一些常见的操作。常见action如下(Intent类中的常量)
Intent.ACTION_VIEW Intent.ACTION_DIAL Intent.ACTION_SENDTO Intent.ACTION_SEND Intent.ACTION_WEB_SEARCH
3 data的匹配规则
3.1 data的匹配规则解析
如果Intent没有提供type,系统将从data中得到数据类型。和action一样,同action类似,只要Intent的data只要与Intent Filter中的任一个data声明完全相同,data方面就完全匹配成功。(1)data由两部分组成:mimeType和URI。Intent的uri可通过setData方法设置,mimetype可通过setType方法设置;
(2)MineType指的是媒体类型:例如imgage/jpeg,auto/mpeg4和viedo/*等,可以表示图片、文本、视频等不同的媒体格式;
(3)URI由scheme、host、port、path | pathPattern | pathPrefix、queryString这5部分组成,例如:
scheme://host:port/path?qureyParameter=queryString
http://www.orangecpp.com:80/tucao?id=hello
Intent Filter中指定data的语法:
<data android:host="" // 指定数据的主机名,如www.baidu.com android:mimeType="" // 指定可以处理的数据类型,允许使用通配符的方式进行指定 android:path="" // 主机名和端口之后的部分 android:pathPattern="" android:pathPrefix="" android:port="" // 指定数据端口部分 android:scheme="" // 指定数据的协议部分,如http android:ssp="" android:sspPattern="" android:sspPrefix=""/>
3.2 案例1–根据URI传递数据的获取
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("svmplayer://player?name=" + name + "&url=" + url)); if (getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY) != null) { try { context.startActivity(intent); } catch (ActivityNotFoundException e) { Log.e("TAG","activity not found for"); } }
if (intent != null) { videoUrl = URLDecoder.decode(intent.getData().getQueryParameter("url"), "UTF-8"); title = URLDecoder.decode(intent.getData().getQueryParameter("name"), "UTF-8"); }
3.3 案例2–匹配http以 “.pdf” 结尾的路径
如果我们想要匹配http以 “.pdf” 结尾的路径,使得别的程序想要打开网络pdf 时,用户能够可以选择我们的程序进行下载查看。 我们可以将scheme设置为 “http”,pathPattern 设置为 “.*//.pdf”,整个 intent-filter 设置为:<intent-filter> <action android:name="android.intent.action.VIEW"></action> <category android:name="android.intent.category.DEFAULT"></category> <data android:scheme="http" android:pathPattern=".*//.pdf"></data> </intent-filter>
如果只想处理某个站点的 pdf,那么在 data 标签里增加 android:host=”yoursite.com” 则只会匹配 http://yoursite.com/xxx/xxx.pdf,但这不会匹配www.yoursite.com,如果也想匹配这个站点的话,你就需要再添加一个data标签,除 android:host 改为 “www.yoursite.com”,其他都一样。
4 category的匹配规则
category也是一个字符串,但是它与action的过滤规则不同,它要求Intent中个如果含有category,那么所有的category都必须和过滤规则中的其中一个category相同。也就是说,Intent中如果出现了category,不管有几个category,对于每个category来说,它必须是过滤规则中的定义了的category。当然,Intent中也可以没有category(若Intent中未指定category,系统会自动为它带上“android.intent.category.DEFAULT”),如果没有,仍然可以匹配成功。
特别说明:这二者共同出现,标明该Activity是一个入口Activity,并且会出现在系统应用列表中,二者缺一不可。
<intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter>
5 Intent Filter常见问题汇总
5.1 path、pathPrefix、pathPattern之间的区别
(1)path 用来匹配完整的路径,如:http://example.com/blog/abc.html,这里将 path 设置为 /blog/abc.html 才能够进行匹配;(2)pathPrefix 用来匹配路径的开头部分,拿上来的 Uri 来说,这里将 pathPrefix 设置为 /blog 就能进行匹配了;
(3)pathPattern 用表达式来匹配整个路径,这里需要说下匹配符号与转义。
5.2 关于隐式intent
每一个通过 startActivity() 方法发出的隐式 Intent 都至少有一个 category,就是 “android.intent.category.DEFAULT”,所以只要是想接收一个隐式 Intent 的 Activity 都应该包括 “android.intent.category.DEFAULT” category,不然将导致 Intent 匹配失败。例如:说一个activity组件要想被其他组件通过隐式intent调用, 则其在manifest.xml中的声明如下。<activity android:name="com.wooyun.org.MainActivity"> <intent-filter> <action android:name="com.google.test" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity>
5.3 于intent-filter匹配优先级
首先查看Intent的过滤器(intent-filter),按照以下优先关系查找:action->data->category。6 自定义隐式Intent
(1)比如有一个Activity名称为SecondActivity,在AndroidManifest.xml中配置:<activity android:name=".SecondActivity"> <intent-filter> <action android:name="com.example.ACTION_SECOND"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </activity>
(2)启动的时候
Intent intent = new Intent("com.example.ACTION_SECOND"); if (getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY) != null) { try { startActivity(intent); } catch (ActivityNotFoundException e) { Log.e("TAG","activity not found for"); } }
(3)只有action和category中的内容同时匹配上Intent中指定的action和category时,该Activity才能响应该Intent。android.intent.category.DEFAULT是默认的category,在调用startActivity方法时会自动将这个category添加到Intent中。可以为一个Activity指定多个category,即在SecondActivity中多添加一个category。
<category android:name="com.zjq.activity.CUSTOM_CATEGORY"/>
(4)则在启动SecondActivity时:
Intent intent = new Intent("com.zjq.activity.ACTION_SECOND"); intent.addCategory("com.zjq.activity.CUSTOM_CATEGORY"); if (getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY) != null) { try { startActivity(intent); } catch (ActivityNotFoundException e) { Log.e("TAG","activity not found for"); } }
7 系统定义的Action
(1)启动浏览器并打开某个网页Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse("http://www.baidu.com")); if (getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY) != null) { try { startActivity(intent); } catch (ActivityNotFoundException e) { Log.e("TAG","activity not found for"); } }
(2)跳转到拨号界面
Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:10086"));
8 参考链接
你必须弄懂的Intent Filter匹配规则Android隐式启动Activity
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories