引言
http://www.oschina.net/question/54100_28547
http://www.apkbus.com/android-18748-1-1.html
上篇我們介紹了Intents和Intent Filters的理論部分,主要是介紹了:activities、services、broadcastreceivers三種組件的Intent機(jī)制兩種Intent(顯式和隱式)及它們?nèi)绾稳テヅ淠康慕M件、Intent對(duì)象包含哪些信息、Intent Filters的action & category & data。
Intent的重要性,我不再著重介紹了,但我還是要說:Intent能夠使應(yīng)用程序突破沙盒與外界交流,者這使得Android的世界變得豐富多彩!本篇將用實(shí)例來介紹,如何應(yīng)用Intent,而且繼續(xù)用SMS方面的例子來闡述。本文的主要內(nèi)容如下:
- 例子(需求)描述
- STEP1、添加用于顯示通訊錄的布局文件
- STEP2、添加Button的點(diǎn)擊事件
- STEP3、添加通訊錄活動(dòng)
- STEP4、解析通訊錄返回的數(shù)據(jù)
- STEP5、在清單文件AndroidManifest.xml中注冊(cè)通訊錄活動(dòng)和讀取Contact數(shù)據(jù)庫(kù)的權(quán)限
- 總結(jié)
例子(需求)描述
用手機(jī)發(fā)過SMS的人都知道:
- 用戶可以先編輯短信,然后再去通訊錄中選擇相應(yīng)的人并發(fā)生給他。
- 用戶可以在短信內(nèi)容中插入通訊錄中聯(lián)系人的號(hào)碼。
我們的這個(gè)例子就是要說明如何實(shí)現(xiàn)這個(gè)功能。要實(shí)現(xiàn)這個(gè)功能,即是創(chuàng)建一個(gè)新的Activity選擇(ACTION_PICK)通訊錄中的數(shù)據(jù),它會(huì)顯示通訊錄中的所有聯(lián)系人并讓用戶選擇,然后關(guān)閉并返回一個(gè)聯(lián)系人的URI給短信程序。下面介紹如何一步一步實(shí)現(xiàn)類似的功能,而且是在之前Android 開發(fā)之旅:短信的收發(fā)及在android模擬器之間實(shí)踐(一)中發(fā)送SMS的例子(TextMessage)基礎(chǔ)上加上從通訊錄中選擇聯(lián)系人的功能。
STEP1、添加用于顯示通訊錄的布局文件
我們用一個(gè)ListView來顯示整個(gè)通訊錄,其中用TextView顯示每一記錄。它們的xml文件分別為contact.xml、listitemlayout,如下所示:
====================================contact.xml
01 |
<? xmlversion = "1.0" encoding = "utf-8" ?> |
03 |
< LinearLayoutxmlns:android = "http://schemas.android.com/apk/res/android" |
05 |
android:orientation = "vertical" |
07 |
android:layout_width = "fill_parent" |
09 |
android:layout_height = "fill_parent" |
13 |
< ListViewandroid:id = "@+id/contactListView" |
15 |
android:layout_width = "fill_parent" |
17 |
android:layout_height = "wrap_content" |
=================================== listitemlayout
01 |
<? xmlversion = "1.0" encoding = "utf-8" ?> |
03 |
< LinearLayoutxmlns:android = "http://schemas.android.com/apk/res/android" |
05 |
android:orientation = "vertical" android:layout_width = "fill_parent" |
07 |
android:layout_height = "fill_parent" > |
09 |
< TextViewandroid:id = "@+id/itemTextView" android:layout_width = "wrap_content" |
11 |
android:layout_height = "wrap_content" android:padding = "10px" |
13 |
android:textSize = "16px" android:textColor = "#FFF" /> |
為了能夠打開通訊錄,我們還需要在TextMessage程序中加入一個(gè)Button btnContact,通過點(diǎn)擊btnContact激活顯示通訊錄的活動(dòng)。這只需在main.xml文件中加入如下代碼:
1 |
< Buttonandroid:layout_width = "wrap_content" |
2 |
android:layout_height = "wrap_content" |
3 |
android:text = "@string/btnContact" |
4 |
android:id = "@+id/btnContact" /> |
記得還有在values/strings.xml中相應(yīng)的加入<stringname="btnContact">contact</string>。
STEP2、添加Button的點(diǎn)擊事件
在上面準(zhǔn)備工作做完之后,我們需要監(jiān)聽btnContact的點(diǎn)擊事件,當(dāng)用戶點(diǎn)擊btnContact時(shí),跳轉(zhuǎn)顯示通訊錄界面,當(dāng)用戶選擇一個(gè)聯(lián)系人之后,返回SMS程序的主界面。這里就要用到了偉大的Intent啦!
01 |
btnContact = (Button) findViewById(R.id.btnContact); |
03 |
btnContact.setOnClickListener( new View.OnClickListener() { |
07 |
publicvoid onClick(View v) { |
11 |
Intent intent = new Intent(Intent.ACTION_PICK, |
13 |
ContactsContract.Contacts.CONTENT_URI); |
15 |
startActivityForResult(intent, PICK_CONTACT); |
STEP3、添加通訊錄活動(dòng)
添加一個(gè)類文件,類名為ContactPick(表示通訊錄活動(dòng)名)繼承Activity。它的主要功能就是獲取從SMS主程序傳遞來的Intent并提取數(shù)據(jù);然后去查詢通訊錄數(shù)據(jù)庫(kù),取出數(shù)據(jù)并填充到STEP1中定義的ListView;最后,還需要添加當(dāng)用戶選擇一個(gè)聯(lián)系人的事件onItemClick,將結(jié)果返回給SMS主程序,這里也用到了我們偉大的Intent啦!代碼如下:
01 |
package skynet.com.cnblogs.www; |
04 |
import android.app.Activity; |
06 |
import android.content.Intent; |
08 |
import android.database.Cursor; |
10 |
import android.net.Uri; |
12 |
import android.os.Bundle; |
14 |
import android.provider.ContactsContract; |
16 |
import android.view.View; |
18 |
import android.widget.AdapterView; |
20 |
import android.widget.ListView; |
22 |
importandroid.widget.SimpleCursorAdapter; |
24 |
import android.widget.AdapterView.OnItemClickListener; |
27 |
publicclass ContactPick extends Activity { |
29 |
/** Called when the activity is first created. */ |
33 |
publicvoid onCreate(Bundle savedInstanceState) { |
35 |
super .onCreate(savedInstanceState); |
37 |
setContentView(R.layout.main); |
40 |
Intent orgIntent=getIntent(); |
42 |
Uri queryUri=orgIntent.getData(); |
44 |
final Cursor c = managedQuery(queryUri, |
55 |
String[] fromColumns= new String[]{ContactsContract.Contacts.DISPLAY_NAME}; |
57 |
int [] toLayoutIDs = newint[] { R.id.itemTextView }; |
59 |
SimpleCursorAdapter adapter = newSimpleCursorAdapter( this , |
61 |
R.layout.listitemlayout, c, fromColumns, toLayoutIDs); |
63 |
ListView lv = (ListView) findViewById(R.id.contactListView); |
65 |
lv.setAdapter(adapter); |
67 |
lv.setOnItemClickListener( new OnItemClickListener() { |
71 |
publicvoid onItemClick(AdapterView<?> parent, View view, int pos, |
75 |
c.moveToPosition(pos); |
77 |
int rowId = c.getInt(c.getColumnIndexOrThrow(ContactsContract.Contacts._ID)); |
79 |
Uri outURI = Uri.parse(ContactsContract.Contacts.CONTENT_URI.toString() + rowId); |
81 |
Intent outData = new Intent(); |
83 |
outData.setData(outURI); |
85 |
setResult(Activity.RESULT_OK,outData); |
STEP4、解析通訊錄返回的數(shù)據(jù)
從通訊錄活動(dòng)返回之后,我們從返回的Intent中提取數(shù)據(jù)并填充到填寫電話號(hào)碼的EditView中。代碼主要如下:
02 |
publicvoid onActivityResult( int reqCode, int resCode, Intent data) { |
04 |
super .onActivityResult(reqCode, resCode, data); |
09 |
case (PICK_CONTACT): { |
11 |
if (resCode == Activity.RESULT_OK) { |
15 |
Uri contactData = data.getData(); |
17 |
Cursor c = managedQuery(contactData, null , null , null , null ); |
21 |
name = c.getString(c.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)); |
25 |
tv = (TextView)findViewById(R.id.edtPhoneNo); |
STEP5、在清單文件AndroidManifest.xml中注冊(cè)通訊錄活動(dòng)和讀取Contact數(shù)據(jù)庫(kù)的權(quán)限
主要工作基本做完了,現(xiàn)在我們只需要注冊(cè)通訊錄活動(dòng)和讀取Contact數(shù)據(jù)的權(quán)限了。完整的清單文件代碼如下:
01 |
<? xmlversion = "1.0" encoding = "utf-8" ?> |
02 |
< manifestxmlns:android = "http://schemas.android.com/apk/res/android" |
03 |
package = "skynet.com.cnblogs.www" android:versionCode = "1" |
04 |
android:versionName = "1.0" > |
08 |
< activityandroid:name = ".TextMessage" android:label = "@string/app_name" > |
12 |
< actionandroid:name = "android.intent.action.MAIN" /> |
13 |
< categoryandroid:name = "android.intent.category.LAUNCHER" /> |
19 |
< activityandroid:name = ".ContactPick" android:label = "@string/app_name" > |
20 |
< actionandroid:name = "android.intent.action.PICK" /> |
21 |
< categoryandroid:name = "android.intent.category.DEFAULT" /> |
27 |
< uses-permissionandroid:name = "android.permission.SEND_SMS" /> |
28 |
< uses-permissionandroid:name = "android.permission.READ_CONTACTS" /> |
注意通訊錄活動(dòng)的Intent Filters,它的
action是
android.intent.action.PICK;
category是
android.intent.category.DEFAULT。現(xiàn)在我們分析一下這個(gè)Intent Filter:
- <actionandroid:name="android.intent.action.PICK"/>:使用戶能夠可以在通訊錄列表中選擇一個(gè),然后將選擇的聯(lián)系人的 URL返回給調(diào)用者。
- <categoryandroid:name="android.intent.category.DEFAULT"/>:這是默認(rèn)的category,如果不知道category系統(tǒng)會(huì)自動(dòng)加上。這個(gè)屬性是讓使其能夠被像Context.startActivity()等找到。要說明的的是,如果列舉了多個(gè)category,這個(gè)活動(dòng)僅會(huì)去處理那些Intent中都包含了所有列舉的category的組件。
我們還可以在清單文件中看到TextMessage活動(dòng)的Intent Filter:
2 |
< actionandroid:name = "android.intent.action.MAIN" /> |
3 |
< categoryandroid:name = "android.intent.category.LAUNCHER" /> |
它指
TextMessage活動(dòng)定是真?zhèn)€程序的入口并且
TextMessage會(huì)列舉在Launcher即啟動(dòng)列表中。
程序運(yùn)行結(jié)果如下圖所示:

圖1、主界面

圖2、點(diǎn)擊contact按鈕之后

圖3、選擇一個(gè)聯(lián)系人之后
總結(jié)
我們用發(fā)短信中選擇聯(lián)系人的例子說明Intent和Intent Filter,這里體現(xiàn)了兩個(gè)活動(dòng)之間如何通過Intent和Intent Filter來交互,這也是我們?cè)诰帉慉ndroid應(yīng)用程序的時(shí)候經(jīng)常遇到了。本文除了上述的主要內(nèi)容之外,還涉及別的知識(shí)點(diǎn),下面列舉幾個(gè)個(gè)人認(rèn)為比較有用的知識(shí)點(diǎn):