1.Intent是什么
Android中提供了Intent機制來協助應用間的交互與通訊,Intent負責對
應用中一次操作的動作、動作涉及數據、附加數據進行描述,Android則
根據此Intent的描述,負責找到對應的組件,將 Intent傳遞給調用的組
件,並完成組件的調用。
Intent不僅可用於應用程序之間,也可用於應用程序內部的Activity/Service
之間的交互。因此,Intent在這里起着一個中介的作用,專門提供組
件互相調用的相關信息,實現調用者與被調用者之間的解耦。
2.Intent定義的內容
在Android參考文檔中,對Intent的定義是執行某操作的一個抽象描述。
(1)Action,也就是要執行的動作
(2)Data,也就是執行動作要操作的數據
(3)type(數據類型)
(4)category(類別)
(5) component(組件)
(6) extras(附加信息)
2.1)執行的動作(action)
動作(action)的一個簡要描述,如VIEW_ACTION(查看)、EDIT_ACTION
(修改)等,Android為我們定義了一套標准動作。
系統定義的動作(action)
ACTION_CALL activity Initiate a phone call.
ACTION_EDIT activity Display data for the user to edit.
ACTION_MAIN activity Start up as the initial activity of a task, with no data input and no returned output.
ACTION_SYNC activity Synchronize data on a server with data on the mobile device.
ACTION_BATTERY_LOW broadcast receiver A warning that the battery is low.
ACTION_HEADSET_PLUG broadcast receiver A headset has been plugged into the device, or unplugged from it.
ACTION_SCREEN_ON broadcast receiver The screen has been turned on.
ACTION_TIMEZONE_CHANGED broadcast receiver The setting for the time zone has changed.
2.2)執行動作要操作的數據(data)
Android中采用指向數據的一個URI來表示,
如在聯系人應用中,一個指向某聯系人的URI可能為:content://contacts/1。
這種URI表示,通過 ContentURI這個類來描述,具體可以參考android.net.ContentURI類的文檔。
以聯系人應用為例,以下是一些action / data對,及其它們要表達的意圖
VIEW_ACTION content://contacts/1-- 顯示標識符為"1"的聯系人的詳細信息
EDIT_ACTION content://contacts/1-- 編輯標識符為"1"的聯系人的詳細信息
VIEW_ACTION content://contacts/-- 顯示所有聯系人的列表
PICK_ACTION content://contacts/-- 顯示所有聯系人的列表,並且允許用戶在列表中選擇一個聯系人,然后把這個聯系人返回給父activity。
--------------------code-----------------
action為Intent.ACTION_VIEW,data為ContactsContract.Contacts.CONTENT_URI
查看聯系人列表
Intent intent = new Intent(Intent.ACTION_VIEW,Uri.parse("content://com.android.contacts/contacts")); //Intent intent = new Intent(Intent.ACTION_VIEW,ContactsContract.Contacts.CONTENT_URI);
startActivity(intent);
查看某一個聯系人
Intent intent = new Intent(Intent.ACTION_VIEW,Uri.parse("content://com.android.contacts/contacts/190")); //Intent intent = new Intent(Intent.ACTION_VIEW,ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, 190));
startActivity(intent);
編輯某一個聯系人
Intent intent = new Intent(Intent.ACTION_EDIT,Uri.parse("content://com.android.contacts/contacts/190")); //Intent intent = new Intent(Intent.ACTION_EDIT,ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, 190));
startActivity(intent);
注意:不能編輯一個聯系人列表。
Intent intent = new Intent(Intent.ACTION_EDIT,Uri.parse("content://com.android.contacts/contacts"));//錯
顯示聯系人列表,並選擇一個,然后獲取該聯系人信息;
Intent intent = new Intent(Intent.ACTION_PICK,ContactsContract.Contacts.CONTENT_URI); startActivityForResult(intent, 100); @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if(requestCode == 100){ if(resultCode == RESULT_OK){ Uri uri = data.getData(); Cursor cursor = getContentResolver().query(uri, null, null, null, null); if(cursor.moveToFirst()){ String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)); System.out.println(name); } cursor.close(); } } }
-----------------------code-------------------------------
Uri uri = data.getData(); Cursor cursor = getContentResolver().query(uri, null, null, null, null); if(cursor.moveToFirst()){ String name = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)); nameet.setText(name); String id = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID)); Cursor c2 = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID+"="+id, null, null); c2.moveToFirst(); String phone = c2.getString(c2.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)); phoneet.setText(phone); c2.close(); cursor.close(); }
2.3)category 類別
category(類別)是被執行動作的附加信息。
2.4)type(數據類型)
type(數據類型),顯式指定Intent的數據類型(MIME)。一般Intent
的數據類型能夠根據數據本身進行判定,
但是通過設置這個屬性,可以強制采用顯式指定的類型而不再進行推導。
Intent intent = new Intent(Intent.ACTION_VIEW); intent.setDataAndType(Uri.parse("file:///mnt/sdcard/a.pdf"),"application/pdf"); startActivity(intent);
2.5)component(組件)
component(組件),指定Intent的的目標組件的類名稱。
通常 Android會根據Intent 中包含的其它屬性的信息
,比如action、data/type、category進行查找,最終找到一個
與之匹配的目標組件。
但是,如果 component這個屬性有指定的話,將直接
使用它指定的組件,而不再執行上述查找過程。
指定了這個屬性以后,Intent的其它所有屬性都是可選的。
Intent intent = new Intent(); ComponentName component = new ComponentName(getApplicationContext(), SecondActivity.class); intent.setComponent(component); startActivity(intent);
2.6)extras(附加信息)
extras(附加信息),是其它所有附加信息的集合。使用extras可以為
組件提供擴展信息,比如,如果要執行“發送電子郵件”這個動作,可以
將電子郵件的標題、正文等保存在extras里,傳給電子郵件發送組件。
3.Android如何解析Intent
在應用中,我們可以以兩種形式來使用Intent:
直接Intent:
指定了component屬性的Intent(調用setComponent
(ComponentName)或者setClass(Context, Class)來指定)。
通過指定具體的組件類,通知應用啟動對應的組件。
間接Intent:沒有指定comonent屬性的Intent。這些Intent需要
包含足夠的信息,這樣系統才能根據這些信息,在所有的可用組件
中,確定滿足此Intent的組件。
間接Intent
Intent解析機制主要是通過查找已注冊在AndroidManifest.xml中
的所有IntentFilter及其中定義的Intent,最終找到匹配的Intent。
IntentFilter意圖篩選器
IntentFilter用來描述Activity能夠做些什么事情。
應用程序的組件為了告訴Android自己能響應、處理哪些隱式Intent
請求,可以聲明一個甚至多個Intent Filter。每個Intent Filter描
述該組件所能響應Intent請求的能力——組件希望接收什么類型的請求
行為,什么類型的請求數據。
間接Intent匹配
隱式Intent(Explicit Intents)和Intent Filter(Implicit Intents)
進行比較時的三要素是Intent的動作、數據以及類別。(隱式Intent:指的是在
Intent intent = new Intent()時的java代碼,而Intent filter是在androidmanifest.xml
文件中定義的。)
實際上,一個隱式Intent請求要能夠傳遞給目標組件,必要通過這三個方
面的 檢查。如果任何一方面不匹配,Android都不會將該隱式Intent傳遞
給目標組件。接下來我們講解這三方面檢查的具體規則。
隱式啟動:
Intent intent = new Intent(); intent.setAction("com.anjoyo.myfirsttest"); startActivity(intent);
intent-filter配置:
<activity android:name=".intentfilter.TestActivity"> <intent-filter > <action android:name="com.anjoyo.myfirsttest"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </activity>
補充
1.作為一個程序為桌面程序
<activity android:name=".intent.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.HOME"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </activity>
<category android:name="android.intent.category.HOME"/>回到桌面 <category android:name="android.intent.category.LAUNCHER"/>作為應用的入口
2.隱式Intent(Explicit Intents)和Intent Filter(Implicit Intents)
進行比較時的三要素是Intent的動作、數據以及類別。
實際上,一個隱式Intent請求要能夠傳遞給目標組件,必要通過這三個方面
的 檢查。如果任何一方面不匹配,Android都不會將該隱式Intent傳遞給目
標組件。接下來我們講解這三方面檢查的具體規則。
1).動作測試
<intent-filter>元素中可以包括子元素<action>,比如:
<intent-filter> <action android:name=”com.example.project.SHOW_CURRENT” /> <action android:name=”com.example.project.SHOW_RECENT” /> <action android:name=”com.example.project.SHOW_PENDING” /> </intent-filter>
一條<intent-filter>元素至少應該包含一個<action>,否則任何Intent
請求都不能和 該<intent-filter>匹配。
如果隱式啟動一個Activity,那么還需要在<intent-filter>中加入
<category android:name="android.intent.category.DEFAULT"/>
例子:
<activity android:name="xxx"> <intent-filter > <action android:name="com.anjoyo.mysecond"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> <intent-filter > <action android:name="com.anjoyo.mysecond2"/> <action android:name="com.anjoyo.mysecond3"/> <category android:name="android.intent.category.DEFAULT"/> </intent-filter> </activity>
action匹配規則:找到一個與隱式Intent的Action定義相同的Intent filter.
2).類別測試
<intent-filter>元素可以包含<category>子元素,比如:
<intent-filter> <category android:name=”android.Intent.Category.DEFAULT” /> <category android:name=”android.Intent.Category.BROWSABLE” /> </intent-filter>
只有當Intent請求中所有的Category與組件中某一個IntentFilter的
<category>完全匹配時,才會讓該Intent請求通過測試,IntentFilter
中多余的<category>聲明並不會導致匹配失敗。
3).數據在<intent-filter>中的描述如下:
<intent-filter> <data android:type=”video/mpeg” android:scheme=”http” . . . /> <data android:type=”audio/mpeg” android:scheme=”http” . . . /> </intent-filter>
<data>元素指定了希望接受的Intent請求的數據URI和數據類型,
URI被分成三部分來進行匹配:scheme、authority和path。
其中,用setData()設定的Intent請求的URI數據類型和scheme必須
與IntentFilter中所指定的一致。若IntentFilter中還指定了
authority或path,它們也需要相匹配才會通過測試。
如:http://www.baidu.com http就是schema
tel:1390023232 tel就是schema
file:///mnt/sdcard/Picture/xx.jpg file就是schema
例子:
Intent intent = new Intent(); intent.setAction(Intent.ACTION_CALL); intent.setData(Uri.parse("tel:123343")); startActivity(intent);
<activity android:name=".intent.ForthActivity"> <intent-filter> <action android:name="android.intent.action.CALL"/> <category android:name="android.intent.category.DEFAULT"/> <data android:scheme="tel"/> </intent-filter> </activity>
3.
1).向下一個Activity傳遞數據(使用Bundle和Intent.putExtras)
Intent it = new Intent(Activity.Main.this, Activity2.class);
Bundle bundle=new Bundle();
bundle.putString("name", "This is from MainActivity!");
it.putExtras(bundle);
startActivity(it);
對於數據的獲取可以采用:
Bundle bundle=getIntent().getExtras();
String name=bundle.getString("name");
2).向上一個Activity返回結果
(使用setResult,針對startActivityForResult(it,REQUEST_CODE)啟動的Activity)
Intent intent=getIntent(); Bundle bundle2=new Bundle(); bundle2.putString("name", "This is from ShowMsg!"); intent.putExtras(bundle2); setResult(RESULT_OK, intent);
回調上一個Activity的結果處理函數(onActivityResult)
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if(requestCode==REQUEST_CODE) { if(resultCode==RESULT_CANCELED) setTitle("cancle"); else if (resultCode==RESULT_OK) { String temp=null; Bundle (); if(bundle!=null) bundle=data.getExtras temp=bundle.getString("name"); setTitle(temp); } } }
簡單例子:
1,調用web瀏覽器
Uri myBlogUri = Uri.parse(http://www.cmd100.com); intent = new Intent(Intent.ACTION_VIEW, myBlogUri);
2,地圖
Uri mapUri = Uri.parse("geo:38.899533,-77.036476"); intent = new Intent(Intent.ACTION_VIEW, mapUri);
3,調撥打電話界面
Uri telUri = Uri.parse("tel:10086"); intent = new Intent(Intent.ACTION_DIAL, telUri);
4,直接撥打電話
Uri callUri = Uri.parse("tel:10086"); intent = new Intent(Intent.ACTION_CALL, callUri);
5,卸載
Uri uninstallUri = Uri.fromParts("package", "xxx", null); intent = new Intent(Intent.ACTION_DELETE, uninstallUri);
6,安裝
Uri installUri = Uri.fromParts("package", "xxx", null); intent = new Intent(Intent.ACTION_PACKAGE_ADDED, installUri);
7,播放
Uri playUri = Uri.parse("file:///sdcard/download/everything.mp3"); intent = new Intent(Intent.ACTION_VIEW, playUri);
8,發郵件
Uri emailUri = Uri.parse("mailto:xx@xxx.com"); intent = new Intent(Intent.ACTION_SENDTO, emailUri);
9,發郵件
intent = new Intent(Intent.ACTION_SEND); String[] tos = { "xx@xxx.com" }; String[] ccs = { "xx@xxx.com" }; intent.putExtra(Intent.EXTRA_EMAIL, tos); intent.putExtra(Intent.EXTRA_CC, ccs); intent.putExtra(Intent.EXTRA_TEXT, "body"); intent.putExtra(Intent.EXTRA_SUBJECT, "subject"); intent.setType("message/rfc882"); Intent.createChooser(intent, "Choose Email Client");
10,發短信
Uri smsUri = Uri.parse("tel:10086"); intent = new Intent(Intent.ACTION_VIEW, smsUri); intent.putExtra("sms_body", "hello~"); intent.setType("vnd.android-dir/mms-sms");
11,直接發郵件
Uri smsToUri = Uri.parse("smsto://10086"); intent = new Intent(Intent.ACTION_SENDTO, smsToUri); intent.putExtra("sms_body", "hello");
12,發彩信
Uri mmsUri = Uri.parse("content://media/external/images/media/23"); intent = new Intent(Intent.ACTION_SEND); intent.putExtra("sms_body", "hello"); intent.putExtra(Intent.EXTRA_STREAM, mmsUri); intent.setType("image/png");
用獲取到的Intent直接調用startActivity(intent)就可以了。
==================================================================