|
上一篇中使用了打电话发短信的功能,但号码联系人信息我们还不知道。本篇开始讲如何从Android中得到本机联系人的信息。
由于Android较快的版本升级,部分API已经发生了变化。本篇探究的通过ContentProvider机制获取联系人的API从Android2.0开始做了很大调整,原来的android.provider.Contacts类及其下相关类由android.provider.ContactsContract代替。原类体系标记为Deprecated(废弃),因为兼容的原因目前还存在,但不保证以后的更新版本中完全丢弃。
所以本文先从Android2.1以上平台的联系人读取开始说起,下面给出代码在Android2.1/2.2中运行的效果图,
首先,创建类ViewContacts继承ListActivity,并设为为应用的开始Activity。
ViewContacts.java 代码:
package jtapp.contacts;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import android.app.ListActivity;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.widget.SimpleAdapter;
public class ViewContacts extends ListActivity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
List<HashMap<String, String>> items = fillMaps();
SimpleAdapter adapter = new SimpleAdapter(
this,items,R.layout.list_item,
new String[]{"name","key"},
new int[]{R.id.item,R.id.item2});
this.setListAdapter(adapter);
}
private List<HashMap<String, String>> fillMaps() {
List<HashMap<String, String>> items = new ArrayList<HashMap<String, String>>();
Cursor cur = null;
try {
// Query using ContentResolver.query or Activity.managedQuery
cur = getContentResolver().query(
ContactsContract.Contacts.CONTENT_URI, null, null, null, null);
if (cur.moveToFirst()) {
int idColumn = cur.getColumnIndex(
ContactsContract.Contacts._ID);
int displayNameColumn = cur.getColumnIndex(
ContactsContract.Contacts.DISPLAY_NAME);
// Iterate all users
do {
String contactId;
String displayName;
String phoneNumber = "";
// Get the field values
contactId = cur.getString(idColumn);
displayName = cur.getString(displayNameColumn);
// Get number of user's phoneNumbers
int numberCount = cur.getInt(cur.getColumnIndex(
ContactsContract.Contacts.HAS_PHONE_NUMBER));
if (numberCount>0) {
Cursor phones = getContentResolver().query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID
+ " = " + contactId
/*+ " and " + ContactsContract.CommonDataKinds.Phone.TYPE
+ "=" + ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE*/,
null, null);
if (phones.moveToFirst()) {
int numberColumn = phones.getColumnIndex(
ContactsContract.CommonDataKinds.Phone.NUMBER);
// Iterate all numbers
do {
phoneNumber += phones.getString(numberColumn) + ",";
} while (phones.moveToNext());
}
}
// Add values to items
HashMap<String, String> i = new HashMap<String, String>();
i.put("name", displayName);
i.put("key", phoneNumber);
items.add(i);
} while (cur.moveToNext());
} else {
HashMap<String, String> i = new HashMap<String, String>();
i.put("name", "Your Phone");
i.put("key", "Have No Contacts.");
items.add(i);
}
} finally {
if (cur != null)
cur.close();
}
return items;
}
}
main.xml 代码:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
androidrientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="show your phone's contacts:"
/>
<ListView android:id="@id/android:list"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:drawSelectorOnTop="false"
/>
</LinearLayout>
list_item.xml 代码:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TableRow android:id="@+id/TableRow01"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView android:id="@+id/item"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20px" />
<TextView android:text=": "
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20px" />
<TextView android:id="@+id/item2"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20px" />
</TableRow>
</LinearLayout>
AndroidManifest.xml 增加uses权限READ_CONTACTS 代码:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="jtapp.contacts" android:versionCode="1" android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".ViewContacts" android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.READ_CONTACTS"></uses-permission>
</manifest>
以上文件编写好后,应用就能够在Android2.1模拟器上正确运行了。
那么该app如果在android1.6上运行,会怎么样呢?1.6上并没有ContactsContract类体系,所以就会报错了。需要注意,ContactContract类是在API Level 5增加的,之前的Android版本并不支持。
在Android 1.6 (API Level 4)上,获取联系人的方法将fillMaps()实现为如下:
private List<HashMap<String, String>> fillMaps() {
List<HashMap<String, String>> items = new ArrayList<HashMap<String, String>>();
Cursor cur = null;
try {
// Form an array specifying which columns to return.
String[] projection = new String[] {
People._ID,
People.NAME,
People.NUMBER
};
// query using ContentResolver.query or Activity.managedQuery
cur = getContentResolver().query(
People.CONTENT_URI,projection, null,null, null);
if (cur.moveToFirst()) {
String name;
String phoneNumber;
int nameColumn = cur.getColumnIndex(People.NAME);
int phoneColumn = cur.getColumnIndex(People.NUMBER);
do {
// Get the field values
name = cur.getString(nameColumn);
phoneNumber = cur.getString(phoneColumn);
// Do something with the values.
HashMap<String, String> i = new HashMap<String, String>();
i.put("name", name);
i.put("key", phoneNumber);
items.add(i);
} while (cur.moveToNext());
} else {
HashMap<String, String> i = new HashMap<String, String>();
i.put("name", "Your Phone");
i.put("key", "Have No Contacts.");
items.add(i);
}
} finally {
if (cur != null)
cur.close();
}
return items;
}
那么就能在1.6上运行了,效果截图如下:
联系人API,在Android2.0后产生变化,如果使用如上1.6版本的调用,你会发现在2.1下姓名有了,但电话号码不显示了。仔细观察可以发现,People.CONTENT_URI等调用在2.0以上的sdk中都标记了Deprecated。这一点,对于编写希望能够同时兼容1.6与2.x版本的应用造成了困难。那么,如果应用涉及到联系人的读取,非得要编写多个版本的apk了吗? 其实,我们可以使用判断当前系统API Level的方法编写两套代码备用,这个就留给大家去实践了。
获得系统API level方法:
int version = android.provider.Settings.System.getInt(context
.getContentResolver(),
android.provider.Settings.System.SYS_PROP_SETTING_VERSION,
3); |
|