说到IntentFilter最先想到的肯定是Intent
Intent
intent是一个消息传递对象,我们可以是有它来启动其他应用组件特定的任务。
作为一个Android开发者相信大家都知道intent在4大组件中的运用吧。
Activity
startActivity(Intent intent)
Service
startService(Intent service)
bindService(Intent service,ServiceConnection conn,int flags)
BroadcastReceiver
sendBroadcast(Intent intent)
sendOrderedBroadcast(Intent intent,String receiverPermission)
sendStickyBroadcast(Intent intent)
Intent 的使用类型
显示Intent
隐式Intent
显示Intent就是直接指定启动的组件类名,一边拿用于应用内部组件调用。
隐式Intent不直接指明要启动的组件,而是通过指定要进行的操作,让系统来找出匹配的组件。
例:
Uri uri=Uri.parse("smsto:18398988989");
Intent intent=new Intent();
intent.setAction(Intent.ACTION_SENDTO);
intent.setData(uri);
intent.putExtra("sms_to","hello");
startActivity(intent);
这里指明的操作是发短信,并且为intent设置了action ,data和extra数据,然后使用startActivity。然后系统就会检查所有的应用,找到可以处理这种Intent的应用。
- 当只有一个应有可以处理时,则应用就会立即打开并未其提供intent
- 当有多个时,会弹出一个选择框,然你选择一个进行操作。
在隐式调用需要intent能够匹配目标组建的intentFilter中所设置的过滤信息,如果不匹配则无法启动目标Activity。
IntentFilter可以设置action,data,category三种过滤信息。每一种信息都可以有多个。
例:
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
为了匹配过滤表,需要同时满足过滤表中的action,category,data信息,否则匹配就会失败。所有的data,action,category分别构成不同的类别,同一类别的信息共同约束当前类别的匹配过程。
只有当一个intent同时匹配action,data,category类别时才算完全匹配,只有完全匹配才能成功启动目标Activity。同时在一个Activity中可以有多个intent-filter,只要满足其中任意一个都可以启动对应的Activity。
<activity
android:name=".activity.launchmode.SingleTaskActivity"
android:alwaysRetainTaskState="true"
android:label="singleTask"
android:launchMode="singleTask"
android:taskAffinity="top.shixinzhang.task2">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.LAUNCHER"/>
<data android:mimeType="text/plain"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<data
android:host="myapp.mycompany.com"
android:scheme="myapp"/>
</intent-filter>
</activity>
IntentFilter的匹配规则
1.action的匹配规则
action是一个字符串,系统预定义了一些action但是我们也可以指自定义,在action匹配时虚满足这样的条件,即intent中的action在过滤规则中必须存在,应为intent中的action不只一条,必须满足每一条在目标activity中的过滤规则中都存在。就如下图的关系:
总而言是就是:action的匹配要求Intent中的action存在且必须和过滤规则中的其中一个action相同。当然在intent中也可以有比匹配的action,但是只要有与之匹配的就可以了。还有就是action未指定的话,匹配失败。
注意:action区分大小写。
常用的内置action:
category的匹配规则
category与action一样都是可以自定义的。但是category的匹配规则就和action不一样了。他要求intent中的category必须和匹配中一个category相同。不能出现匹配规则以外的category,否则就匹配失败。
注意:intent中category可以不设置,这样也可以满足匹配规则。
data的匹配规则
data的构成:
data的匹配规则和action类似,如果过滤规则中设置data,那么intent中必须也要定义可匹配的data。
data的组成:mimeType和URI。mimeType指媒体类型,如image/jpeg、video/*等,可以表示图片,视频,文本的不同媒体类型。而URI中包含的信息很多了:
URI结构:
<scheme>://<host>:<port>/[<path>|<pathPrefix>|<pathPattern>]
实例:
http://www.baidu.com:80/search/info
content://com.example.project:200/folder/sunfolder/etc
- Scheme:URI的模式,比如http,content,file等,如果不设置scheme那么整个URI是无效的。scheme是有默认值的默认值为content和file
- Host:URI主机名
- Port:端口号
- Path,pathPrefix,pathPattern:表示路径信息
data的匹配规则就是:intent中的data至少可以匹配过滤器中的一个。
代码中设置data:
intent.setDataAndType(Uri.parse("file://abc"),"image/png");
不能是由setData和setType因为在这两个函数中都会将另外一个属性设置为NULL。
public Intent setData(Uri data){
mData=data;
mType=null;
return this;
}
使用隐式调用时如何查看是否有Activity匹配我们的隐式Intent。
判断方法:
1.PackgeManager的resolveActivity方法
2.intent的resolveActivity方法
当他么找不到Activity的时候就会返回NULL
参考书:
《Android 开发艺术探索》