Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> [Android]Intent的使用

[Android]Intent的使用

編輯:關於Android編程

Intent 是 Android 程序中各組件之間進行交互的一種重要方式,它不僅可以指明當前組件想要執行的動作,還可以在不同組件之間傳遞數據。Intent 一般可被用於啟動活動、啟動服務、以及發送廣播等場景。

Intent的使用包括兩種方式:

顯式Intent

隱式Intent

其中,隱式也包含多種方式。

一、顯式Intent

在前一篇文章中,我們已經詳細說明了怎麼創建一個Activity,再
創建一個活動2,新建一個 second_layout.xml 布局文件,代碼如下:



    

我們還是定義一個按鈕,按鈕上顯示 Button 2。然後新建活動 SecondActivity 繼承自
Activity,代碼如下:

public class SecondActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.second_layout);
    }
}

最後在 AndroidManifest.xml 中為 SecondActivity 進行注冊。



    
        
            
            
        
    

    
    

由於 SecondActivity 不是主活動,因此不需要配置標簽裡的內容,注冊活動的代碼也是簡單了許多。現在第二個活動已經創建完成,剩下的問題就是如何去啟動這第二個活動了。

Intent 有多個構造函數的重載,其中一個是:

 Intent(Context packageContext, Class cls)

這個構造函數接收兩個參數,第一個參數 Context 要求提供一個啟動活動的上下文,第二個參數 Class 則是指定想要啟動的目標活動, 通過這個構造函數就可以構建出 Intent 的 “意圖” 。

然後我們應該怎麼使用這個 Intent 呢?Activity 類中提供了一個 startActivity()方法, 這個方法是專門用於啟動活動的, 它接收一個 Intent參數, 這裡我們將構建好的 Intent傳入 startActivity()方法就可以啟動目標活動了。

修改 FirstActivity 中按鈕的點擊事件,代碼如下所示:

button1.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
        startActivity(intent);
    }
});

我們首先構建出了一個 Intent,傳入 FirstActivity.this作為上下文,傳入 SecondActivity.class作為目標活動,這樣我們的“意圖”就非常明顯了,即在 FirstActivity 這個活動的基礎上打開 SecondActivity 這個活動。然後通過 startActivity()方法來執行這個 Intent。
這裡寫圖片描述vcnP0ru49rvutq/U9cO0sOzE2KO/uty88rWlo6ywtM/CIEJhY2sgvPy+zb/J0tTP+rvZtbHHsLvutq+jrLTTtvi72LW9yc/Su7j2u+62r8HLoaPKudPD1eLW1re9yr3AtMb0tq+77ravo6xJbnRlbnQgtcQmbGRxdW870uLNvCZyZHF1bzu3x7Ojw/fP1KOs0vK0y87Sw8ezxtauzqrP1Mq9IEludGVudKGjPC9wPg0KPGgyIGlkPQ=="二隱式intent">二、隱式Intent

1. 應用內部Intent

相比於顯式 Intent,隱式 Intent 則含蓄了許多,它並不明確指出我們想要啟動哪一個活動, 而是指定了一系列更為抽象的 action 和 category 等信息, 然後交由系統去分析這個 Intent,並幫我們找出合適的活動去啟動。

什麼叫做合適的活動呢?簡單來說就是可以響應我們這個隱式 Intent 的活動,那麼目前SecondActivity 可以響應什麼樣的隱式 Intent 呢?

通過在標簽下配置的內容,可以指定當前活動能夠響應的 action和 category,打開 AndroidManifest.xml,添加如下代碼:


    
        
        
    

在 標簽中我們指明了當前活動可以響應com.example.activitytest.ACTION_START 這個 action,而標簽則包含了一些附加信息,更精確地指明了當前的活動能夠響應的 Intent 中還可能帶有的 category。只有和中的內容同時能夠匹配上 Intent 中指定的 action 和 category 時,這個活動才能響應該 Intent。

修改 FirstActivity 中按鈕的點擊事件,代碼如下所示:

button1.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        Intent intent = new Intent("com.example.activitytest.ACTION_START");
        startActivity(intent);
    }
});

可以看到,我們使用了 Intent 的另一個構造函數,直接將 action 的字符串傳了進去,表明我們想要啟動能夠響應 com.example.activitytest.ACTION_START 這個 action 的活動。那前
面不是說要 和 同時匹配上才能響應的嗎?怎麼沒看到哪裡有指定category 呢?這是因為 android.intent.category.DEFAULT 是一種默認的 category,在調用
startActivity()方法的時候會自動將這個 category 添加到 Intent 中。

重新運行程序,在 FirstActivity 的界面點擊一下按鈕,你同樣成功啟動 SecondActivity了。不同的是,這次你是使用了隱式 Intent 的方式來啟動的,說明我們在標簽下配置的 action 和 category 的內容已經生效了!

每個 Intent 中只能指定一個 action,但卻能指定多個 category。目前我們的 Intent 中只有一個默認的 category,那麼現在再來增加一個吧。

修改 FirstActivity 中按鈕的點擊事件,代碼如下所示:

button1.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        Intent intent = new Intent("com.example.activitytest.ACTION_START");
        intent.addCategory("com.example.activitytest.MY_CATEGORY");
        startActivity(intent);
    }
});

可以調用 Intent 中的 addCategory()方法來添加一個 category,這裡我們指定了一個自定義的 category,值為 com.example.activitytest.MY_CATEGORY。
現在重新運行程序,在 FirstActivity 的界面點擊一下按鈕,你會發現,程序崩潰了!這是你第一次遇到程序崩潰,可能會有些束手無策。別緊張,其實大多數的崩潰問題都是很好解決的,只要你善於分析。在 LogCat 界面查看錯誤日志,你會看到如圖所示的錯誤信息。
這裡寫圖片描述
錯誤信息中提醒我們,沒有任何一個活動可以響應我們的 Intent,為什麼呢?這是因為我們剛剛在 Intent 中新增了一個 category,而 SecondActivity 的標簽中並沒有聲明可以響應這個 category,所以就出現了沒有任何活動可以響應該 Intent 的情況。現在我們在中再添加一個 category 的聲明,如下所示:


    
        
        
        
    

再次重新運行程序,你就會發現一切都正常了。

2.啟動應用外Intent

使用隱式 Intent,我們不僅可以啟動自己程序內的活動,還可以啟動其他程序的活動,這使得 Android 多個應用程序之間的功能共享成為了可能。比如說你的應用程序中需要展示一個網頁,這時你沒有必要自己去實現一個浏覽器(事實上也不太可能) ,而是只需要調用系統的浏覽器來打開這個網頁就行了。

修改 FirstActivity 中按鈕點擊事件的代碼,如下所示:

button1.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        Intent intent = new Intent(Intent.ACTION_VIEW);
        intent.setData(Uri.parse("http://www.baidu.com"));
        startActivity(intent);
    }
});

這裡我們首先指定了 Intent 的 action 是 Intent.ACTION_VIEW, 這是一個 Android 系統內置的動作,其常量值為 android.intent.action.VIEW。然後通過 Uri.parse()方法,將一個網址字符串解析成一個 Uri 對象,再調用 Intent 的 setData()方法將這個 Uri 對象傳遞進去。重新運行程序,在 FirstActivity 界面點擊按鈕就可以看到打開了系統浏覽器,如圖所示:
這裡寫圖片描述

上述的代碼中,可能你會對 setData()部分感覺到陌生,這是我們前面沒有講到過的。這個方法其實並不復雜,它接收一個 Uri 對象,主要用於指定當前 Intent 正在操作的數據,而這些數據通常都是以字符串的形式傳入到 Uri.parse()方法中解析產生的。與此對應,我們還可以在標簽中再配置一個標簽,用於更精確地指定當前活動能夠響應什麼類型的數據。標簽中主要可以配置以下內容。

android:scheme
用於指定數據的協議部分,如上例中的 http 部分。 android:host
用於指定數據的主機名部分,如上例中的 www.baidu.com 部分。 android:port
用於指定數據的端口部分,一般緊隨在主機名之後。 android:path
用於指定主機名和端口之後的部分,如一段網址中跟在域名之後的內容。 android:mimeType
用於指定可以處理的數據類型,允許使用通配符的方式進行指定。

只有標簽中指定的內容和 Intent 中攜帶的 Data 完全一致時,當前活動才能夠響應該 Intent。不過一般在標簽中都不會指定過多的內容,如上面浏覽器示例中,其實只需要指定 android:scheme 為 http,就可以響應所有的 http 協議的 Intent 了。

為了讓你能夠更加直觀地理解,我們來自己建立一個活動,讓它也能響應打開網頁的Intent。新建 third_layout.xml 布局文件,代碼如下:



    

然後新建活動 ThirdActivity 繼承自 Activity,代碼如下:

public class ThirdActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.third_layout);
    }
}

最後在 AndroidManifest.xml 中為 ThirdActivity 進行注冊。


    
        
        
        
    

我 們 在 ThirdActivity 的 中 配 置 了 當 前 活 動 能 夠 響 應 的 action 是Intent.ACTION_VIEW 的常量值,而 category 則毫無疑問指定了默認的 category 值,另外在標簽中我們通過 android:scheme 指定了數據的協議必須是 http 協議, 這樣 ThirdActivity應該就和浏覽器一樣,能夠響應一個打開網頁的 Intent 了。讓我們運行一下程序試試吧,在FirstActivity 的界面點擊一下按鈕,結果如圖所示:
這裡寫圖片描述

可以看到,系統自動彈出了一個列表,顯示了目前能夠響應這個 Intent 的所有程序。點擊 Browser 還會像之前一樣打開浏覽器,並顯示百度的主頁,而如果點擊了 ActivityTest,則會啟動 ThirdActivity。需要注意的是,雖然我們聲明了 ThirdActivity 是可以響應打開網頁的Intent 的,但實際上這個活動並沒有加載並顯示網頁的功能,所以在真正的項目中盡量不要去做這種有可能誤導用戶的行為,不然會讓用戶對我們的應用產生負面的印象。除了 http 協議外,我們還可以指定很多其他協議,比如 geo 表示顯示地理位置、tel 表示撥打電話。下面的代碼展示了如何在我們的程序中調用系統撥號界面。

button1.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        Intent intent = new Intent(Intent.ACTION_DIAL);
        intent.setData(Uri.parse("tel:10086"));
        startActivity(intent);
    }
});

首先指定了 Intent 的 action 是 Intent.ACTION_DIAL,這又是一個 Android 系統的內置動作。然後在 data 部分指定了協議是 tel,號碼是 10086。重新運行一下程序,在 FirstActivity的界面點擊一下按鈕,結果如圖所示:
這裡寫圖片描述

3. 向下一個活動傳遞數據

在啟動活動時傳遞數據的思路很簡單,Intent 中提供了一系列 putExtra()方法的重載,可以把我們想要傳遞的數據暫存在 Intent 中,啟動了另一個活動後,只需要把這些數據再從Intent 中取出就可以了。比如說 FirstActivity 中有一個字符串,現在想把這個字符串傳遞到SecondActivity 中,你就可以這樣編寫:

button1.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        String data = "Hello SecondActivity";
        Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
        intent.putExtra("extra_data", data);
        startActivity(intent);
    }
});

這裡我們還是使用顯式 Intent 的方式來啟動 SecondActivity,並通過 putExtra()方法傳遞了一個字符串。注意這裡 putExtra()方法接收兩個參數,第一個參數是鍵,用於後面從 Intent中取值,第二個參數才是真正要傳遞的數據。

然後我們在 SecondActivity 中將傳遞的數據取出,並打印出來,代碼如下所示:

public class SecondActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.second_layout);
        Intent intent = getIntent();
        String data = intent.getStringExtra("extra_data");
        Log.d("SecondActivity", data);
    }
}

首先可以通過 getIntent()方法獲取到用於啟動 SecondActivity 的 Intent,然後調用getStringExtra()方法,傳入相應的鍵值,就可以得到傳遞的數據了。這裡由於我們傳遞的是字符串,所以使用 getStringExtra()方法來獲取傳遞的數據,如果傳遞的是整型數據,則使用getIntExtra()方法,傳遞的是布爾型數據,則使用 getBooleanExtra()方法,以此類推。

重新運行程序,在 FirstActivity 的界面點擊一下按鈕會跳轉到 SecondActivity,查看LogCat 打印信息,如圖所示:
這裡寫圖片描述

4. 返回數據給上一個活動

既然可以傳遞數據給下一個活動,那麼能不能夠返回數據給上一個活動呢?答案是肯定的。不過不同的是,返回上一個活動只需要按一下 Back 鍵就可以了,並沒有一個用於啟動活動 Intent 來傳遞數據。通過查閱文檔你會發現,Activity 中還有一個 startActivityForResult()方法也是用於啟動活動的,但這個方法期望在活動銷毀的時候能夠返回一個結果給上一個活動。毫無疑問,這就是我們所需要的。

startActivityForResult()方法接收兩個參數,第一個參數還是 Intent,第二個參數是請求碼,用於在之後的回調中判斷數據的來源。我們還是來實戰一下,修改 FirstActivity 中按鈕的點擊事件,代碼如下所示:

button1.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
        startActivityForResult(intent, 1);
    }
});

這裡我們使用了 startActivityForResult()方法來啟動 SecondActivity,請求碼只要是一個唯一值就可以了,這裡傳入了 1。接下來我們在 SecondActivity 中給按鈕注冊點擊事件,並在點擊事件中添加返回數據的邏輯,代碼如下所示:

public class SecondActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.second_layout);
        Button button2 = (Button) findViewById(R.id.button_2);

        button2.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent();
                intent.putExtra("data_return", "Hello FirstActivity");
                setResult(RESULT_OK, intent);
                finish();
            }
        });
    }
}

可以看到,我們還是構建了一個 Intent,只不過這個 Intent 僅僅是用於傳遞數據而已,它沒有指定任何的“意圖” 。緊接著把要傳遞的數據存放在 Intent 中,然後調用了 setResult()方法。這個方法非常重要,是專門用於向上一個活動返回數據的。setResult()方法接收兩個參數 ,第 一個 參數 用於 向上一 個活 動返 回處 理結果 ,一 般只 使用 RESULT_OK 或RESULT_CANCELED 這兩個值,第二個參數則是把帶有數據的 Intent 傳遞回去,然後調用了 finish()方法來銷毀當前活動。

由於我們是使用 startActivityForResult()方法來啟動 SecondActivity 的,在 SecondActivity被銷毀之後會回調上一個活動的 onActivityResult()方法,因此我們需要在 FirstActivity 中重寫這個方法來得到返回的數據,如下所示:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
        case 1:
            if (resultCode == RESULT_OK) {
                String returnedData = data.getStringExtra("data_return");
                Log.d("FirstActivity", returnedData);
            }
            break;
        default:
    }
}

onActivityResult()方法帶有三個參數,第一個參數 requestCode,即我們在啟動活動時傳入的請求碼。 第二個參數 resultCode, 即我們在返回數據時傳入的處理結果。 第三個參數 data,即攜帶著返回數據的 Intent。由於在一個活動中有可能調用 startActivityForResult()方法去啟
動很多不同的活動,每一個活動返回的數據都會回調到 onActivityResult()這個方法中,因此我 們 首 先 要 做 的 就 是 通 過 檢 查 requestCode 的 值 來 判 斷 數 據 來 源 。 確 定 數 據 是 從SecondActivity 返回的之後,我們再通過 resultCode 的值來判斷處理結果是否成功。最後從data 中取值並打印出來,這樣就完成了向上一個活動返回數據的工作。

重 新運 行程 序, 在 FirstActivity 的 界面 點擊 按鈕 會 打開 SecondActivity , 然後 在SecondActivity 界面點擊 Button 2 按鈕會回到 FirstActivity,這時查看 LogCat 的打印信息,如圖所示:
這裡寫圖片描述

可以看到,SecondActivity 已經成功返回數據給 FirstActivity 了。
這時候你可能會問,如果用戶在 SecondActivity 中並不是通過點擊按鈕,而是通過按下Back 鍵回到 FirstActivity,這樣數據不就沒法返回了嗎?沒錯,不過這種情況還是很好處理的,我們可以通過重寫 onBackPressed()方法來解決這個問題,代碼如下所示:

@Override
public void onBackPressed() {
    Intent intent = new Intent();
    intent.putExtra("data_return", "Hello FirstActivity");
    setResult(RESULT_OK, intent);
    finish();
}

這樣的話,當用戶按下 Back 鍵,就會去執行 onBackPressed()方法中的代碼,我們在這裡添加返回數據的邏輯就行了。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved