使用 Intent 在活動之間切換
從主活動跳轉到其他活動
使用顯式 Intent。
我們新增一個空白活動,命名為 AddCourseActivity,記得勾選「產生布局檔」。
但不要勾選 Launcher Activity 選項。
Intent
Intent 是 Android 程式中各元件之間互動的一種重要方式。
它不僅可以指明目前元件想要執行的動作,還能在不同元件之間傳遞資料。
Intent 分為:顯式 Intent 和隱式 Intent
Intent 有多個建構函式。
我在主活動的按鈕上實例化一個 Intent,從主活動跳到第二個活動。
// 先初始化一個 Intent,指定從哪裡到哪裡
Intent it = new Intent(FirstActivity.this, AddCourseActivity.class);
startActivity(it);Code language: JavaScript (javascript)
隱式 Intent 的使用
相較於顯式 Intent,隱式 Intent 不需要指明要啟動哪個活動,而是指定一系列更抽象的 action 和 category。
然後讓系統分析這個 Intent,幫我們找出合法的活動來啟動。
我們修改 AndroidManifest.xml。
給第二個活動加上 action 和 category。
action 用來指明這個活動可以回應此 action。
<activity android:name=".AddCourseActivity">
<intent-filter>
<action android:name="com.foxdevelop.www.activitydemo.ACTION_START" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>Code language: HTML, XML (xml)
只有當 Intent 能夠匹配活動的 action 和 category 時,該活動才能回應 Intent。
// 初始化一個 Intent,讓它去匹配 AndroidManifest.xml 中對應的 action
Intent it = new Intent("com.foxdevelop.www.activitydemo.ACTION_START");
startActivity(it);Code language: JavaScript (javascript)
為什麼不需要匹配 category?
因為我們的這個活動使用的是 android.intent.category.DEFAULT。
這是一個預設值。
當我們呼叫 startActivity 時,會自動傳入 DEFAULT。
每個 Intent 只能指定一個 action,但可以指定多個 category。
目前是 DEFAULT,所以我們不用額外添加。
如果需要添加其他 category:
// 初始化 Intent 匹配 action,同時加入 category
Intent it = new Intent("com.foxdevelop.www.activitydemo.ACTION_START");
it.addCategory("com.foxdevelop.www.activitydemo.MY_CATEGORY");
it.addCategory("com.foxdevelop.www.activitydemo.MY_CATEGORY1111111");
startActivity(it);Code language: JavaScript (javascript)
點擊「新增課程」選單後,程式出錯了。
原因是我們給 intent 增加了一個 category,但第二個活動並沒有宣告這個 category。
所以我們需要把這個 category 加上去。
<activity android:name=".AddCourseActivity">
<intent-filter>
<action android:name="com.foxdevelop.www.activitydemo.ACTION_START" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="com.foxdevelop.www.activitydemo.MY_CATEGORY" />
</intent-filter>
</activity>Code language: HTML, XML (xml)
注意:
如果 intent 有多個 category,並不是只要符合其中一個就可以,而是「所有」category 都必須匹配才行。
<activity android:name=".AddCourseActivity">
<intent-filter>
<action android:name="com.foxdevelop.www.activitydemo.ACTION_START" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="com.foxdevelop.www.activitydemo.MY_CATEGORY" />
</intent-filter>
</activity>Code language: HTML, XML (xml)
case R.id.add:
// 初始化 Intent 匹配 action,同時加入 category
Intent it = new Intent("com.foxdevelop.www.activitydemo.ACTION_START");
it.addCategory("com.foxdevelop.www.activitydemo.MY_CATEGORY2222222");
//it.addCategory("android.intent.category.DEFAULT");
startActivity(it);
break;Code language: JavaScript (javascript)
使用隱式 Intent 開啟網頁
隱式 Intent 還有很多其他功能可以實現。
它不只能啟動同一個程式的活動,還能啟動其他程式的活動。
這讓多個應用程式之間的功能共享成為可能。
例如微信聊天時,朋友傳給你一個地址,你可以選擇用 QQ 瀏覽器開啟。
下面我們來試試看:
Intent it = new Intent(Intent.ACTION_VIEW); // 系統內建的 Action
it.setData(Uri.parse("http://www.foxdevelop.com")); // 開啟一個網址
startActivity(it);Code language: JavaScript (javascript)
http:// 不能省略,否則會報錯。
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.foxdevelop.www.activitydemo, PID: 8917
android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.VIEW dat=www.foxdevelop.com }
at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:1809)
at android.app.Instrumentation.execStartActivity(Instrumentation.java:1523)
at android.app.Activity.startActivityForResult(Activity.java:4224)
at android.support.v4.app.BaseFragmentActivityApi16.startActivityForResult(BaseFragmentActivityApi16.java:54)
at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java:68)Code language: PHP (php)
使用隱式 Intent 撥打電話
可以呼叫 tel 協定來打電話
上節課我們用 http 協定開啟網域。
例如下面嘗試撥打 10010。

Intent it = new Intent(Intent.ACTION_DIAL); // 系統內建的 Action
it.setData(Uri.parse("tel:10010")); // 撥打這支電話,需要使用者確認
startActivity(it);Code language: JavaScript (javascript)
活動之間傳遞資料
Intent 可以傳遞資料
intent 英[ɪnˈtent] 美[ɪnˈtɛnt] 意圖,目的;意思,含義。
使用它的 putExtra 方法可以傳遞資料。
然後在第二個活動中,透過呼叫 getStringExtra 方法可以取得傳過來的資料。
在第二個活動中可以呼叫 getIntent 方法取得 Intent。
當然,如果傳的是整數,可以使用 getIntExtra 方法取得。
首先在第一個活動裡面:
Intent it = new Intent(FirstActivity.this, AddCourseActivity.class);
it.putExtra("site", "www.foxdevelop.com");
it.putExtra("name", "FoxDevelop");
startActivity(it);Code language: JavaScript (javascript)
接著在第二個活動取得 Intent 物件,然後就能取得裡面的值。
在第二個活動的 onCreate 方法裡:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_course_acticity);
Intent it = getIntent();
String site = it.getStringExtra("site");
String name = it.getStringExtra("name");
int version = it.getIntExtra("version", 1);
Log.e(TAG, site);
}Code language: JavaScript (javascript)
返回資料給前一個活動
當我們退出目前活動時
活動中有一個 startActivityForResult 方法,可以在活動銷毀前返回一個結果給上一個活動。
該方法接收兩個參數:第一個是 Intent,第二個是請求碼,用於之後的回調中判斷資料的來源。
在活動銷毀之前,使用 setResult 方法可以向上一個活動返回結果。一般使用 RESULT_OK 或 RESULT_CANCELED,第二個參數則是把帶資料的 Intent 傳回去。
我們可以給 Intent 使用 putExtra 設定值。
由於我們在上個活動使用了 startActivityForResult 來啟動第二個活動,所以當第二個活動銷毀後,會觸發第一個活動的 onActivityResult 方法。在這裡我們可以取得 Intent 和結果編碼。
如果使用者不是點擊按鈕退回,而是使用 back 鍵退回,這時需要重寫第二個活動的 onBackPressed 方法才行。
1. 在第一個活動啟動 Intent 時
Intent it = new Intent(FirstActivity.this, AddCourseActivity.class);
it.putExtra("site", "www.foxdevelop.com");
it.putExtra("name", "FoxDevelop");
it.putExtra("version", 1);
startActivityForResult(it, 1);Code language: JavaScript (javascript)
2. 第一個活動中重寫
public class FirstActivity extends AppCompatActivity {
private static final String TAG = "FirstActivity";
// 重寫第一個活動的方法,當第二個活動退出就會執行這裡的程式碼
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK) {
String h = data.getStringExtra("hot");
Log.d(TAG, h);
}
super.onActivityResult(requestCode, resultCode, data);
}Code language: JavaScript (javascript)
3. 在第二個活動中
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_course_acticity);
// 取得上一個活動的資料
Intent it = getIntent();
String site = it.getStringExtra("site");
String name = it.getStringExtra("name");
int version = it.getIntExtra("version", 1);
Log.e(TAG, site);
// 給按鈕加上退回事件,在事件裡給 Intent 賦值,設定結果編碼,同時結束活動
Button b = findViewById(R.id.button);
b.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent it = getIntent();
it.putExtra("hot", "熱門課程");
setResult(RESULT_OK, it);
finish();
}
});
}Code language: JavaScript (javascript)
當我們退回主活動時,就會觸發事件並輸出日誌。
05-12 06:17:46.741 12960-12960/com.foxdevelop.www.activitydemo D/FirstActivity: 熱門課程
如果想要退回鍵也能返回資料
需要重寫 onBackPressed。
我們在第二個活動中重寫:
// 這個方法是當我們按退回鍵時觸發
@Override
public void onBackPressed() {
Intent it = getIntent();
it.putExtra("hot", "最新課程");
setResult(RESULT_OK, it);
finish();
}Code language: JavaScript (javascript)
05-12 06:23:08.654 13209-13209/com.foxdevelop.www.activitydemo D/FirstActivity: 熱門課程
05-12 06:23:16.405 13209-13209/com.foxdevelop.www.activitydemo D/FirstActivity: 最新課程
05-12 06:23:35.612 13209-13209/com.foxdevelop.www.activitydemo D/FirstActivity: 最新課程