顯式調用
Intent intent = new Intent();
intent.setClassName(“lbb.demo.anotest”, “lbb.demo.anotest.TwoActivity”);
startActivity(intent);
打開包名爲”lbb.demo.anotest”的 “lbb.demo.anotest.TwoActivity”方法。。。可能啓動另外一個app
new Intent(this,AnoActivity.class); 打開當前應用的AnoActivity
隱式調用
Action,Catogory匹配
//此時action爲”lbb.demo.anotest.TwoActivity”,同時默認添加DEFAULT的category
Intent intent = new Intent(“lbb.demo.anotest.TwoActivity”);
//intent.addCategory(“android.intent.category.DEFAULT”);
startActivity(intent);
//此時根據AMS規則,是全局查找的。。。並不是只針對於當前應用。。可能啓動另外一個app
<activity
android:name=".TwoActivity"
android:label="@string/title_activity_two"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="lbb.demo.anotest.TwoActivity"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</activity>
category android:name=”android.intent.category.DEFAULT”這樣是必不可少的。否則隱式匹配不到該activity,同時注意大小寫匹配
Data匹配
Each element can specify a URI and a data type (MIME media type). There are separate attributes —scheme, host, port, and path — for each part of the URI:
scheme://host:port/path or pathPrefix or pathPattern
For example, in the following URI,
content://com.example.project:200/folder/subfolder/etc
the scheme is “content”, the host is “com.example.project”, the port is “200”, and the path is “folder/subfolder/etc”.
path 用來匹配完整的路徑,如:http://example.com/blog/abc.html,這裏將 path 設置爲 /blog/abc.html 才能夠進行匹配;
pathPrefix 用來匹配路徑的開頭部分,拿上來的 Uri 來說,這裏將 pathPrefix 設置爲 /blog 就能進行匹配了;
pathPattern 用表達式來匹配整個路徑,這裏需要說下匹配符號與轉義。
匹配符號:
“” 用來匹配0次或更多,如:“a” 可以匹配“a”、“aa”、“aaa”…
“.” 用來匹配任意字符,如:“.” 可以匹配“a”、“b”,“c”…
因此 “.*” 就是用來匹配任意字符0次或更多,如:“.*html” 可以匹配 “abchtml”、“chtml”,“html”,“sdf.html”…
轉義:因爲當讀取 Xml 的時候,“/” 是被當作轉義字符的(當它被用作 pathPattern 轉義之前),因此這裏需要兩次轉義,讀取 Xml 是一次,在 pathPattern 中使用又是一次。如:“” 這個字符就應該寫成 “//”,“/” 這個字符就應該寫成 “////”。
setType 調用後設置 mimeType,然後將 data 置爲 null;
setData 調用後設置 data,然後將 mimeType 置爲 null;
setDataAndType 調用後纔會同時設置 data 與 mimeType。
setDataAndType不等同於先調用setData後調用setType,尤其注意
URI的schema是有默認值的,默認值是”content”/”file”
<intent-filter>
<data android:mimeType="video/mpeg"/>
</intent-filter>
//正確方式
intent.setDataAndType(Uri.parse("file://abc"), "video/mpeg");
intent.setDataAndType(Uri.parse("content://abc"), "video/mpeg");
intent.setType("video/mpeg");
intent.setDataAndType(Uri.parse(“http://abc“), “video/mpeg”);
這樣是匹配不到的,因爲schema部分不匹配默認值是”content”/”file”
PackageManager相關方法
如果有多個action匹配就會出現選擇框。。如果沒有任何一個,就會Force Close,所以可以通過方法檢查是否有符合條件的activity,避免FC
PackageManager方法
/**
* Determine the best action to perform for a given Intent. This is how
* {@link Intent#resolveActivity} finds an activity if a class has not
* been explicitly specified.
*
* <p><em>Note:</em> if using an implicit Intent (without an explicit ComponentName
* specified), be sure to consider whether to set the {@link #MATCH_DEFAULT_ONLY}
* only flag. You need to do so to resolve the activity in the same way
* that {@link android.content.Context#startActivity(Intent)} and
* {@link android.content.Intent#resolveActivity(PackageManager)
* Intent.resolveActivity(PackageManager)} do.</p>
*
* @param intent An intent containing all of the desired specification
* (action, data, type, category, and/or component).
* @param flags Additional option flags. The most important is
* {@link #MATCH_DEFAULT_ONLY}, to limit the resolution to only
* those activities that support the {@link android.content.Intent#CATEGORY_DEFAULT}.
*
* @return Returns a ResolveInfo containing the final activity intent that
* was determined to be the best action. Returns null if no
* matching activity was found. If multiple matching activities are
* found and there is no default set, returns a ResolveInfo
* containing something else, such as the activity resolver.
*
* @see #MATCH_DEFAULT_ONLY
* @see #GET_INTENT_FILTERS
* @see #GET_RESOLVED_FILTER
*/
public abstract ResolveInfo resolveActivity(Intent intent, int flags);
/**
* Retrieve all activities that can be performed for the given intent.
*
* @param intent The desired intent as per resolveActivity().
* @param flags Additional option flags. The most important is
* {@link #MATCH_DEFAULT_ONLY}, to limit the resolution to only
* those activities that support the {@link android.content.Intent#CATEGORY_DEFAULT}.
*
* @return A List<ResolveInfo> containing one entry for each matching
* Activity. These are ordered from best to worst match -- that
* is, the first item in the list is what is returned by
* {@link #resolveActivity}. If there are no matching activities, an empty
* list is returned.
*
* @see #MATCH_DEFAULT_ONLY
* @see #GET_INTENT_FILTERS
* @see #GET_RESOLVED_FILTER
*/
public abstract List<ResolveInfo> queryIntentActivities(Intent intent,
int flags);
看兩個方法的註釋
resolveActivity返回最佳匹配,找不到匹配的返回null
queryIntentActivities 返回所有的,找不到匹配的返回null
flags必須是CATEGORY_DEFAULT,增加catogory匹配規則,否則會忽略category匹配,那麼可能會導致startactivity/startservice失敗
最後實現肯定是通過PMS(PackageManagerService)執行對應方法,IBinder通信
綜合前面,AMS,WMS,PMS都介紹過了。
例子
<activity
android:name=".TestActivity"
android:label="@string/title_activity_test"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.TestActivity"/>
<category android:name="android.intent.category.DEFAULT"/>
<data
android:host="baidu"
android:mimeType="image/png"
android:scheme="http"/>
</intent-filter>
</activity>
@OnClick(R.id.but)
void OnClick() {
Intent intent = new Intent();
intent.setAction("android.intent.action.TestActivity");
intent.setDataAndType(Uri.parse("http://baidu:8888/abc/..."), "image/png");
PackageManager pm = getPackageManager();
if (pm.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY) != null) {
startActivity(intent);
}else{
Log.d("LiaBin","no match intent");
}
}