Intent
被称为显式Intent
.在启动显式Intent
的时候,系统将忽略Intent Filter
,直接启动相应的组件(固然,若是目标组件设定了权限,还须要验证调用者是否得到相应权限)Intent
被称为隐式Intent
.一般使用<intent-filter>
标签配合<action>
,<data>
以及<category>
来定义一个Intent
的过滤规则一般咱们应该优先使用显式Intent,这样不只性能会好一些,并且被启动的组件是肯定的(就是你经过类名所指定的那个)html
**注意:**若是targetSdkVersion
>=21的话,startService
,bindService
不能使用隐式Intent
,不然会抛出IllegalArgumentException
java
ContextImpl.java private void validateServiceIntent(Intent service) { if (service.getComponent() == null && service.getPackage() == null) { if (getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.LOLLIPOP) { IllegalArgumentException ex = new IllegalArgumentException("Service Intent must be explicit: " + service); throw ex; } else { Log.w(TAG, "Implicit intents with startService are not safe: " + service + " " + Debug.getCallers(2, 3)); } } }
<intent-filter>
中能够定义0个或多个<action>
Intent
中的action(Intent.getAction)
包含在<intent-filter>
之中,那么action
匹配环节就经过了Intent
没有设置action
,那么只要<intent-filter>
定义了<action>
,那么action
匹配环节也会经过**须要注意的是:**若是<intent-filter>
中没有定义任何<action>
,那么不管你发送的Intent
是否设置了action
,这个<intent-filter>
都不会匹配android
<intent-filter>
中能够定义0个或者多个<category>
Intent
中设置的category
是<intent-filter>
中所定义的category
的子集时,category
匹配环节才会经过(对于没有设置category
的Intent
,这个环节始终经过)**须要注意的是:**若是隐式Intent
配合startActivity
或者startActivityForResult
使用,那么要想匹配,<intent-filter>
中须要加入android.intent.category.DEFAULT
,缘由是Android framework会加上PackageManager.MATCH_DEFAULT_ONLY
app
能够参考Intent.java public ComponentName resolveActivity(PackageManager pm) { if (mComponent != null) { return mComponent; } ResolveInfo info = pm.resolveActivity(this, PackageManager.MATCH_DEFAULT_ONLY); // 这儿 if (info != null) { return new ComponentName(info.activityInfo.applicationInfo.packageName,info.activityInfo.name); } return null; }
<intent-filter>
能够定义0个或多个<data>
标签URI的匹配
URI包括schema
,host
,port
,path
. * 若是没有指定schema
,那么host
将被忽略 * 若是没有指定host
,那么port
将被忽略 * 若是schema
和host
都没有指定,那么path
将被忽略 * 若<data>
中没有定义URI相关信息,那么只有Intent
也没有定义URI信息,URI匹配才会经过 * 若Intent
中的URI的相应部分匹配<data>
中定义的URI的有效部分,那么URI匹配经过(例如: <data>
中只定义了schema
,那么只要Intent
中的URI的schema
和其匹配,那么URI匹配经过) * 若Intent
中的URI的schema为content
或者file
,且<data>
中没有指定URI,那么URI匹配经过ide
<data>
没有指定mimeType且Intent
也没有指定mimeType,或者<data>
和Intent
都指定了mimeType,且匹配时,mimeType匹配才经过<data>
标签时,至关于定义了一组mimeType
和一组URI
,只有和这一组mimeType
中的一个mimeType
匹配以及这一组URI
中的URI
匹配时,<data>
匹配才经过例如 <intent-filter> <action android:name="com.yyter.intentfilter.ignored"/> <data android:mimeType="vnd.android.cursor.item/vnd.com.yyter.intentfilter.action.target"/> <data android:scheme="yyter"/> <data android:mimeType="image/*" android:scheme="http" android:host="android.com"/> <data android:scheme="http" android:host="www.baidu.com"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> 1.intent.setType("image/jpeg");//不匹配 2.intent.setDataAndType(Uri.parse("yyter://"), "image/jpeg");//不匹配 3.intent.setDataAndType(Uri.parse("yyter://www.baidu.com"), "image/jpeg");//匹配 4.intent.setDataAndType(Uri.parse("yyter://android.com"), "image/jpeg");//匹配 5.intent.setDataAndType(Uri.parse("http://android.com"), "vnd.android.cursor.item/vnd.com.yyter.intentfilter.action.target");//匹配 ...
**建议:**一个<data>
标签要么只定义mimeType
, 要么只定义URI
,不要混在一块儿性能
action
,category
和data
都匹配经过时,<intent-filter>
才匹配,一个组件能够定义多个<intent-filter>
,只要其中一个<intent-filter>
匹配,那么这个组件就经过匹配.**注意:**对于定义了<intent-filter>
的组件,那么它将是对外可见的,若是只是app内部使用,能够在组件标签中加上android:exported="false"
ui
BroadcastReceiver
匹配,发送者都没有感知IllegalArgumentException
startService
返回null
ComponentName
(Android,找到一个匹配的service后,就不会接着寻找了)ContentProvider
是经过ContentResolver
来使用的,并不使用Intent
来启动,也不能定义<intent-filter>
)ActivityNotFoundException
Intent sendIntent = new Intent(Intent.ACTION_SEND); ... if (sendIntent.resolveActivity(getPackageManager()) != null) { String title = getResources().getString(R.string.chooser_title); Intent chooser = Intent.createChooser(sendIntent, title); startActivity(chooser); }
若是只有一个应用匹配时,将直接启动对应的Activity,不会弹出选择框this
PackageManager
的queryIntentActivities
方法,找出匹配的全部Activity,而后使用自定义UI来展现