引言
http://www.oschina.net/question/54100_28547
http://www.apkbus.com/android-18748-1-1.html
上篇我们介绍了Intents和Intent Filters的理论部分,主要是介绍了:activities、services、broadcastreceivers三种组件的Intent机制两种Intent(显式和隐式)及它们如何去匹配目的组件、Intent对象包含哪些信息、Intent Filters的action & category & data。
Intent的重要性,我不再着重介绍了,但我还是要说:Intent能够使应用程序突破沙盒与外界交流,者这使得Android的世界变得丰富多彩!本篇将用实例来介绍,如何应用Intent,而且继续用SMS方面的例子来阐述。本文的主要内容如下:
- 例子(需求)描述
- STEP1、添加用于显示通讯录的布局文件
- STEP2、添加Button的点击事件
- STEP3、添加通讯录活动
- STEP4、解析通讯录返回的数据
- STEP5、在清单文件AndroidManifest.xml中注册通讯录活动和读取Contact数据库的权限
- 总结
例子(需求)描述
用手机发过SMS的人都知道:
- 用户可以先编辑短信,然后再去通讯录中选择相应的人并发生给他。
- 用户可以在短信内容中插入通讯录中联系人的号码。
我们的这个例子就是要说明如何实现这个功能。要实现这个功能,即是创建一个新的Activity选择(ACTION_PICK)通讯录中的数据,它会显示通讯录中的所有联系人并让用户选择,然后关闭并返回一个联系人的URI给短信程序。下面介绍如何一步一步实现类似的功能,而且是在之前Android 开发之旅:短信的收发及在android模拟器之间实践(一)中发送SMS的例子(TextMessage)基础上加上从通讯录中选择联系人的功能。
STEP1、添加用于显示通讯录的布局文件
我们用一个ListView来显示整个通讯录,其中用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程序中加入一个Button btnContact,通过点击btnContact激活显示通讯录的活动。这只需在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中相应的加入<stringname="btnContact">contact</string>。
STEP2、添加Button的点击事件
在上面准备工作做完之后,我们需要监听btnContact的点击事件,当用户点击btnContact时,跳转显示通讯录界面,当用户选择一个联系人之后,返回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、添加通讯录活动
添加一个类文件,类名为ContactPick(表示通讯录活动名)继承Activity。它的主要功能就是获取从SMS主程序传递来的Intent并提取数据;然后去查询通讯录数据库,取出数据并填充到STEP1中定义的ListView;最后,还需要添加当用户选择一个联系人的事件onItemClick,将结果返回给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、解析通讯录返回的数据
从通讯录活动返回之后,我们从返回的Intent中提取数据并填充到填写电话号码的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中注册通讯录活动和读取Contact数据库的权限
主要工作基本做完了,现在我们只需要注册通讯录活动和读取Contact数据的权限了。完整的清单文件代码如下:
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"/> |
注意通讯录活动的Intent Filters,它的
action是
android.intent.action.PICK;
category是
android.intent.category.DEFAULT。现在我们分析一下这个Intent Filter:
- <actionandroid:name="android.intent.action.PICK"/>:使用户能够可以在通讯录列表中选择一个,然后将选择的联系人的 URL返回给调用者。
- <categoryandroid:name="android.intent.category.DEFAULT"/>:这是默认的category,如果不知道category系统会自动加上。这个属性是让使其能够被像Context.startActivity()等找到。要说明的的是,如果列举了多个category,这个活动仅会去处理那些Intent中都包含了所有列举的category的组件。
我们还可以在清单文件中看到TextMessage活动的Intent Filter:
2 |
<actionandroid:name="android.intent.action.MAIN"/> |
3 |
<categoryandroid:name="android.intent.category.LAUNCHER"/> |
它指
TextMessage活动定是真个程序的入口并且
TextMessage会列举在Launcher即启动列表中。
程序运行结果如下图所示:

图1、主界面

图2、点击contact按钮之后

图3、选择一个联系人之后
总结
我们用发短信中选择联系人的例子说明Intent和Intent Filter,这里体现了两个活动之间如何通过Intent和Intent Filter来交互,这也是我们在编写Android应用程序的时候经常遇到了。本文除了上述的主要内容之外,还涉及别的知识点,下面列举几个个人认为比较有用的知识点: