最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

第六章 組件通訊與廣播消息(Intent)

2018-11-08 23:40 作者:swiss126  | 我要投稿

參考資料:

《Android應(yīng)用程序開發(fā)》ISBN 9787302283164

參考軟件:

Android Studio、Eclipse+ADT、Android SDK、JDK

Intent簡介

  Intent的中文意思是“意圖,意向”,在Android中提供了Intent機制來協(xié)助應(yīng)用間的交互與通訊,Intent負責(zé)對應(yīng)用中一次操作的動作、動作涉及數(shù)據(jù)、附加數(shù)據(jù)進行描述,Android則根據(jù)此Intent的描述,負責(zé)找到對應(yīng)的組件,將 Intent傳遞給調(diào)用的組件,并完成組件的調(diào)用。Intent不僅可用于應(yīng)用程序之間,也可用于應(yīng)用程序內(nèi)部的Activity/Service之間的交互。因此,可以將Intent理解為不同組件之間通信的“媒介”專門提供組件互相調(diào)用的相關(guān)信息。

1、Intent的概念:

  Android中提供了Intent機制來協(xié)助應(yīng)用間的交互與通訊,或者采用更準確的說法是,Intent不僅可用于應(yīng)用程序之間,也可用于應(yīng)用程序內(nèi)部的activity, service和broadcast receiver之間的交互。Intent這個英語單詞的本意是“目的、意向、意圖”。

  Intent是一種運行時綁定(runtime binding)機制,它能在程序運行的過程中連接兩個不同的組件。通過Intent,你的程序可以向Android表達某種請求或者意愿,Android會根據(jù)意愿的內(nèi)容選擇適當?shù)慕M件來響應(yīng)。

  activity、service和broadcast receiver之間是通過Intent進行通信的,而另外一個組件Content Provider本身就是一種通信機制,不需要通過Intent。我們來看下面這個圖就知道了:

  如果Activity1需要和Activity2進行聯(lián)系,二者不需要直接聯(lián)系,而是通過Intent作為橋梁。通俗來講,Intnet類似于中介、媒婆的角色。

2、對于向這三種組件發(fā)送intent有不同的機制:

  使用Context.startActivity() 或Activity.startActivityForResult(),傳入一個intent來啟動一個activity。使用 Activity.setResult(),傳入一個intent來從activity中返回結(jié)果。

  將intent對象傳給Context.startService()來啟動一個service或者傳消息給一個運行的service。將intent對象傳給Context.bindService()來綁定一個service。

  將intent對象傳給Context.sendBroadcast(),Context.sendOrderedBroadcast(),或者Context.sendStickyBroadcast()等廣播方法,則它們被傳給 broadcast receiver。

?Intent的相關(guān)屬性

Intent由以下各個組成部分:

component(組件):目的組件

action(動作):用來表現(xiàn)意圖的行動

category(類別):用來表現(xiàn)動作的類別

data(數(shù)據(jù)):表示與動作要操縱的數(shù)據(jù)

type(數(shù)據(jù)類型):對于data范例的描寫

extras(擴展信息):擴展信息

Flags(標志位):期望這個意圖的運行模式

Intent類型分為顯式Intent(直接類型)、隱式Intent(間接類型)。官方建議使用隱式Intent。上述屬性中,component屬性為直接類型,其他均為間接類型。

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

Activity 中 Intent Filter 的匹配過程:

1、component(組件):目的組件

Component屬性明確指定Intent的目標組件的類名稱。(屬于直接Intent)

如果 component這個屬性有指定的話,將直接使用它指定的組件。指定了這個屬性以后,Intent的其它所有屬性都是可選的。

例如,啟動第二個Activity時,我們可以這樣來寫:

? ? ? ? ?button1.setOnClickListener(new?OnClickListener() { ? ? ? ? ??

??? ? ? ? ? @Override

? ? ? ? ? ??public void?onClick(View v) {

? ? ? ? ? ? ? ? ?//創(chuàng)建一個意圖對象

? ? ? ? ? ? ? ? ?Intent intent =?new?Intent();

? ? ? ? ? ? ? ? ?//創(chuàng)建組件,通過組件來響應(yīng)

? ? ? ? ? ? ? ? ?ComponentName component =?new ComponentName(MainActivity.this,SecondActivity.class);

?????????????????intent.setComponent(component);???????????????

? ? ? ? ? ? ? ? startActivity(intent);???????????????

?????????????}

? ? ? ? ?});

如果寫的簡單一點,監(jiān)聽事件onClick()方法里可以這樣寫:

Intent intent =?new?Intent();

//setClass函數(shù)的第一個參數(shù)是一個Context對象

//Context是一個類,Activity是Context類的子類,也就是說,所有的Activity對象,都可以向上轉(zhuǎn)型為Context對象

//setClass函數(shù)的第二個參數(shù)是一個Class對象,在當前場景下,應(yīng)該傳入需要被啟動的Activity類的class對象

intent.setClass(MainActivity.this, SecondActivity.class);

startActivity(intent);???

再簡單一點,可以這樣寫:(當然,也是最常見的寫法)

Intent intent =?newIntent(MainActivity.this,SecondActivity.class);

startActivity(intent);

2、Action(動作):用來表現(xiàn)意圖的行動

當日常生活中,描述一個意愿或愿望的時候,總是有一個動詞在其中。比如:我想“做”三個俯臥撐;我要“寫” 一封情書,等等。在Intent中,Action就是描述做、寫等動作的,當你指明了一個Action,執(zhí)行者就會依照這個動作的指示,接受相關(guān)輸入,表現(xiàn)對應(yīng)行為,產(chǎn)生符合的輸出。在Intent類中,定義了一批量的動作,比如ACTION_VIEW,ACTION_PICK等,基本涵蓋了常用動作。加的動作越多,越精確。

Action 是一個用戶定義的字符串,用于描述一個 Android 應(yīng)用程序組件,一個 Intent Filter 可以包含多個 Action。在 AndroidManifest.xml 的Activity 定義時,可以在其?<intent-filter >節(jié)點指定一個 Action列表用于標識 Activity 所能接受的“動作”。

action動作大全:

http://blog.csdn.net/ithomer/article/details/8242471

Intent的各種常見作用

http://www.cnblogs.com/hanyonglu/archive/2012/03/26/2417278.html

3、category(類別):用來表現(xiàn)動作的類別

Category屬性也是作為<intent-filter>子元素來聲明的。例如:

<intent-filter>

<actionandroid:name="com.vince.intent.MY_ACTION"></action>

<categoryandroid:name="com.vince.intent.MY_CATEGORY"></category>?

<categoryandroid:name="android.intent.category.DEFAULT"></category>?

</intent-filter>???

Action 和category通常是放在一起用的,所以這里一起介紹一下。我們來先來舉一個例子:

新建一個工程文件smyh006_Intent01,在默認文件的基礎(chǔ)之上,新建文件SecondActicity.java和activity_second.xml。

緊接著,我們要到清單文件中進行注冊,打開AndroidManifest.xml,添加SecondActivity的action和category的過濾器:

? ? ? ? ?<activity

? ? ? ? ? ? ?android:name=".SecondActivity">

? ? ? ? ? ? ?<intent-filter>

? ? ? ? ? ? ? ? ?<action?android:name="com.example.smyh006intent01.MY_ACTION"/>

? ? ? ? ? ? ? ? ??<category?android:name="android.intent.category.DEFAULT"/>

? ? ? ? ? ? ?</intent-filter>????????????

? ? ? ??</activity>

上方代碼,表示SecondActicity可以匹配第4行的MY_ACTION這個動作,此時,如果在其他的Acticity通過這個action的條件來查找,那SecondActicity就具備了這個條件。類似于相親時,我要求對方有哪些條件,然后對方這個SecondActicity恰巧滿足了這個條件(夠通俗了吧)。

注:如果沒有指定的category,則必須使用默認的DEFAULT(即上方第5行代碼)。

也就是說:只有<action>和<category>中的內(nèi)容同時能夠匹配上Intent中指定的action和category時,這個活動才能響應(yīng)Intent。如果使用的是DEFAULT這種默認的category,在稍后調(diào)用startActivity()方法的時候會自動將這個category添加到Intent中。

現(xiàn)在來修改MainActivity.java中按鈕的點擊事件,代碼如下:

? ? ? ? ?button1.setOnClickListener(new?OnClickListener() {???????????

??????????????@Override

? ? ? ? ? ? ?public void?onClick(View v) {

? ? ? ? ? ? ? ? ?//啟動另一個Activity,(通過action屬性進行查找)

? ? ? ? ? ? ? ? ? Intent intent =?new?Intent();

? ? ? ? ? ? ? ? ??//設(shè)置動作(實際action屬性就是一個字符串標記而已)

? ? ? ? ? ? ????intent.setAction("com.example.smyh006intent01.MY_ACTION");//方法:Intentandroid.content.Intent.setAction(String action)

??????????????????startActivity(intent);?????? ?

??????????????}

? ? ? ? });

上方代碼中,也可以換成下面這種簡潔的方式:

? ? ? ? button1.setOnClickListener(new?OnClickListener() {???????????

?????????????@Override

? ? ? ? ? ??public void?onClick(View v) {

? ? ? ? ? ? ? ? ?//啟動另一個Activity,(通過action屬性進行查找)

? ? ? ? ? ? ? ? ?Intent intent =?newIntent("com.example.smyh006intent01.MY_ACTION");//方法: android.content.Intent.Intent(String action)????????????????

? ? ? ? ? ? ? ? startActivity(intent);???????

?????????????}

? ? ? ? ?});

上方第5行代碼:在這個Intent中,我并沒有指定具體哪一個Activity,我只是指定了一個action的常量。所以說,隱式Intent的作用就表現(xiàn)的淋漓盡致了。此時,點擊MainActicity中的按鈕,就會跳到SecondActicity中去。

上述情況只有SecondActicity匹配成功。如果有多個組件匹配成功,就會以對話框列表的方式讓用戶進行選擇。我們來詳細介紹一下:

我們新建文件ThirdActicity.java和activity_third.xml,然后在清單文件AndroidManifest.xml中添加ThirdActivity的action和category的過濾器:

? ? ? ? ?<activity

? ? ? ? ? ? ?android:name=".ThirdActivity">

? ? ? ? ? ? ?<intent-filter>

? ? ? ? ? ? ? ? ??<action?android:name="com.example.smyh006intent01.MY_ACTION"/>

? ? ? ? ? ? ? ? ??<category?android:name="android.intent.category.DEFAULT"/>

? ? ? ? ? ? ?</intent-filter>???????????

? ? ? ? ?</activity>

此時,運行程序,當點擊MainActivity中的按鈕時,彈出如下界面:

相信大家看到了這個界面,應(yīng)該就一目了然了。于是我們可以做出如下總結(jié):

在自定義動作時,使用activity組件時,必須添加一個默認的類別

具體的實現(xiàn)為:

<intent-filter>

??????????????<action android:name="com.example.action.MY_ACTION"/>

??????????????<category android:name="android.intent.category.DEFAULT"/>

</intent-filter>

如果有多個組件被匹配成功,就會以對話框列表的方式讓用戶進行選擇。

每個Intent中只能指定一個action,但卻能指定多個category;類別越多,動作越具體,意圖越明確(類似于相親時,給對方提了很多要求)。

目前我們的Intent中只有一個默認的category,現(xiàn)在可以通過intent.addCategory()方法來實現(xiàn)。修改MainActivity中按鈕的點擊事件,代碼如下:

?? ? ? ? button1.setOnClickListener(new?OnClickListener() {???????????

? ? ? ? ? ? @Override

? ? ? ? ? ? ?public void?onClick(View v) {

? ? ? ? ? ? ? ??//啟動另一個Activity,(通過action屬性進行查找)

? ? ? ? ? ? ? ? ? Intent intent =?new?Intent();

? ? ? ? ? ? ? ? ??//設(shè)置動作(實際action屬性就是一個字符串標記而已)

? ? ? ? ? ? ? ?intent.setAction("com.example.smyh006intent01.MY_ACTION");?//方法:Intent android.content.Intent.setAction(String action)

? ? ? ? ? ? ? ? intent.addCategory("com.example.smyh006intent01.MY_CATEGORY");

??????????????????startActivity(intent);???????

?????????????}

? ? ? ? ?});

既然在Intent中增加了一個category,那么我們要在清單文件中去聲明這個category,不然程序?qū)o法運行。代碼如下:

? ? ? ? ? ? android:name=".SecondActivity">

? ? ? ? ? ? ?<intent-filter>

? ? ? ? ? ? ? ? ??<action?android:name="com.example.smyh006intent01.MY_ACTION"/>

? ? ? ? ? ? ? ? ??<category?android:name="android.intent.category.DEFAULT"/>

? ? ? ? ? ? ? ? ??<category?android:name="com.example.smyh006intent01.MY_CATEGORY"/>

? ? ? ? ? ? ?</intent-filter>???????????

? ? ? ??</activity>

此時,點擊MainActicity中的按鈕,就會跳到SecondActicity中去。

總結(jié)如下:

自定義類別:?在Intent添加類別可以添加多個類別,那就要求被匹配的組件必須同時滿足這多個類別,才能匹配成功。操作Activity的時候,如果沒有類別,須加上默認類別

4、data(數(shù)據(jù)):表示與動作要操縱的數(shù)據(jù)

·????????Data屬性是Android要訪問的數(shù)據(jù),和action和Category聲明方式相同,也是在<intent-filter>中。

·????????多個組件匹配成功顯示優(yōu)先級高的;相同顯示列表。

Data是用一個uri對象來表示的,uri代表數(shù)據(jù)的地址,屬于一種標識符。通常情況下,我們使用action+data屬性的組合來描述一個意圖:做什么

使用隱式Intent,我們不僅可以啟動自己程序內(nèi)的活動,還可以啟動其他程序的活動,這使得Android多個應(yīng)用程序之間的功能共享成為了可能。比如應(yīng)用程序中需要展示一個網(wǎng)頁,沒有必要自己去實現(xiàn)一個瀏覽器(事實上也不太可能),而是只需要條用系統(tǒng)的瀏覽器來打開這個網(wǎng)頁就行了。

【實例】打開指定網(wǎng)頁:

MainActivity.java中,監(jiān)聽器部分的核心代碼如下:

? ? ? ? button1.setOnClickListener(new?OnClickListener() {???????????

?????????????@Override

? ? ? ? ? ??public void?onClick(View v) {

? ? ? ? ? ? ? ? ?Intent intent =?new?Intent();

? ? ? ? ? ? ? ? intent.setAction(Intent.ACTION_VIEW);

? ? ? ? ? ? ? ? ?Uri data =Uri.parse("http://www.baidu.com");

?????????????????intent.setData(data);????????????????

?????????????????startActivity(intent);???????

? ? ? ? ? ? }

? ? ? ? ?});

當然,上方代碼也可以簡寫成:

? ? ? 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);???????

?????????????}

? ? ? ? ?});

第4行代碼:指定了Intent的action是?Intent.ACTION_VIEW,表示查看的意思,這是一個Android系統(tǒng)內(nèi)置的動作;

第5行代碼:通過Uri.parse()方法,將一個網(wǎng)址字符串解析成一個Uri對象,再調(diào)用intent的setData()方法將這個Uri對象傳遞進去。

當點擊按鈕時,將跳到如下界面:

此時,調(diào)用的是系統(tǒng)默認的瀏覽器,也就是說,只調(diào)用了這一個組件?,F(xiàn)在如果有多個組件得到了匹配,應(yīng)該是什么情況呢?

我們修改修改清單文件中對SecondAcivity的聲明:

? ? ? ? ?<activity

? ? ? ? ? ??android:name=".SecondActivity">

? ? ? ? ? ? ?<intent-filter>

? ? ? ? ? ? ? ? ?<action?android:name="android.intent.action.VIEW" />

? ? ? ? ? ? ? ? ??<category?android:name="android.intent.category.DEFAULT"/>

? ? ? ? ? ? ? ? ??<data?android:scheme="http"?android:host="www.baidu.com"/>?????????????????

? ? ? ? ? ? ?</intent-filter>???????????

? ? ? ? ?</activity>

現(xiàn)在,SecondActivity也匹配成功了,我們運行程序,點擊MainActicity的按鈕時,彈出如下界面供我們選擇:

我們可以總結(jié)如下:

?當Intent匹配成功的組件有多個時,顯示優(yōu)先級高的組件,如果優(yōu)先級相同,顯示列表讓用戶自己選擇

優(yōu)先級從-1000至1000,并且其中一個必須為負的才有效

注:系統(tǒng)默認的瀏覽器并沒有做出優(yōu)先級聲明,其優(yōu)先級默認為正數(shù)。

優(yōu)先級的配置如下:

在清單文件中修改對SecondAcivity的聲明,即增加一行代碼,通過來android:priority設(shè)置優(yōu)先級,如下:

? ? ? ? ?<activity

? ? ? ? ? ? ?android:name=".SecondActivity">

? ? ? ? ? ? ?<intent-filter?android:priority="-1">

? ? ? ? ? ? ? ? ??<action?android:name="android.intent.action.VIEW"/>

? ? ? ? ? ? ? ? ??<category?android:name="android.intent.category.DEFAULT"/>

? ? ? ? ? ? ? ? ??<data?android:scheme="http"

android:host="www.baidu.com"/>?????????????????????????????????

? ? ? ? ? ??</intent-filter>???????????

? ? ? ? ?</activity>

注:

Data屬性的聲明中要指定訪問數(shù)據(jù)的Uri和MIME類型??梢栽?lt;data>元素中通過一些屬性來設(shè)置:

android:scheme、android:path、android:port、android:mimeType、android:host等,通過這些屬性來對應(yīng)一個典型的Uri格式scheme://host:port/path。例如:http://www.google.com。

5、type(數(shù)據(jù)類型):對于data范例的描寫

如果Intent對象中既包含Uri又包含Type,那么,在<intent-filter>中也必須二者都包含才能通過測試。

Type屬性用于明確指定Data屬性的數(shù)據(jù)類型或MIME類型,但是通常來說,當Intent不指定Data屬性時,Type屬性才會起作用,否則Android系統(tǒng)將會根據(jù)Data屬性值來分析數(shù)據(jù)的類型,所以無需指定Type屬性。

data和type屬性一般只需要一個,通過setData方法會把type屬性設(shè)置為null,相反設(shè)置setType方法會把data設(shè)置為null,如果想要兩個屬性同時設(shè)置,要使用Intent.setDataAndType()方法。

【任務(wù)】:data+type屬性的使用?【實例】:播放指定路徑的mp3文件。

具體如下:

新建工程文件smyh006_Intent02,MainActivity.java中按鈕監(jiān)聽事件部分的代碼如下:

? ? ? ? button.setOnClickListener(new?OnClickListener(){

??????????????@Override

? ? ? ? ? ? ?public void?onClick(View v) {

? ? ? ? ? ? ? ? ?Intent intent =?new?Intent();

?? ? ? ? ? ? ? ? intent.setAction(Intent.ACTION_VIEW);

? ? ? ? ? ? ? ? ? Uri data =Uri.parse("file:///storage/sdcard0/平凡之路.mp3");

? ? ? ? ? ? ? ? ??//設(shè)置data+type屬性

? ? ? ? ? ? ? ? ? intent.setDataAndType(data,"audio/mp3");?//方法:Intentandroid.content.Intent.setDataAndType(Uri data, String type)

?????????????????startActivity(intent);???????????????

?????????????}???????????

? ? ? ? ?});

代碼解釋:

第6行:"file://"表示查找文件,后面再加上我的小米手機存儲卡的路徑:/storage/sdcard0,再加上具體歌曲的路徑。

第8行:設(shè)置data+type屬性  

運行后,當點擊按鈕時,效果如下:

上方界面中,使用的是小米系統(tǒng)默認的音樂播放器。

6、extras(擴展信息):擴展信息

是其它所有附加信息的集合。使用extras可以為組件提供擴展信息,比如,如果要執(zhí)行“發(fā)送電子郵件”這個動作,可以將電子郵件的標題、正文等保存在extras里,傳給電子郵件發(fā)送組件。

7Flags(標志位):期望這個意圖的運行模式

一個程序啟動后系統(tǒng)會為這個程序分配一個task供其使用,另外同一個task里面可以擁有不同應(yīng)用程序的activity。那么,同一個程序能不能擁有多個task?這就涉及到加載activity的啟動模式,這個需要單獨講一下。

注:android中一組邏輯上在一起的activity被叫做task,自己認為可以理解成一個activity堆棧。

例子1:點擊按鈕返回Home界面:?運行效果圖:

核心代碼:

Intent?it?=?new?Intent();it.setAction(Intent.ACTION_MAIN);it.addCategory(Intent.CATEGORY_HOME);startActivity(it);

Intent的常見應(yīng)用

https://blog.csdn.net/u012758088/article/details/68922219?locationNum=9&fps=1

1、打開指定網(wǎng)頁:(直接復(fù)制的上面的代碼)

MainActivity.java中,監(jiān)聽器部分的核心代碼如下:

? ? ? button1.setOnClickListener(new?OnClickListener() {???????????

?????????????@Override

? ? ? ? ? ??public voidonClick(View v) {

? ? ? ? ? ? ? ? ?Intent intent =?new?Intent();

? ? ? ? ? ? ? ? ?intent.setAction(Intent.ACTION_VIEW);//方法:android.content.Intent.Intent(String action)

? ? ? ? ? ? ? ? ?Uri data =Uri.parse("http://www.baidu.com");

?????????????????intent.setData(data);????????????????

?????????????????startActivity(intent);???????

? ? ? ? ? ? }

? ? ? ? });

當然,上方代碼也可以簡寫成:

? ?button1.setOnClickListener(new?OnClickListener() {???????????

?????????????@Override

? ? ? ? ? ? ?public voidonClick(View v) {

? ? ? ? ? ? ? ? ?Intent intent =?new?Intent(Intent.ACTION_VIEW);

? ? ? ? ? ? ? intent.setData(Uri.parse("http://www.baidu.com"));????????????????

?????????????????startActivity(intent);???????

? ? ? ? ? ? }

? ? ? ? ?});

第4行代碼:指定了Intent的action是?Intent.ACTION_VIEW,表示查看的意思,這是一個Android系統(tǒng)內(nèi)置的動作;

第5行代碼:通過Uri.parse()方法,將一個網(wǎng)址字符串解析成一個Uri對象,再調(diào)用intent的setData()方法將這個Uri對象傳遞進去。

或者可以寫成:

? ? ? ?button1.setOnClickListener(new?OnClickListener() {???????????

? ? ? ? ? ? @Override

? ? ? ? ? ??public voidonClick(View v) {

? ? ? ? ? ? ? ? ?Uri uri =Uri.parse("http://www.baidu.com");

? ? ? ? ? ? ? ? ?Intent intent =?new Intent(Intent.ACTION_VIEW,uri);//方法:?? ? ? ? ? ? ? ? ?? ? ? ? ? ? ? ? ?? ? ? ? ? ? ??android.content.Intent.Intent(String action, Uri uri)? ? ? ?

?????????????????startActivity(intent);???????

?????????????}

? ? ? ? });

2、打電話:

【方式一】打開撥打電話的界面:

? ? ? ? ? ? ? ???Intent intent =?new?Intent(Intent.ACTION_DIAL);

? ? ? ? ? ? ? ? intent.setData(Uri.parse("tel:10086"));

? ? ? ? ? ? ? ? ?startActivity(intent);?

運行程序后,點擊按鈕,顯示如下界面:

【方式二】直接撥打電話:

? ? ? ? ? ? ? ??Intent intent =?new?Intent(Intent.ACTION_CALL);

? ? ? ? ? ? ? ? intent.setData(Uri.parse("tel:10086"));

? ? ? ? ? ? ? ? startActivity(intent);

要使用這個功能必須在配置文件中加入權(quán)限:(加一行代碼)

1???? <uses-sdk

2???????? android:minSdkVersion="8"

3????????android:targetSdkVersion="16" />

4???? <uses-permissionandroid:name="android.permission.CALL_PHONE"/>

3、發(fā)短信:

【方式一】打開發(fā)送短信的界面:action+type

? ? ? ? ?Intent intent =?new?Intent(Intent.ACTION_VIEW);

? ? ? ? intent.setType("vnd.android-dir/mms-sms");

? ? ? ? intent.putExtra("sms_body","具體短信內(nèi)容");?//"sms_body"為固定內(nèi)容

? ? ? ? ?startActivity(intent);

【方式二】打開發(fā)短信的界面(同時指定電話號碼):action+data

? ? ? ? Intent intent =?new?Intent(Intent.ACTION_SENDTO);

? ? ? ? intent.setData(Uri.parse("smsto:18780260012"));

? ? ? ? intent.putExtra("sms_body","具體短信內(nèi)容");?//"sms_body"為固定內(nèi)容???????

? ? ? ? startActivity(intent);

4、播放指定路徑音樂:action+data+type

? ? ? ? ?Intent intent =?new?Intent(Intent.ACTION_VIEW);

? ? ? ? ?Uri uri =Uri.parse("file:///storage/sdcard0/平凡之路.mp3");

////路徑也可以寫成:"/storage/sdcard0/平凡之路.mp3"

? ? ? ? intent.setDataAndType(uri,"audio/mp3");?//方法:Intent android.content.Intent.setDataAndType(Uridata, String type)

? ? ? ? startActivity(intent);

5、卸載程序:action+data(例如點擊按鈕,卸載某個應(yīng)用程序,根據(jù)包名來識別)

注:無論是安裝還是卸載,應(yīng)用程序是根據(jù)包名package來識別的。

? ? ? ? ?Intent intent =?new?Intent(Intent.ACTION_DELETE);

? ? ? ? ?Uri data =Uri.parse("package:com.example.smyh006intent01");

?????????intent.setData(data);

? ? ? ? ?startActivity(intent);

6、安裝程序:action+data+type

? ? ? ? ?Intent intent =?new?Intent(Intent.ACTION_VIEW);

? ? ? ? ?Uri data = Uri.fromFile(new File("/storage/sdcard0/AndroidTest/smyh006_Intent01.apk"));????//路徑不能寫成:"file:///storage/sdcard0/···"

? ? ? ? ?intent.setDataAndType(data,"application/vnd.android.package-archive");??//Type的字符串為固定內(nèi)容

? ? ? ? ?startActivity(intent);

注:第2行的路徑不能寫成:"file:///storage/sdcard0/···",不然報錯如下:

疑問:通過下面的這種方式安裝程序,運行時為什么會出錯呢?

? ? ?//通過指定的action來安裝程序

? ? ?publicvoid?installClickTwo(View view){

? ? ? ? ?Intent intent =?new?Intent(Intent.ACTION_PACKAGE_ADDED);

? ? ? ? ?Uri data = Uri.fromFile(newFile("/storage/sdcard0/AndroidTest/smyh006_Intent01.apk"));????//路徑不能寫成:"file:///storage/sdcard0/···"

?????????intent.setData(data);

?????????startActivity(intent);

? ? ?}

運行后,主界面如下:

Intent數(shù)據(jù)傳遞

1.Intent傳遞簡單數(shù)據(jù)

直接通過調(diào)用Intent的putExtra()方法存入數(shù)據(jù),然后在獲得Intent后調(diào)用getXxxExtra獲得對應(yīng)類型的數(shù)據(jù);傳遞多個的話,可以使用Bundle對象作為容器,通過調(diào)用Bundle的putXxx先將數(shù)據(jù)存儲到Bundle中,然后調(diào)用Intent的putExtras()方法將Bundle存入Intent中,然后獲得Intent以后,調(diào)用getExtras()獲得Bundle容器,然后調(diào)用其getXXX獲取對應(yīng)的數(shù)據(jù)!另外數(shù)據(jù)存儲有點類似于Map的<鍵,值>!

2.Intent傳遞數(shù)組

寫入數(shù)組

bd.putStringArray("StringArray",new String[]{"呵呵","哈哈"});

//可把StringArray換成其他數(shù)據(jù)類型,比如int,float等等...

讀取數(shù)組

String[]str = bd.getStringArray("StringArray")

3.Intent傳遞集合

嗯,數(shù)組很簡單吧,那我們再來傳下集合~這個就稍微復(fù)雜點了,分情況處理:

(1List<基本數(shù)據(jù)類型或String>

寫入集合:

intent.putStringArrayListExtra(name,value)

intent.putIntegerArrayListExtra(name,value)

讀取集合:

intent.getStringArrayListExtra(name)

intent.getIntegerArrayListExtra(name)

(2List< Object>

將list強轉(zhuǎn)成Serializable類型,然后傳入(可用Bundle做媒介)

寫入集合:

putExtras(key,(Serializable)list)

讀取集合:

(List<Object>)getIntent().getSerializable(key)

PS:Object類需要實現(xiàn)Serializable接口

(3Map<String, Object>,或更復(fù)雜的

解決方法是:外層套個List

//傳遞復(fù)雜些的參數(shù)

Map<String,Object> map1 = new HashMap<String, Object>();?

map1.put("key1","value1");?

map1.put("key2","value2");?

List<Map<String,Object>> list = new ArrayList<Map<String, Object>>();?

list.add(map1);?

Intentintent = new Intent();?

intent.setClass(MainActivity.this,ComplexActivity.class);?

Bundlebundle = new Bundle();?

//須定義一個list用于在budnle中傳遞需要傳遞的ArrayList<Object>,這個是必須要的?

ArrayListbundlelist = new ArrayList();??

bundlelist.add(list);??

bundle.putParcelableArrayList("list",bundlelist);?

intent.putExtras(bundle);???????????????

startActivity(intent);

4.Intent傳遞對象

傳遞對象的方式有兩種:將對象轉(zhuǎn)換為Json字符串或者通過Serializable,Parcelable序列化不建議使用Android內(nèi)置的摳腳Json解析器,可使用fastjson或者Gson第三方庫!

(1)將對象轉(zhuǎn)換為Json字符串

Gson解析的例子:

Model:

publicclass Author{

??? private int id;

??? private String name;

??? //...

}

?

publicclass Author{

??? private int id;

??? private String name;

??? //...

}

寫入數(shù)據(jù):

Bookbook=new Book();

book.setTitle("Java編程思想");

Authorauthor=new Author();

author.setId(1);

author.setName("BruceEckel");

book.setAuthor(author);

Intentintent=new Intent(this,SecondActivity.class);

intent.putExtra("book",newGson().toJson(book));

startActivity(intent);

讀取數(shù)據(jù):

StringbookJson=getIntent().getStringExtra("book");

Bookbook=new Gson().fromJson(bookJson,Book.class);

Log.d(TAG,"booktitle->"+book.getTitle());

Log.d(TAG,"bookauthor name->"+book.getAuthor().getName());

(2)使用Serializable,Parcelable序列化對象

Serializable實現(xiàn):

①業(yè)務(wù)Bean實現(xiàn):Serializable接口,寫上getter和setter方法②Intent通過調(diào)用putExtra(String name, Serializable value)傳入對象實例當然對象有多個的話多個的話,我們也可以先Bundle.putSerializable(x,x);
③新Activity調(diào)用getSerializableExtra()方法獲得對象實例: eg:Product pd = (Product)getIntent().getSerializableExtra("Product");
④調(diào)用對象get方法獲得相應(yīng)參數(shù)

Parcelable實現(xiàn):

一般流程:

①業(yè)務(wù)Bean繼承Parcelable接口,重寫writeToParcel方法,將你的對象序列化為一個Parcel對象;
②重寫describeContents方法,內(nèi)容接口描述,默認返回0就可以③實例化靜態(tài)內(nèi)部對象CREATOR實現(xiàn)接口Parcelable.Creator
④同樣式通過Intent的putExtra()方法傳入對象實例,當然多個對象的話,我們可以先放到Bundle里Bundle.putParcelable(x,x),再Intent.putExtras()即可

一些解釋:

通過writeToParcel將你的對象映射成Parcel對象,再通過createFromParcel將Parcel對象映射成你的對象。也可以將Parcel看成是一個流,通過writeToParcel把對象寫到流里面,在通過createFromParcel從流里讀取對象,只不過這個過程需要你來實現(xiàn),因此寫的順序和讀的順序必須一致。

實現(xiàn)Parcelable接口的代碼示例:

//InternalDescription Interface,You do not need to manage?

@Override?

publicint describeContents() {?

???? return 0;?

}?

@Override?

publicvoid writeToParcel(Parcel parcel, int flags){?

??? parcel.writeString(bookName);?

??? parcel.writeString(author);?

??? parcel.writeInt(publishTime);?

}?

publicstatic final Parcelable.Creator<Book> CREATOR = new Creator<Book>(){?

??? @Override?

??? public Book[] newArray(int size) {?

??????? return new Book[size];?

??? }?

??? @Override?

??? public Book createFromParcel(Parcel source){?

??????? Book mBook = new Book();???

??????? mBook.bookName = source.readString();??

??????? mBook.author = source.readString();???

??????? mBook.publishTime = source.readInt();??

??????? return mBook;?

??? }?

};

Android Studio生成Parcleable插件:

Intellij/Andriod Studio插件android-parcelable-intellij-plugin只要ALT+Insert,即可直接生成Parcleable接口代碼。

另外:Android中大量用到Parcelable對象,實現(xiàn)Parcable接口又是非常繁瑣的,可以用到第三方的開源框架:Parceler,因為Maven的問題,暫時還沒試。

參考地址:[Android的Parcelable自動生成]

3.兩種序列化方式的比較:

兩者的比較:

·????????1)在使用內(nèi)存的時候,Parcelable比Serializable性能高,所以推薦使用Parcelable。

·????????2)Serializable在序列化的時候會產(chǎn)生大量的臨時變量,從而引起頻繁的GC。

·????????3)Parcelable不能使用在要將數(shù)據(jù)存儲在磁盤上的情況,因為Parcelable不能很好的保證數(shù)據(jù)的持續(xù)性在外界有變化的情況下。盡管Serializable效率低點,但此時還是建議使用Serializable。

5.Intent傳遞Bitmap

bitmap默認實現(xiàn)Parcelable接口,直接傳遞即可

實現(xiàn)代碼:

Bitmapbitmap = null;

Intentintent = new Intent();

Bundlebundle = new Bundle();

bundle.putParcelable("bitmap",bitmap);

intent.putExtra("bundle",bundle);

6.傳來傳去不方便,直接定義全局數(shù)據(jù)

如果是傳遞簡單的數(shù)據(jù),有這樣的需求,Activity1 ->Activity2 -> Activity3 -> Activity4,你想在Activity中傳遞某個數(shù)據(jù)到Activity4中,怎么破,一個個頁面?zhèn)髅矗?/p>

顯然不科學(xué)是吧,如果你想某個數(shù)據(jù)可以在任何地方都能獲取到,你就可以考慮使用?Application全局對象了!

Android系統(tǒng)在每個程序運行的時候創(chuàng)建一個Application對象,而且只會創(chuàng)建一個,所以Application 是單例(singleton)模式的一個類,而且Application對象的生命周期是整個程序中最長的,他的生命周期等于這個程序的生命周期。如果想存儲一些比靜態(tài)的值(固定不改變的,也可以變),如果你想使用 Application就需要自定義類實現(xiàn)Application類,并且告訴系統(tǒng)實例化的是我們自定義的Application 而非系統(tǒng)默認的,而這一步,就是在AndroidManifest.xml中衛(wèi)我們的application標簽添加:name屬性!

關(guān)鍵部分代碼:

1)自定義Application類:

classMyApp extends Application {

??? private String myState;

??? public String getState(){

??????? return myState;

??? }

??? public void setState(String s){

??????? myState = s;

??? }

}

2AndroidManifest.xml中聲明:

<applicationandroid:name=".MyApp" android:icon="@drawable/icon"

? android:label="@string/app_name">

3)在需要的地方調(diào)用:

classBlah extends Activity {

??? @Override

??? public void onCreate(Bundle b){

?????? ?...

??? MyApp appState = ((MyApp)getApplicationContext());

??? String state = appState.getState();

??????? ...

??? }

}

高逼格寫法

在任何位置都能獲取到Application全局對象。

Applicaiton是系統(tǒng)的一個組件,他也有自己的一個生命周期,我們可以在onCraete里獲得這個 Application對象。貼下修改后的代碼吧!

classMyApp extends Application {

??? private String myState;

??? private static MyApp instance;

??? public static MyApp getInstance(){

??????? return instance;

??? }

??? public String getState(){

??????? return myState;

??? }

??? public void setState(String s){

??????? myState = s;

??? }

??? @Override

??? public void onCreate(){

??????? onCreate();

??????? instance = this;

??? }

}

然后在任意地方我們就可以直接調(diào)用:MyApp.getInstance()來獲得Application的全局對象!

注意事項:

Application對象是存在于內(nèi)存中的,也就有它可能會被系統(tǒng)殺死,比如這樣的場景:

我們在Activity1中往application中存儲了用戶賬號,然后在Activity2中獲取到用戶賬號,并且顯示!

如果我們點擊home鍵,然后過了N久候,系統(tǒng)為了回收內(nèi)存kill掉了我們的app。這個時候,我們重新打開這個app,這個時候很神奇的,回到了Activity2的頁面,但是如果這個時候你再去獲取Application 里的用戶賬號,程序就會報NullPointerException,然后crash掉~

之所以會發(fā)生上述crash,是因為這個Application對象是全新創(chuàng)建的,可能你以為App是重新啟動的,其實并不是,僅僅是創(chuàng)建一個新的Application,然后啟動上次用戶離開時的Activity,從而創(chuàng)造App 并沒有被殺死的假象!所以如果是比較重要的數(shù)據(jù)的話,建議你還是進行本地化,另外在使用數(shù)據(jù)的時候要對變量的值進行非空檢查!還有一點就是:不止是Application變量會這樣,單例對象以及公共靜態(tài)變量也會這樣~

7.單例模式傳參

上面的Application就是基于單例的,單例模式的特點就是可以保證系統(tǒng)中一個類有且只有一個實例。這樣很容易就能實現(xiàn),在A中設(shè)置參數(shù),在B中直接訪問了。這是幾種方法中效率最高的。

范例代碼:(代碼來自于網(wǎng)上~)

①定義一個單例類

publicclass XclSingleton?

{?

??? //單例模式實例?

??? private static XclSingleton instance = null;?

?????

??? //synchronized?用于線程安全,防止多線程同時創(chuàng)建實例?

??? public synchronized static XclSingletongetInstance(){?

??????? if(instance == null){?

??????????? instance = new XclSingleton();?

??????? }????

??????? return instance;?

??? }????

?????

?? ?finalHashMap<String, Object> mMap;?

??? private XclSingleton()?

??? {?

??????? mMap = new HashMap<String,Object>();?

??? }?

?????

??? public void put(String key,Object value){?

??????? mMap.put(key,value);?

??? }?

?????

??? public Object get(String key)?

??? {?

??????? return mMap.get(key);?

??? }?

?????

}

設(shè)置參數(shù):

XclSingleton.getInstance().put("key1","value1");?

XclSingleton.getInstance().put("key2","value2");

Activity跳轉(zhuǎn)后返回值

獲取子Activity的返回值,一般可以分為以下三個步驟

1、以Sub-Activity的方式啟動子Activity

2、設(shè)置子Activity的返回值

3、在父Activity中獲取返回值

startActivityForResult(intent, 0);

其中的0表示是哪個activity返回的

第六章 組件通訊與廣播消息(Intent)的評論 (共 條)

分享到微博請遵守國家法律
丽水市| 甘德县| 东辽县| 霍山县| 自治县| 惠来县| 牙克石市| 海原县| 江源县| 西昌市| 伊宁县| 凌源市| 山东省| 屏南县| 林州市| 舟山市| 合水县| 鸡泽县| 武强县| 临潭县| 吴堡县| 南城县| 来安县| 沈阳市| 勃利县| 汝城县| 江都市| 阿巴嘎旗| 焉耆| 搜索| 马公市| 陆川县| 肇庆市| 仲巴县| 大丰市| 忻州市| 武夷山市| 青海省| 南康市| 宾阳县| 临泉县|