1.由一个问题引发的思考:
对于启动一个广播,静态注册一个广播,intent-filter中什么也不设置,在发送广播中对intent也不设置,是否可以匹配到?
写代码验证,直接编译不通过:
Missing one of the key attributes ‘action#name,category#name’ on element intent-filter at AndroidManifest.xml:20:13-25:29
2.IntentFilter过滤规则的全面学习
(1)IntentFilter的解释:
Structured description of Intent values to be matched. An IntentFilter can
match against actions, categories, and data (either via its type, scheme,
and/or path) in an Intent. It also includes a “priority” value which is
used to order multiple matching filters.
IntentFilter objects are often created in XML as part of a package's {@link android.R.styleable#AndroidManifest AndroidManifest.xml} file, using {@link android.R.styleable#AndroidManifestIntentFilter intent-filter} tags.
意思就是IntentFilter是和intent相匹配的,其中action,category,组成了匹配规则。同时intentFilter还可以设置优先级,其中默认是0,范围是【-1000,1000】,值越大优先级越高。并且IntentFilter多被通过AndroidManifest.xml的形式使用。
(2)使用场景
activity的隐式启动和广播的匹配
(3)IntentFilter的匹配规则
IntentFilter的过滤信息有action,category,data.一个组件可以包含多个intent-filter,一个intent只要能完全匹配一组intent-filter即可成功的启动对应的组件。
1.action的匹配规则
intent-filter中必须包含一个action,intent信息中也必须指定一个action。intent-filter中可以有一个或者多个action,只要intent匹配其中的一个action即可。
2.category的匹配规则
intent中可以不指定category,在receiver的intent-filter中也可以不指定category,但是当要隐式启动一个activity是就必须指定android.intent.category.DEFAULT的category。否则系统也会报找不到指定的activity.当intent中指定了一个category时,就会在具有category的intent-filter中去找匹配组件。
3.data的匹配规则
data由两部分组成mimeType和URI.mimeType指媒体类型,比如image/jpeg、audio/*等。
URI的结构为
<scheme>//<host>:<port>/[<path> | <pathPrefix>|<pathPattern>]
scheme :URI的模式,比如http、file、content等,如果URI中没有指定scheme,那么整个URI的其他参数无效。
host:URI的主机名,比如www.baidu.com,如果host么有指定那么真个URI的其他参数无效。
port:URI的端口号。
path,pathPattern,pathPrefix:这三个参数指定路径信息
data的规则是如果inent-filter中描述了data,那么必须要在intent中描述匹配的data信息,如果intent-filter中没有描述data信息,那么intent中可以不指定data信息。data的规则中如果intent-filter只指定了mimeType,那么其默认的URI的scheme是file或者content。在intent中就必须同时设置mimeType和URI。如果intent-filter中有多组data,那么intent中只需要匹配一组即可。
例如:
<receiver android:name=".MyBroadcastReceiver">
<intent-filter>
<action android:name="xcr"/>
<data android:mimeType="text/*"/>
<category android:name="android.intent.category.ALTERNATIVE"/>
</intent-filter>
</receiver>
public class MainActivity extends AppCompatActivity {
private static final String TAG ="MainActivityxcr";
MyBroadcastReceiver mMyBroadcastReceiver;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent intent= new Intent();
intent.setAction("xcr");
// intent.addCategory("xxx");
// intent.setDataAndType(Uri.parse("file://abc"),"text/*");
PackageManager manager = this.getPackageManager();
ComponentName componentName = intent.resolveActivity(manager);
Log.d(TAG,"componentName =" + componentName);
startActivity(intent);
Intent intent1 =new Intent();
intent1.setDataAndType(Uri.parse("file://abc"),"text/*");
intent1.setAction("xcr");
sendBroadcast(intent1);
}
}
log:
07-14 18:36:27.027 9409-9409/? D/MyBroadcastReceiver: onReceive
(3)可以通过
PackageManager manager = this.getPackageManager();
ComponentName componentName = intent.resolveActivity(manager);
来判断是否有匹配的activity,并且这个方法是过滤了不包含intent-filter中category声明了android.intent.category.DEFAULT的。如果有匹配的activity,那么就会返回都匹配的组件,如果没有就会返回null。