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來展現