前言
每個應(yīng)用程序都有若干個Activity組成,每一個Activity都是一個應(yīng)用程序與用戶進行交互的窗口,呈現(xiàn)不同的交互界面。因為每一個Acticity的任務(wù)不一樣,所以經(jīng)常互在各個Activity之間進行跳轉(zhuǎn),在Android中這個動作是靠Intent來完成的。你通過startActivity()方法發(fā)送一個Intent給系統(tǒng),系統(tǒng)會根據(jù)這個Intent幫助你找到對應(yīng)的Activity,即使這個Activity在其他的應(yīng)用中,也可以用這種方法啟動它。
Intent的定義
Intent意圖可以是明確的指定組件(四大組件)的名稱,這樣你可以精確的啟動某個系統(tǒng)組件,比如啟動一個Activity。它也可以是模糊的,沒有指定組件名稱,只要是能夠匹配到這個Intent的應(yīng)用都可以接收到,比如發(fā)送一個拍照Intent,所有的拍照應(yīng)用都會響應(yīng)。
顯式Intent和隱式Intent
-
顯式的Intent就是你已經(jīng)知道要啟動的組件名稱,比如某個Activity的包名和類名,在Intent中明確的指定了這個組件(Activity),一般來說這種Intent經(jīng)常用在一個應(yīng)用中,因為你已經(jīng)明確的知道要啟動的組件名稱。
當(dāng)你創(chuàng)建一個顯式Intent來啟動一個Activity或者Service時,系統(tǒng)會立刻通過你的Intent對象啟動那個組件。
-
隱式的Intent就是你不知道要啟動的組件名稱,只知道一個Intent動作要執(zhí)行,比如:拍照,錄像,查看地圖。一般來說這種Intent用在不同的應(yīng)用之間傳遞信息。
當(dāng)你創(chuàng)建一個隱式Intent,系統(tǒng)會根據(jù)manifest file中的intent filter找匹配的組件,如果你發(fā)送的Intent匹配到一個intent filter,系統(tǒng)會把你的Intent傳遞給該filter對應(yīng)的組件(Activity、Service等),并且啟動它。如果找到多個匹配的intent filter對應(yīng)的應(yīng)用程序,則會彈出一個對話框讓你選擇哪個應(yīng)用程序接受你的Intent。
注:
- intent filter是一種應(yīng)用程序manifest文件中的語法表達,就像是html的標(biāo)簽,它是一個系統(tǒng)組件標(biāo)簽(比如:Activity)的組成部分,可以說是子標(biāo)簽吧,這個系統(tǒng)組件接受什么樣的intent就是用它來指定的,如果一個系統(tǒng)組件不寫intent filter,那么它只能通過顯式的intent來啟動。
- 出于安全的角度,你的Service組件務(wù)必不要用隱式的intent filter來進行說明,因為用隱式的intent啟動一個Service往往不能保證Service會被啟動,并且用戶也不知道哪個Service會響應(yīng)你的Intent。從Android5.0(API 21),系統(tǒng)會拋出異常當(dāng)你用隱式的Intent去調(diào)用bindService()方法。
Intent七大屬性
Intent對象大致包括7大屬性:ComponentName、 Action 、 Category 、 Data 、Type、 Extra 、Flag。
-
Component Name(目標(biāo)組件): 目標(biāo)組件
要啟動的組件名稱,在創(chuàng)建Intent的時候是可選的,但是它是顯式Intent的重要標(biāo)志,有它就意味著只有Component name匹配上的那個組件才能接收你發(fā)送出來的顯示intent。如果不寫那么你創(chuàng)建的Intent就是隱式的,系統(tǒng)會根據(jù)這個intent的其他信息(比如:action、data、category)來確定哪些組件來接收這個intent,所以如果你想明確的啟動哪個組件,就通過component name來指定。Intent的ComponentName屬性是一個類的全稱,包括包名,比如:com.example.ExampleActivity,你可以通過Intent的setComponent(),setClass(),setClassName()方法來設(shè)定,也可以通過Intent的構(gòu)造方法來設(shè)定。
-
Action(動作): 用來表示意圖的動作,如:查看,發(fā)郵件,打電話
是一個可以指明目標(biāo)組件行為的字符串。action很大程度上決定了category和data中應(yīng)傳入的信息;您也可以在自己的應(yīng)用程序組件中指定action,以便讓其他應(yīng)用程序啟動自己的組件。對應(yīng)action中字符串,不建議使用硬編碼的形式,而應(yīng)在所屬組件的類中設(shè)置為常量。如需在自己的組件中定義action,應(yīng)以應(yīng)用的包名作為前綴,比如:
public static final String ACTION_TIMETRAVEL="com.example.action.TIMETRAVEL";常用動作
最常用的是Action_MAIN(作為初始的Activity啟動,沒有數(shù)據(jù)的輸入輸出)ACTION_MAIN:(android.intent.action.MAIN)Android程序入口。 每個Android應(yīng)用必須且只能包含一個此類型的Action聲明?!救绻O(shè)置多個,則哪個在前,執(zhí)行哪個?!?ACTION_VIEW: (android.intent.action.VIEW) 顯示指定數(shù)據(jù)。 ACTION_EDIT: (android.intent.action.EDIT) 編輯指定數(shù)據(jù)。 ACTION_DIAL: (android.intent.action.DIAL) 顯示撥號面板。 ACTION_CALL: (android.intent.action.CALL) 直接呼叫Data中所帶的號碼。 ACTION_ANSWER: (android.intent.action.ANSWER) 接聽來電。 ACTION_SEND: (android.intent.action.SEND) 向其他人發(fā)送數(shù)據(jù)(例如:彩信/email)。 ACTION_SENDTO: (android.intent.action.SENDTO) 向其他人發(fā)送短信。 ACTION_SEARCH: (android.intent.action.SEARCH) 執(zhí)行搜索。 ACTION_GET_CONTENT: (android.intent.action.GET_CONTENT) 讓用戶選擇數(shù)據(jù),并返回所選數(shù)據(jù)。setAction(String action) 用來設(shè)置Intent的動作,參數(shù)可以為常量
getAction() 方法用來獲取Intent動作名稱
上面的Action都是系統(tǒng)定義好的,具有一定意義的動作指向的動作。
Intent的Action對象其實就是一個字符串常量,系統(tǒng)的Action對象是系統(tǒng)定義好的字符串常量,我們也可以自己定義自己的Action作為字符串常量。就像上面的例子使用到了自定義的Action字符串對象。 -
category(類別): 用來表示動作的類別。
Intent的action、category屬性都是普通的字符串,其中action表示Intent需要完成的一個抽象”動作”,而category則為action添加額外的類別信息,通常action和category一塊使用。
需要指出的是,一個Intent中只能包含一個action屬性,但可以包含多個category屬性。當(dāng)程序創(chuàng)建Intent時,該Intent默認(rèn)啟動常量值為andorid.intent.category.DEFAULT的組件。這里的一個Intent中只能包含一個action屬性,并不是Activity中xml的設(shè)置規(guī)范,而是你要跳轉(zhuǎn)到的頁面去,你只能設(shè)置一個Action的值。
常用的Category:CATEGORY_DEFAULT:Android系統(tǒng)中默認(rèn)的執(zhí)行方式,按照普通Activity的執(zhí)行方式執(zhí)行?!?br> CATEGORY_HOME:設(shè)置該組件為Home Activity。
CATEGORY_PREFERENCE:設(shè)置該組件為Preference?!?br> CATEGORY_LAUNCHER:設(shè)置為當(dāng)前應(yīng)用程序優(yōu)先級最高的Activity,通常與ACTION_MAIN配合使 用?!?br> CATEGORY_BROWSABLE:設(shè)置該組件可以使用瀏覽器啟動?!?br> CATEGORY_GADGET:設(shè)置該組件可以內(nèi)嵌到另外的Activity中。
-
data(數(shù)據(jù)): 表示與動作要操作的數(shù)據(jù)。如:查看指定的聯(lián)系人
Data數(shù)據(jù)用來向Action屬性提供動作的數(shù)據(jù)。這里的Data不是Intent里面的數(shù)據(jù),而是指明動作的具體數(shù)據(jù),比如說動作是打電話,那么打給具體的某一個人,就用到了date里面的數(shù)據(jù)來指定。同樣發(fā)郵件、或打開具體的某一個網(wǎng)址也是通過Data數(shù)據(jù)。
Data屬性只接受Uri對象,Uri對象是統(tǒng)一資源標(biāo)識符。對應(yīng)概念不用太多理解,只需知道里面某些具體值的表現(xiàn)形式就可以了。
Uri其實就是相當(dāng)于一個網(wǎng)址,如圖所示:
網(wǎng)址只是Uri其中一種格式的字符串,要使用它還要把它解析后轉(zhuǎn)化為Uri類型。
為Intent對象添加Data數(shù)據(jù),代碼:
intent.setData(Uri.parse(“http://www.baidu.com“));系統(tǒng)內(nèi)置的幾個Data屬性常量:
tel://:號碼數(shù)據(jù)格式,后跟電話號碼。 mailto://:郵件數(shù)據(jù)格式,后跟郵件收件人地址。 smsto://:短息數(shù)據(jù)格式,后跟短信接收號碼。 content://:內(nèi)容數(shù)據(jù)格式,后跟需要讀取的內(nèi)容。 file://:文件數(shù)據(jù)格式,后跟文件路徑。 market://search?q=pname:pkgname:市場數(shù)據(jù)格式,在Google Market里搜索包名為pkgname的應(yīng)用。 geo://latitude, longitude:經(jīng)緯數(shù)據(jù)格式,在地圖上顯示經(jīng)緯度所指定的位置。 -
type(數(shù)據(jù)類型): 對data類型的描述。
與Data有關(guān)的,這個不是Intent的數(shù)據(jù)類型,是Intent的Action的Data數(shù)據(jù)的類型。intent.setAction(android.content.Intent.ACTION_VIEW); Uri uri = Uri.parse("file:///storage/emulated/0/Pictures/Screenshots/qqq.mp4"); String type = "video/mp4"; intent.setDataAndType(uri,type); startActivity(intent) -
extras(附件信息): 附件信息。如:詳細資料,一個文件,某事。
extras屬性主要用于傳遞目標(biāo)組件所需要的額外的數(shù)據(jù)。
通過putExtras()方法設(shè)置。保存數(shù)據(jù);
通過getExtras()方法設(shè)置。獲取數(shù)據(jù)通常我們使用Intent來直接傳遞Bundle對象,但也可以傳遞其他系統(tǒng)內(nèi)置的一些參數(shù)。
如果要傳遞是是對象,那么對象必須實現(xiàn)序列化。Intent intent = new Intent(); intent.setClass(this, SubActivity.class); // 直接添加 //intent.putExtra("MyData", new ParcelableData()); // 通過Bundle Bundle bundle = new Bundle(); bundle.putString("MyString", "test bundle"); bundle.putParcelable("MyData", new ParcelableData()); intent.putExtras(bundle); startActivity(intent);//ParcelableData parcelableData = getIntent().getParcelableExtra("MyData"); Bundle bundle = getIntent().getExtras(); ParcelableData parcelableData = bundle.getParcelable("MyData"); String testBundleString = bundle.getString("MyString"); Log.v("string=", testBundleString); Log.v("name=", parcelableData.getName()); Log.v("age=", ""+parcelableData.getAge()); -
flags屬性:Intent可調(diào)用addFlags()方法來為Intent添加控制標(biāo)記。
1、FLAG_ACTIVITY_CLEAR_TOP:(效果同Activity LaunchMode的singleTask)
2、FLAG_ACTIVITY_SINGLE_TOP:(效果同Activity LaunchMode的singleTop)
3、FLAG_ACTIVITY_NEW_TASK: (效果類似Activity LaunchMode的singleInstance)
捉到一只Sample↓↓↓↓↓
MianActivity.java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//從Android 7.0開始,一個應(yīng)用提供自身文件給其它應(yīng)用使用時,如果給出一個file://格式的URI的話,應(yīng)用會拋出FileUriExposedException。
//解決方法置入一個不設(shè)防的VmPolicy,但是要確保目標(biāo)應(yīng)用有本地讀寫權(quán)限
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
StrictMode.setVmPolicy(builder.build());
}
}
public void clickButton(View view) {
Intent intent = new Intent();
intent.setAction(android.content.Intent.ACTION_VIEW);
switch (view.getId()) {
case R.id.button_main_call:
intent.setAction(Intent.ACTION_CALL);
intent.setData(Uri.parse("tel:10086"));
break;
case R.id.button_main_dial:
intent.setAction(Intent.ACTION_DIAL);
intent.setData(Uri.parse("tel:10086"));
break;
case R.id.button_main_dialer:
intent.setAction("com.android.phone.action.TOUCH_DIALER");
break;
case R.id.button_main_sms:
intent.setAction(Intent.ACTION_SENDTO);
intent.setData(Uri.parse("smsto:10086"));
intent.putExtra("sms_body", "該吃飯了,下課吧!");
break;
case R.id.button_main_setting:
intent.setAction("android.settings.SETTINGS");
break;
case R.id.button_main_datesetting:
intent.setAction("android.settings.DATE_SETTINGS");
break;
case R.id.button_main_soundsetting:
intent.setAction("android.settings.SOUND_SETTINGS");
break;
case R.id.button_main_wifisetting:
intent.setAction("android.settings.WIFI_SETTINGS");
break;
case R.id.button_main_contacts:
intent.setAction("com.android.contacts.action.LIST_CONTACTS");
break;
case R.id.button_main_web:
intent.setAction(android.content.Intent.ACTION_VIEW);
intent.setData(Uri.parse("http://www.baidu.com"));
break;
case R.id.button_main_showimage:
intent.setAction(android.content.Intent.ACTION_VIEW);
intent.setDataAndType(
Uri.fromFile(new File("mnt/sdcard/Download/landscape.jpg")),
"image/*");
break;
case R.id.button_main_showtext:
intent.setAction(android.content.Intent.ACTION_VIEW);
intent.setDataAndType(
Uri.fromFile(new File("mnt/sdcard/Download/info.txt")),
"text/*");
break;
case R.id.button_main_playaudio:
intent.setAction(android.content.Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File(
"mnt/sdcard/Download/heavencity.mp3")), "audio/*");
break;
case R.id.button_main_playvideo:
intent.setAction(android.content.Intent.ACTION_VIEW);
String type = "video/mp4";
Uri uri = Uri.parse("file:///storage/emulated/0/Pictures/Screenshots/qqq.mp4");
intent.setDataAndType(uri,type);
break;
case R.id.button_main_home:
intent.setAction("android.intent.action.MAIN");
intent.addCategory("android.intent.category.HOME");
break;
default:
break;
}
startActivity(intent);
}
}
AndroidManifest.xml中需要打電話的權(quán)限
<uses-permission android:name="android.permission.CALL_PHONE"/>
layout文件
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/scrollView1"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="@+id/button_main_call"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="clickButton"
android:text="直接撥號" />
<Button
android:id="@+id/button_main_dial"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="clickButton"
android:text="啟動撥號面板" />
<Button
android:id="@+id/button_main_dialer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="clickButton"
android:text="顯示撥號面板" />
<Button
android:id="@+id/button_main_sms"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="clickButton"
android:text="發(fā)送短信" />
<Button
android:id="@+id/button_main_setting"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="clickButton"
android:text="系統(tǒng)設(shè)置" />
<Button
android:id="@+id/button_main_datesetting"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="clickButton"
android:text="日期設(shè)置" />
<Button
android:id="@+id/button_main_soundsetting"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="clickButton"
android:text="聲音設(shè)置" />
<Button
android:id="@+id/button_main_wifisetting"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="clickButton"
android:text="WIFI設(shè)置" />
<Button
android:id="@+id/button_main_web"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="clickButton"
android:text="瀏覽網(wǎng)頁" />
<Button
android:id="@+id/button_main_contacts"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="clickButton"
android:text="查看聯(lián)系人" />
<Button
android:id="@+id/button_main_showimage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="clickButton"
android:text="查看圖片" />
<Button
android:id="@+id/button_main_showtext"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="clickButton"
android:text="查看文本" />
<Button
android:id="@+id/button_main_playvideo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="clickButton"
android:text="播放視頻" />
<Button
android:id="@+id/button_main_playaudio"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="clickButton"
android:text="播放音頻" />
<Button
android:id="@+id/button_main_home"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="clickButton"
android:text="HOME" />
</LinearLayout>
</ScrollView>