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 :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中只需要匹配一组即可。
例如:
android:name=".MyBroadcastReceiver">
android:name="xcr"/>
android:mimeType="text/*"/>
android:name="android.intent.category.ALTERNATIVE"/>
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。