Android開發(fā) - Intent

什么是Intent

Intent是Android程序總各組件之間進(jìn)行交互的一種重要方式,它不僅可以指明當(dāng)前組件想要執(zhí)行的動作,還可以再不同組件之間傳遞數(shù)據(jù)。Intent一般可用于啟動活動、啟動服務(wù)以及發(fā)送廣播等場景。

Intent分類

  • 顯示Intent

Intent有很多構(gòu)造函數(shù)重載,其中一個是Intent(Context packageContext, Class<?>cls)。該函數(shù)接受兩個參數(shù),第一個參數(shù)是Context要求提供一個啟動活動的上下文,第二個參數(shù)Class則是指定想要啟動的目標(biāo)活動,通過這個構(gòu)造函數(shù)就可以創(chuàng)建出Intent的“意圖”。再使用startActivity()方法啟動活動,該方法接收一個Intent參數(shù),只需要將上邊創(chuàng)建好的Intent傳入該函數(shù)即可

創(chuàng)建兩個Activity,F(xiàn)irstActivity(主活動)和SecondActivity,在FirstActivity中創(chuàng)建一個按鈕,點(diǎn)擊之后進(jìn)入SecondActivity

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.first_layout);
        Button button = (Button)findViewById(R.id.button_1);
        button.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                // 構(gòu)建Intent,傳入FirstActivity.this作為上下文,傳入SecondActivity.class作為目標(biāo)活動
                Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
                // 這樣"意圖"就比較明顯了,即在FirstActivity這個活動的基礎(chǔ)上打來SecondActivity這個活動,執(zhí)行Intent
                startActivity(intent);
            }
        });
    }

運(yùn)行后就可以成功啟動SecondActivity了,如果想回到上一個活動,只要按下Back鍵就可以銷毀當(dāng)前活動,回到上一個活動了

  • 使用隱式Intent

相比于顯式Intent,隱式Intent并不明確指出想要啟動哪一個活動,而是指定一系列更為抽象的action和category等信息,然后交由系統(tǒng)去分析這個Intent,并找出合適的活動去啟動

那么什么是合適的活動呢?簡答來說就是可以響應(yīng)這個隱式Intent的活動。對于SecondActivity可以響應(yīng)什么樣的隱式Intent呢?通過在<activity>標(biāo)簽下配置<intent-filter>的內(nèi)容,可以指定當(dāng)前活動能夠響應(yīng)的action和category,打開AndroidMainfest.xml,添加如下代碼

<activity android:name=".SecondActivity">
            <intent-filter>
                <action android:name="com.znty.activitytest.ACTION_START" />
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
        </activity>

在<action>標(biāo)簽中,指明了當(dāng)前活動可以響應(yīng)com.znty.xietao.activitytest.ACTION_START這個action,而<category>標(biāo)簽則包含了一些附加信息,更明確地指明了當(dāng)前的活動能夠響應(yīng)的Intent中還可能帶有category。只有<action>和<category>中的內(nèi)容同時能夠匹配上Intent中指定的action和category時,這個活動才能響應(yīng)該Intent(就是起個名和分個類)。

回到FirstActivity中的按鈕事件,修改為:

Button button = (Button)findViewById(R.id.button_1);
        button.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                Intent intent = new Intent("com.znty.activitytest.ACTION_START");
                startActivity(intent);
            }
        });

可以看到使用了Intent的另外一個構(gòu)造函數(shù),直接將action的字符串傳進(jìn)去,表明想要啟動能夠響應(yīng)“com.znty.xietao.activitytest.ACTION_START”這個action的活動,由于category設(shè)置的是DEFAULT,這是一種默認(rèn)的category,在調(diào)用startActivity()方法的時候會自動將這個category添加到Intent中。

重新運(yùn)行程序,可以得到和顯示Intent使用一樣的效果,這里使用的是隱式Intent,這就說明了在<activity>標(biāo)簽下設(shè)置的action和category的內(nèi)容生效了

每個Intent只能指定一個action,但卻能指定多個category。現(xiàn)在在Intent中除了默認(rèn)的category,再添加一個category。調(diào)用Intent的addcategory()方法來添加一個category

Button button = (Button)findViewById(R.id.button_1);
        button.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                Intent intent = new Intent("com.znty.activitytest.ACTION_START");
                intent.addCategory("com.zntq.activitytest.MY_CATEGORY");
                startActivity(intent);
            }
        });

同時需要在AndroidManifest.xml中進(jìn)行設(shè)置,否則的話整個程序就會直接閃退

<activity android:name=".SecondActivity">
            <intent-filter>
                <action android:name="com.znty.activitytest.ACTION_START" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="com.zntq.activitytest.MY_CATEGORY" />
            </intent-filter>
        </activity>

這樣再一次運(yùn)行之后,就會發(fā)現(xiàn)一切都正常了

更多隱式Intent的用法

使用隱式Intent不僅可以啟動自己程序內(nèi)的活動,還可以啟動其他程序的活動,這使得Android多個應(yīng)用程序之間的功能共享成為了可能。比如在應(yīng)用程序中需要展示一個網(wǎng)頁,只需要調(diào)用系統(tǒng)的瀏覽器來打開這個網(wǎng)頁就行

Button button = (Button)findViewById(R.id.button_1);
        button.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(Intent.ACTION_VIEW);
                // Intent.ACTION_VIEW是一個Android系統(tǒng)內(nèi)置的動作,它的常量值是"android.intent.action.VIEW"
                intent.setData(Uri.parse("http://www.baidu.com"));
                // 通過Uri.parse()方法,將一個網(wǎng)址字符串解析成一個UR對象,再調(diào)用Intent的setData()方法將這個Uri對象傳進(jìn)去
                // setData()方法,它接收一個Uri對象,主要用于指定當(dāng)前Intent正在操作的數(shù)據(jù),而這些數(shù)據(jù)通常都是以字符串的形式傳入到Uri.parse()方法中進(jìn)行解析產(chǎn)生的。
                startActivity(intent);
            }
        });

與上邊的對應(yīng),還可以再<intent-filter>標(biāo)簽中再配置一個<data>標(biāo)簽,用于更精確地指定當(dāng)前活動能夠響應(yīng)什么類型的數(shù)據(jù)。<data>標(biāo)簽中主要可以配置以下內(nèi)容

  • android:scheme。用于指定數(shù)據(jù)的協(xié)議部分,如上例中的http部分。
  • android:host。用于指定數(shù)據(jù)的主機(jī)名部分,如上例中的www.baidu.com部分。
  • android:port。用于指定數(shù)據(jù)的端口部分,一般緊隨在主機(jī)名之后。
  • android:path。用于指定主機(jī)名和端口之后的部分,如一段網(wǎng)址中跟在域名之后的部分。
  • android:mineType。用于指定可以處理的數(shù)據(jù)類型,允許使用通配符的方式進(jìn)行指定。

只有<data>標(biāo)簽中指定的內(nèi)容和Intent中攜帶的Data完全一致時,當(dāng)前活動才能夠響應(yīng)該Intent。不過<data>標(biāo)簽都不會指定過多的內(nèi)容,如上邊例子中,其實(shí)只需要指定android:scheme為http,就可以響應(yīng)所有的http協(xié)議的Intent了。

調(diào)用系統(tǒng)打電話功能,改變FirstActivity中按鈕想打電話的“意圖”,data部分指定的協(xié)議時10086,當(dāng)然還可以指定其他很多協(xié)議,如geo表示顯示地理位置等

Button button = (Button)findViewById(R.id.button_1);
        button.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                // 響應(yīng)打電話功能
                Intent intent = new Intent(Intent.ACTION_DIAL);
                intent.setData(Uri.parse("tel:10086"));
                startActivity(intent);
            }
        });

向下一個Intent傳遞數(shù)據(jù)

Intent不僅能啟動Activity,還可以再啟動Activity的時候傳遞數(shù)據(jù)。它的思路很簡單,Intent提供了一系列putExtra()方法的重載,可以把想要傳遞的數(shù)據(jù)暫存在Intent中,啟動了另一個活動之后,只需要把這些數(shù)據(jù)再從Intent中取出來就可以了。

比如FirstActivity中有一個字符串,現(xiàn)在想把這個字符串傳遞到SecondActivity中,可以這樣編寫

在FirstActivity中:

Button button = (Button)findViewById(R.id.button_1);
        button.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                String data = "Hello SecondActivity";
                Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
                intent.putExtra("extra_data", data); 
                // 第一個參數(shù)是鍵,用于后邊的取值,第二個參數(shù)是真正的數(shù)據(jù)
                startActivity(intent);
            }
        });

在SecondActivity中接收數(shù)據(jù):

public class SecondActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.second_layout);
        // 通過getIntent()方法獲取到用于SecondActivity的Intent
        Intent intent = getIntent();
        // 調(diào)用getStringExtra()方法來獲取傳遞的數(shù)據(jù),用鍵來取
        // 如果傳遞的是整型數(shù)據(jù),則使用getIntExtra()方法;傳遞的是布爾型數(shù)據(jù)getBoolExtra()方法
        String data = intent.getStringExtra("extra_data");
        System.out.println(data);
        Log.d("SecondActivity", data);
    }
}

返回數(shù)據(jù)給上一個Activity

返回上一個活動只需要按一下Back鍵就可以了,并沒有一個用于啟動活動Intent來傳遞數(shù)據(jù)。Activity還有一個startActivityForResult()方法也適用于啟動活動的,但是這個方法期望在活動銷毀的時候能夠返回一個結(jié)果給上一個活動,這就是我們所需要的。

startActivityForResult()方法接收兩個參數(shù),第一個參數(shù)還是Intent,第二個參數(shù)是請求碼,用于之后的回調(diào)中判斷數(shù)據(jù)的來源

修改FirstActivity中按鈕的點(diǎn)擊事件

Button button = (Button)findViewById(R.id.button_1);
        button.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(FirstActivity.this, SecondActivity.class);
                // 使用startActivityForResult()方法來啟動Activity,請求碼只要是一個唯一值就可以了,這里傳入1
                startActivityForResult(intent, 1);
            }
        });

在SecondActivity中給按鈕注冊事件

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.second_layout);
        // 給按鈕注冊點(diǎn)擊事件,并在點(diǎn)擊事件中添加返回數(shù)據(jù)的邏輯
        Button button2 = (Button)findViewById(R.id.button_2);
        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 創(chuàng)建一個Intent,該Intent僅僅用于傳遞數(shù)據(jù),沒有指定任何的"意圖"
                Intent intent = new Intent();
                // 把數(shù)據(jù)存放在Intent中
                intent.putExtra("data_return", "Hello FirstActivity");
                // 調(diào)用setresult()方法,該方法是專門用于向上一個頁面?zhèn)鬟f數(shù)據(jù)的。接收兩個參數(shù),第一個參數(shù)
                // 用于向上一個活動返回處理結(jié)果,一般只使用RESULT_OK或RESULT_CANCELED這兩個值,第二個參數(shù)則把
                // 帶有數(shù)據(jù)的Intent傳遞回去
                setResult(RESULT_OK, intent);
                // 調(diào)用finish()方法來銷毀當(dāng)前活動
                finish();
            }
        });
    }

在SecondActivity銷毀之后會回調(diào)上一個活動的onActivityResult()方法,再回到FirstActivity

// 由于使用 startActivityForResult()方法來啟動SecondActivity的,在SecondActivity被銷毀之后會回調(diào)
    // 上一個活動也就是FirstActivity的onActivityResult()方法,因此重寫該方法
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        // 該方法接收三個參數(shù),第一個參數(shù)requestCode,就是啟動活動時傳入的請求碼,第二個參數(shù)resultCode,即返回數(shù)據(jù)時
        // 傳入的處理結(jié)果,第三個參數(shù)就是攜帶者返回數(shù)據(jù)的Intent
        super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode) {
            case 1:
                if (resultCode == RESULT_OK) {
                    String returnedData = data.getStringExtra("data_return");
                    Log.d("FirstActivity", returnedData);
                }
                break;
            default:
        }
    }

由于在一個Activity中有可能調(diào)用startActivityForResult()方法去啟動很多不同的Activity,每一個Activity返回的數(shù)據(jù)都會回調(diào)到onActivityResult()這個方法中,因此首先要通過檢查requestCode的值來判斷數(shù)據(jù)源。確定數(shù)據(jù)是從SecondActivity返回的之后,再通過resultCode的值來判斷處理結(jié)果是否成功,最后從data中取值并打印,這樣就完成了向上一個Activity返回數(shù)據(jù)的工作。

如果用戶在SecondActivity中并不是通過點(diǎn)擊按鈕而是通過按下Back鍵回到FirstActivity,這時候需要在SecondActivity中重寫onBackPressed()方法來解決:

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

這樣當(dāng)用戶按下Back鍵,就會執(zhí)行onBackPressed()方法中的代碼,從而在這里添加返回數(shù)據(jù)的邏輯就行。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,517評論 6 539
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,087評論 3 423
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,521評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,493評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,207評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,603評論 1 325
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,624評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,813評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,364評論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,110評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,305評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,874評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,532評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,953評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,209評論 1 291
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,033評論 3 396
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,268評論 2 375

推薦閱讀更多精彩內(nèi)容

  • 作為Android的四大組件之一,活動最先走進(jìn)我們的視野,其重要性不言而喻,今天就抽出時間來專門對Android活...
    loser先生閱讀 894評論 0 0
  • 如果一個 Intent 請求在一片數(shù)據(jù)上執(zhí)行一個動作, Android 如何知道哪個應(yīng)用程序(和組件)能用來響應(yīng)這...
    柒黍閱讀 5,814評論 0 1
  • 01. 你說,你愛我 可我卻忘了問 你愛的,是不是只有我 02. 分手那天,陽光明媚 可我的心 卻涼了一絲 03....
    一個喜歡深夜讀書的女子閱讀 641評論 4 21
  • 有這樣一種人 遇到一些傷心的事,想要去向朋友傾訴,于是用開玩笑的語氣跟她傾訴了,她會安慰我。 后來,遇到了已經(jīng)開不...
    聽你的聲音閱讀 150評論 0 0
  • 【引言】禪意隨心轉(zhuǎn),心在若有若無間輪轉(zhuǎn)流淌。像風(fēng)一樣似有似無,感覺得到卻抓不住。 【正文】 一個是皮囊 一個是靈魂...
    營州布衣閱讀 186評論 2 5