前言
每個(gè)應(yīng)用程序都有若干個(gè)Activity組成儿奶,每一個(gè)Activity都是一個(gè)應(yīng)用程序與用戶進(jìn)行交互的窗口章母,呈現(xiàn)不同的交互界面舵变。因?yàn)槊恳粋€(gè)Acticity的任務(wù)不一樣晾腔,所以經(jīng)常互在各個(gè)Activity之間進(jìn)行跳轉(zhuǎn)矛紫,在Android中這個(gè)動(dòng)作是靠Intent來完成的。你通過startActivity()方法發(fā)送一個(gè)Intent給系統(tǒng),系統(tǒng)會(huì)根據(jù)這個(gè)Intent幫助你找到對(duì)應(yīng)的Activity参歹,即使這個(gè)Activity在其他的應(yīng)用中,也可以用這種方法啟動(dòng)它隆判。
Intent的定義
Intent意圖可以是明確的指定組件(四大組件)的名稱犬庇,這樣你可以精確的啟動(dòng)某個(gè)系統(tǒng)組件,比如啟動(dòng)一個(gè)Activity侨嘀。它也可以是模糊的臭挽,沒有指定組件名稱,只要是能夠匹配到這個(gè)Intent的應(yīng)用都可以接收到咬腕,比如發(fā)送一個(gè)拍照Intent欢峰,所有的拍照應(yīng)用都會(huì)響應(yīng)。
顯式Intent和隱式Intent
-
顯式的Intent就是你已經(jīng)知道要啟動(dòng)的組件名稱涨共,比如某個(gè)Activity的包名和類名纽帖,在Intent中明確的指定了這個(gè)組件(Activity),一般來說這種Intent經(jīng)常用在一個(gè)應(yīng)用中举反,因?yàn)槟阋呀?jīng)明確的知道要啟動(dòng)的組件名稱懊直。
當(dāng)你創(chuàng)建一個(gè)顯式Intent來啟動(dòng)一個(gè)Activity或者Service時(shí),系統(tǒng)會(huì)立刻通過你的Intent對(duì)象啟動(dòng)那個(gè)組件火鼻。
-
隱式的Intent就是你不知道要啟動(dòng)的組件名稱室囊,只知道一個(gè)Intent動(dòng)作要執(zhí)行,比如:拍照魁索,錄像融撞,查看地圖。一般來說這種Intent用在不同的應(yīng)用之間傳遞信息粗蔚。
當(dāng)你創(chuàng)建一個(gè)隱式Intent尝偎,系統(tǒng)會(huì)根據(jù)manifest file中的intent filter找匹配的組件,如果你發(fā)送的Intent匹配到一個(gè)intent filter支鸡,系統(tǒng)會(huì)把你的Intent傳遞給該filter對(duì)應(yīng)的組件(Activity冬念、Service等),并且啟動(dòng)它牧挣。如果找到多個(gè)匹配的intent filter對(duì)應(yīng)的應(yīng)用程序急前,則會(huì)彈出一個(gè)對(duì)話框讓你選擇哪個(gè)應(yīng)用程序接受你的Intent。
注:
- intent filter是一種應(yīng)用程序manifest文件中的語法表達(dá)瀑构,就像是html的標(biāo)簽裆针,它是一個(gè)系統(tǒng)組件標(biāo)簽(比如:Activity)的組成部分刨摩,可以說是子標(biāo)簽吧,這個(gè)系統(tǒng)組件接受什么樣的intent就是用它來指定的世吨,如果一個(gè)系統(tǒng)組件不寫intent filter澡刹,那么它只能通過顯式的intent來啟動(dòng)。
- 出于安全的角度耘婚,你的Service組件務(wù)必不要用隱式的intent filter來進(jìn)行說明罢浇,因?yàn)橛秒[式的intent啟動(dòng)一個(gè)Service往往不能保證Service會(huì)被啟動(dòng),并且用戶也不知道哪個(gè)Service會(huì)響應(yīng)你的Intent沐祷。從Android5.0(API 21)嚷闭,系統(tǒng)會(huì)拋出異常當(dāng)你用隱式的Intent去調(diào)用bindService()方法。
Intent七大屬性
Intent對(duì)象大致包括7大屬性:ComponentName赖临、 Action 胞锰、 Category 、 Data 兢榨、Type嗅榕、 Extra 、Flag吵聪。
-
Component Name(目標(biāo)組件): 目標(biāo)組件
要啟動(dòng)的組件名稱凌那,在創(chuàng)建Intent的時(shí)候是可選的,但是它是顯式Intent的重要標(biāo)志吟逝,有它就意味著只有Component name匹配上的那個(gè)組件才能接收你發(fā)送出來的顯示intent案怯。如果不寫那么你創(chuàng)建的Intent就是隱式的,系統(tǒng)會(huì)根據(jù)這個(gè)intent的其他信息(比如:action澎办、data、category)來確定哪些組件來接收這個(gè)intent金砍,所以如果你想明確的啟動(dòng)哪個(gè)組件局蚀,就通過component name來指定。Intent的ComponentName屬性是一個(gè)類的全稱恕稠,包括包名琅绅,比如:com.example.ExampleActivity,你可以通過Intent的setComponent()鹅巍,setClass()千扶,setClassName()方法來設(shè)定,也可以通過Intent的構(gòu)造方法來設(shè)定骆捧。
-
Action(動(dòng)作): 用來表示意圖的動(dòng)作澎羞,如:查看,發(fā)郵件敛苇,打電話
是一個(gè)可以指明目標(biāo)組件行為的字符串妆绞。action很大程度上決定了category和data中應(yīng)傳入的信息;您也可以在自己的應(yīng)用程序組件中指定action,以便讓其他應(yīng)用程序啟動(dòng)自己的組件括饶。對(duì)應(yīng)action中字符串株茶,不建議使用硬編碼的形式,而應(yīng)在所屬組件的類中設(shè)置為常量图焰。如需在自己的組件中定義action启盛,應(yīng)以應(yīng)用的包名作為前綴,比如:
public static final String ACTION_TIMETRAVEL="com.example.action.TIMETRAVEL";
常用動(dòng)作
最常用的是Action_MAIN(作為初始的Activity啟動(dòng),沒有數(shù)據(jù)的輸入輸出)ACTION_MAIN:(android.intent.action.MAIN)Android程序入口技羔。 每個(gè)Android應(yīng)用必須且只能包含一個(gè)此類型的Action聲明僵闯。【如果設(shè)置多個(gè)堕阔,則哪個(gè)在前棍厂,執(zhí)行哪個(gè)〕剑】 ACTION_VIEW: (android.intent.action.VIEW) 顯示指定數(shù)據(jù)牺弹。 ACTION_EDIT: (android.intent.action.EDIT) 編輯指定數(shù)據(jù)。 ACTION_DIAL: (android.intent.action.DIAL) 顯示撥號(hào)面板时呀。 ACTION_CALL: (android.intent.action.CALL) 直接呼叫Data中所帶的號(hào)碼张漂。 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的動(dòng)作,參數(shù)可以為常量
getAction() 方法用來獲取Intent動(dòng)作名稱
上面的Action都是系統(tǒng)定義好的,具有一定意義的動(dòng)作指向的動(dòng)作坞靶。
Intent的Action對(duì)象其實(shí)就是一個(gè)字符串常量憔狞,系統(tǒng)的Action對(duì)象是系統(tǒng)定義好的字符串常量,我們也可以自己定義自己的Action作為字符串常量彰阴。就像上面的例子使用到了自定義的Action字符串對(duì)象瘾敢。 -
category(類別): 用來表示動(dòng)作的類別。
Intent的action尿这、category屬性都是普通的字符串,其中action表示Intent需要完成的一個(gè)抽象”動(dòng)作”,而category則為action添加額外的類別信息,通常action和category一塊使用簇抵。
需要指出的是,一個(gè)Intent中只能包含一個(gè)action屬性,但可以包含多個(gè)category屬性射众。當(dāng)程序創(chuàng)建Intent時(shí),該Intent默認(rèn)啟動(dòng)常量值為andorid.intent.category.DEFAULT的組件碟摆。這里的一個(gè)Intent中只能包含一個(gè)action屬性,并不是Activity中xml的設(shè)置規(guī)范叨橱,而是你要跳轉(zhuǎn)到的頁面去焦履,你只能設(shè)置一個(gè)Action的值拓劝。
常用的Category:CATEGORY_DEFAULT:Android系統(tǒng)中默認(rèn)的執(zhí)行方式,按照普通Activity的執(zhí)行方式執(zhí)行嘉裤≈A伲
CATEGORY_HOME:設(shè)置該組件為Home Activity。
CATEGORY_PREFERENCE:設(shè)置該組件為Preference屑宠∠岫矗
CATEGORY_LAUNCHER:設(shè)置為當(dāng)前應(yīng)用程序優(yōu)先級(jí)最高的Activity,通常與ACTION_MAIN配合使 用典奉√煞
CATEGORY_BROWSABLE:設(shè)置該組件可以使用瀏覽器啟動(dòng)∥谰粒
CATEGORY_GADGET:設(shè)置該組件可以內(nèi)嵌到另外的Activity中公你。
-
data(數(shù)據(jù)): 表示與動(dòng)作要操作的數(shù)據(jù)。如:查看指定的聯(lián)系人
Data數(shù)據(jù)用來向Action屬性提供動(dòng)作的數(shù)據(jù)假瞬。這里的Data不是Intent里面的數(shù)據(jù)陕靠,而是指明動(dòng)作的具體數(shù)據(jù),比如說動(dòng)作是打電話脱茉,那么打給具體的某一個(gè)人剪芥,就用到了date里面的數(shù)據(jù)來指定。同樣發(fā)郵件琴许、或打開具體的某一個(gè)網(wǎng)址也是通過Data數(shù)據(jù)税肪。
Data屬性只接受Uri對(duì)象,Uri對(duì)象是統(tǒng)一資源標(biāo)識(shí)符榜田。對(duì)應(yīng)概念不用太多理解益兄,只需知道里面某些具體值的表現(xiàn)形式就可以了。
Uri其實(shí)就是相當(dāng)于一個(gè)網(wǎng)址箭券,如圖所示:
網(wǎng)址只是Uri其中一種格式的字符串偏塞,要使用它還要把它解析后轉(zhuǎn)化為Uri類型。
為Intent對(duì)象添加Data數(shù)據(jù)邦鲫,代碼:
intent.setData(Uri.parse(“http://www.baidu.com“));系統(tǒng)內(nèi)置的幾個(gè)Data屬性常量:
tel://:號(hào)碼數(shù)據(jù)格式,后跟電話號(hào)碼神汹。 mailto://:郵件數(shù)據(jù)格式庆捺,后跟郵件收件人地址。 smsto://:短息數(shù)據(jù)格式屁魏,后跟短信接收號(hào)碼滔以。 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ù)類型): 對(duì)data類型的描述适滓。
與Data有關(guān)的敦迄,這個(gè)不是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(附件信息): 附件信息罚屋。如:詳細(xì)資料,一個(gè)文件嗅绸,某事脾猛。
extras屬性主要用于傳遞目標(biāo)組件所需要的額外的數(shù)據(jù)。
通過putExtras()方法設(shè)置鱼鸠。保存數(shù)據(jù);
通過getExtras()方法設(shè)置猛拴。獲取數(shù)據(jù)通常我們使用Intent來直接傳遞Bundle對(duì)象,但也可以傳遞其他系統(tǒng)內(nèi)置的一些參數(shù)瞧柔。
如果要傳遞是是對(duì)象漆弄,那么對(duì)象必須實(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開始倒谷,一個(gè)應(yīng)用提供自身文件給其它應(yīng)用使用時(shí),如果給出一個(gè)file://格式的URI的話糙箍,應(yīng)用會(huì)拋出FileUriExposedException渤愁。
//解決方法置入一個(gè)不設(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="直接撥號(hào)" />
<Button
android:id="@+id/button_main_dial"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="clickButton"
android:text="啟動(dòng)撥號(hào)面板" />
<Button
android:id="@+id/button_main_dialer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="clickButton"
android:text="顯示撥號(hào)面板" />
<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>