众所周知 Android组件的启动模式有两种 显式调用和隐式调用,这两种调用方式从字面意思就很好理解,显式调用需要指定被启动的组件比如:
Intent i= new Intent(); i.setClass(this,SecondActivity.class); startActivity(i);
隐式调用则不需要。那么隐式调用是怎么匹配找到被启动的组件呢?答案是IntentFilter,在Manifest.xml中注册组件的时候可以加上这个我们来看下IntentFilter包含那些信息:
<activity android:name=".ipc.IpcActivity"> <intent-filter> <action android:name="com.ipc"></action> <category android:name="111"></category> <category android:name="111"></category> <data android:scheme="http://" android:host="123" android:mimeType="image/*"></data> </intent-filter></activity>
那么想要隐式启动这个组件就需要匹配这个组件的IntentFilter,一个IntentFilter包含有action,category,和data。action指的是动作就是说你需要启动是哪个组件,categray和data则是需要携带什么类型的数据,
首先来说action的匹配规则:Android系统已经包含了一些action,我们还可以自己定义一个action。如果需要action匹配成功则需要我们Intent里的action和IntentFilter里的action里的某一个相同即可,换句话说 只要我们Intent里的action出现在了IntentFilter里则匹配成功。这里需要注意的是 如果Intent里没有action则匹配失败,也就是说action是必须有,而且还区分大小写。
接下来说下category匹配规则。catefgory的匹配规则和data不同,只要你在Intent中添加了category则需要你添加的category必须出现在IntentFilter中,也就是说 IntentFilter中的category是完全包括Inten里的category才能匹配成功,举个例子:我们需要匹配上面的IntentFilter,我们可以在Intent添加category = “111”或者category = “222”或者category = “111”,category = “111”但是我们不能添加这样的category category = “111”,category = “333”如果这样则匹配失败。
这里需要提出的一点,当我们没有写category的时候系统会默认给我们分配一个
<category android:name="android.intent.category.DEFAULT"></category>
所以在一般在隐式启动组件的时候不指定category也是可以启动成功的 因为不Itent里不指定category的时候系统也会默认给我们分配一个<category android:name="android.intent.category.DEFAULT"></category>
所以一般建议在IntnetFilter里加上一个默认的category确保隐式启动成功
最后说说 datad 匹配规则。data匹配规则比较麻烦。因为data的结构本身就比较复杂
我们先来说说data的数据格式:一个data用xml可以表示成如下形式
<data android:scheme="http" android:host="123" android:port="8080" android:path="/abc" android:pathPrefix="/abc" android:mimeType="image/*"></data>
data有两部分组成 URI 和mimeType。mimeType指媒体类型如image/,video/等 URI 则又比较复杂(蛋疼)一个完整的URI 的格式如下:scheme://host:port/[path|pathPrefix|pathPattern]
上面的中括号部分可以是没有最常见的一个URL :http://www.google.com:80/search
URI中的scheme 指的是URL的类型或者说模式比如 http,file,content必写项没有的话则此URI没有意义
URI中的host主机名 必写项,
URI中的port 只有URI中的scheme和host都存在且有意思时候才是必写项。
后面的几个参数主要是路径信息 大家可以自己去查查相关资料。
介绍完URI的结构后我们来说说data的匹配规则,data的匹配规则和action差不多也要求必须有并且Intent里的data必须出现在IntentFilter中比如我们想匹配下面的一个IntentFilter中的data<data android:mimeType="image/*"></data>
则我们必须在我们的Intent添加intent.setType("img/jepg")
这里很奇怪没有URI ,其实没有URI的时候 系统会默认给我们分配一个默认的URI 一般都是 file或者是content,但是如果指定了URI则代码这样写就不能匹配成功比如我们匹配:<data android:scheme="http" http://.... android:mimeType="image/*"></data>
则我们不能写intent.setType(“img/jepg”),http://….intent.setData(Uri.parser(“”http://))因为setType或者setData的时候都会把另外一个置空,我们需要intent.setDataAndType(Uri.paser("http://"),“img/*”)
好了到此我们就写完成了 隐式启动组件的基本原理了下面结合个小例子总结下:
我们要隐式启动<activity android:name=".ipc.IpcActivity"> <intent-filter> <action android:name="com.ipc"></action> <action android:name="com.111"></action> <category android:name="com.ipc222"></category> <category android:name="22222"></category> <category android:name="android.intent.category.DEFAULT"></category> <data android:host="abc" android:mimeType="image/*" android:scheme="http"></data> <data android:host="abc" android:mimeType="image/*" android:scheme="abc"></data> </intent-filter></activity>
这个IpcActivity 则我们的Intent可以这样写Intent intent = new Intent(); intent.setAction("com.111");// intent.setAction("com.ipc"); intent.addCategory("com.ipc222"); intent.setDataAndType(Uri.parse("http://abc:80"), "image/*"); startActivity(intent);
这样我们就可以隐式启动IPC了,文中有可能有错误或者没讲到的地方请多多指正,多谢~