Android啓動一個界面,可以通過顯示和隱式兩種方式。
(一)activity的跳轉方式小結
地址:https://github.com/buder-cp/base_component_learn/tree/master/URIJump
方式一:顯示啓動,通過類名
一般應用內部跳轉會經常使用該方法。
/**
* 方式一:類名跳轉
*/
Intent intent = new Intent(MainActivity.this, Main2Activity.class);
startActivity(intent);
方式二:通過ComponentName跳轉
通過組件名稱跳轉需要知道包名和Activity名稱,該方法一般用於外部應用跳轉。
Intent it = new Intent();
ComponentName componentName = new ComponentName("com.test.helleworld", "com.test.helloworld.ActivityA");
it.setComponent(componentName);
startActivity(it);
方式三:通過包名、類名跳轉
與上述方法類似,都需要知道包名和Activit名稱,其實setClassNmae裏面也是通過設置ComponentName的,該方法一般用於外部應用跳轉。
Intent it = new Intent();
it.setClassName("com.test.helleworld", "com.test.helloworld.ActivityA");
startActivity(it);
方式四:根據包名跳轉
根據應用包名跳轉,這裏打開的是跳轉應用的默認啓動Activity。
PackageManager pm = getPackageManager();
Intent it = pm.getLaunchIntentForPackage("com.test.helloworld");
//it.setAction("android.intent.action.MAIN");
startActivity(it);
方式五:隱式啓動利用action,通過在AndroidManifest中定義intentfilter進行action的匹配
不需要指定跳轉的Activity名字,只需雙方協定好指定的action即可,該方法一般常用於外部應用跳轉。
- 步驟一:在啓動界面new Intent中定義好我們要跳轉到界面的action,這個action名字可以隨意起,例如這裏是self_define_action
/**
* 方式二:action跳轉
*/
Intent intent1 = new Intent("self_define_action");
startActivity(intent1);
- 步驟二:在被啓動界面的manifest文件中定義好和上面對應的action
<activity android:name=".Main2Activity" android:exported="true">
<intent-filter>
<!--配置action路徑-->
<action android:name="self_define_action" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
方式三:隱式啓動,利用URI,和上面的action類似,只是這裏由action轉成了uri
- 步驟一:首先需要定義符合URI通信的協議,這裏很簡單:hello://test.uri.activity?action=123&secret=buder
(1)scheme協議:hello
(2)host路由地址:test.uri.activity
(3)?query參數:query參數可以有多個,是鍵值對的表示方式,鍵值對之間用&連接。本例中key=action,value=123
- 步驟二:協議定義好後,需要在intent中添加上action字段,這裏我們還是自定義self_define_uri作爲action字段
/**
* 方式三:URI跳轉
*/
String uriString = "hello://test.uri.activity?action=123&secret=buder";
Uri uri = Uri.parse(uriString);
Intent intent = new Intent("self_define_uri");
//Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(uri);
startActivity(intent);
- 步驟三:在被跳轉的activity的manifest文件中聲明好和上面兩步對應的協議字段
本例中,action爲self_define_uri;scheme爲hello;host爲test.uri.activity
<activity android:name=".Main2Activity" android:exported="true">
<intent-filter>
<!-- <action android:name="android.intent.action.VIEW" />-->
<action android:name="self_define_uri" />
<category android:name="android.intent.category.DEFAULT" />
<data
android:scheme="hello"
android:host="test.uri.activity" />
</intent-filter>
</activity>
- 步驟四:當我們業務中需要傳過來的參數時,在接收方這麼獲取穿過來的參數:
Intent intent = getIntent();
if (null != intent) {
Uri uri = intent.getData();
if (uri == null) {
return;
}
String actionData = uri.getQueryParameter("action");
String secretData = uri.getQueryParameter("secret");
TextView tv = findViewById(R.id.txt);
tv.append("\n傳過來的action值爲:" + actionData);
tv.append("\n傳過來的secret值爲:" + secretData);
}
(二)activity傳參小結
intent傳遞參數的方式有兩種,一種是大家熟悉的extra,鍵值對的形式,直接傳遞參數;另一種就是uri的方式。
方式一:intent傳參,將參數放到bundle中
如下例子中,有一個playInfo的key裏面有一個JSONObject的字符串:
Intent intent = new Intent(ACTION_DETAIL);
Bundle bundle = new Bundle();
JSONObject playInfoJsonObject = new JSONObject();
try {
playInfoJsonObject.put("playType", "");
playInfoJsonObject.put("videoId", content.related_aids);
playInfoJsonObject.put("episodeId", content.related_vids);
playInfoJsonObject.put("history", "-1");
playInfoJsonObject.put("chnId", "");
playInfoJsonObject.put("customer", PACKAGE_NAME);
} catch (JSONException e) {
e.printStackTrace();
}
String playInfo = playInfoJsonObject.toString();
bundle.putString("playInfo", playInfo);
intent.putExtras(bundle);
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
context.startActivity(intent);
} catch (ActivityNotFoundException e) {
e.printStackTrace();
}
方式二:使用URI,需要先拼接URI地址
先來認識下URI,如下這個字符串就是一個URI地址例子:
String str = "content://com.android.test?username=merlin&password=123456";
它的文件結構如下:
[scheme:][//authority][path][?query][#fragment]
其中有下面幾個規則:
- path可以有多個,每個用/連接,比如
scheme://authority/path1/path2/path3?query#fragment
- query參數可以帶有對應的值,也可以不帶,如果帶對應的值用=表示,如:
scheme://authority/path1/path2/path3?id = 1#fragment,這裏有一個參數id,它的值是1
- query參數可以有多個,每個用&連接
scheme://authority/path1/path2/path3?id = 1&name = mingming&old#fragment
這裏有三個參數:
參數1:id,其值是:1
參數2:name,其值是:mingming
參數3:old,沒有對它賦值,所以它的值是null
- 在android中,除了scheme、authority是必須要有的,其它的幾個path、query、fragment,它們每一個可以選擇性的要或不要,但順序不能變,比如:
其中"path"可不要:scheme://authority?query#fragment
其中"path"和"query"可都不要:scheme://authority#fragment
其中"query"和"fragment"可都不要:scheme://authority/path
"path","query","fragment"都不要:scheme://authority
等等……
對於URI,我們平時的用法如下:
Uri uri = Uri.parse("qijian://test.uri.activity?action=1");
Intent intent = new Intent("android.qijian.schemeurl.activity");
intent.setData(uri);
startActivity(intent);
有時候需要我們去拼裝這些URI,常用代碼如下:
public static Uri getRouteUri(Action action){
try {
Uri.Builder builder=new Uri.Builder();
builder.scheme(action.scheme);
builder.authority(action.host);
builder.path(action.path);
Map<String, String> query=action.query;
if(query!=null&&!query.isEmpty()){
for (Map.Entry<String, String> entry:query.entrySet()){
builder.appendQueryParameter(entry.getKey(), entry.getValue());
}
}
return builder.build();
} catch (Exception e) {
Log.e(TAG, "getRouteUri: build route uri error, action="+action, e);
return null;
}
}
(三)啓動三方APP的方式小結
兩種啓動三方APP包的方式:
if (!TextUtils.isEmpty(packageName)) {
Intent intent;
if (!TextUtils.isEmpty(className)) {
ComponentName componentName = new ComponentName(packageName, className);
intent = new Intent();
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.setComponent(componentName);
intent.setAction(Intent.ACTION_VIEW);
intent.putExtra(CUSTOM_PARAMS, params);
} else {
intent = context.getPackageManager().getLaunchIntentForPackage(packageName);
intent.putExtra(CUSTOM_PARAMS, params);
}
context.startActivity(intent);
}