Android進階之讀取手機聯絡人顯示listview並點選撥號(CursorAdapter)
一、CursorAdapter介紹
1、繼承於BaseAdapter是個虛類,它為cursor和ListView提供了連線的橋樑。
如:public abstract class CursorAdapter extends BaseAdapter
2、注意cursor的必須要有個命名為”_id”的列。比如Contacts._ID就為”_id”
3、必須實現以下函式:
①newView(Context context, Cursor cursor, ViewGroup parent)
newView:並不是每次都被呼叫的,它只在例項化的時候呼叫,資料增加的時候也會呼叫,但是在重繪(比如修改條目裡的TextView的內容)的時候不會被呼叫
②bindView(View view, Context context, Cursor cursor)
bindView:從程式碼中可以看出在繪製Item之前一定會呼叫bindView方法它在重繪的時候也同樣被呼叫
4、更新ListView方法:adapter.changeCursor(cursor),它的功能類似於adapter.notifyDataSetChanged()方法
二、讀取通訊錄詳解
1、許可權
<!-- 讀取聯絡人許可權 -->
<uses-permission android:name="android.permission.READ_CONTACTS" ></uses-permission>
<!-- 撥打電話許可權 -->
<uses-permission android:name="android.permission.CALL_PHONE"></uses-permission>
2、獲取Cursor方法
Cursor phoneCursor = resolver.query(Phone.CONTENT_URI,
PHONES_PROJECTION, null, null, null);
3、為什麼不使用Adapter繼承於BaseAdapter?
因為Object物件不能轉型為Cursor, 所以使用的Adapter繼承於CursorAdapter,才能轉型為CursorWrapper。
/**
* 點選監聽實現
*
* 實現:獲得選中項的電話號碼並撥號
*/
private class onItemClickListener implements OnItemClickListener {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//從指標的封裝類中獲得選中項的電話號碼並撥號
//返回值是Object類需要向下轉型成CursorWrapper型別
CursorWrapper wrapper = (CursorWrapper) lvContact.getItemAtPosition(position - 1);
//返回從0開始的索引,如果列名不存在將返回-1
int columnIndex = wrapper.getColumnIndex(Phone.NUMBER);
if (!wrapper.isNull(columnIndex)) {
String number = wrapper.getString(columnIndex);
// 判斷電話號碼的有效性
if (PhoneNumberUtils.isGlobalPhoneNumber(number)) {
Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel://" + number));
startActivity(intent);
}
}
}
}
三、例子程式碼
1、AndroidManifest.xml
<!-- 讀取聯絡人許可權 -->
<uses-permission android:name="android.permission.READ_CONTACTS" />
<!-- 撥打電話許可權 -->
<uses-permission android:name="android.permission.CALL_PHONE" />
2、item_contact.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:orientation="horizontal" >
<ImageView
android:id="@+id/iv_head"
android:layout_width="45dp"
android:layout_height="45dp"
android:src="@mipmap/ic_launcher" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center_vertical"
android:layout_marginLeft="8dp"
android:orientation="horizontal" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"
android:text="TextView" />
<TextView
android:id="@+id/number"
android:textSize="12sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
</LinearLayout>
3、activity_contact.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ListView
android:id="@+id/lv_contact"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
</ListView>
</RelativeLayout>
4、ContactAdapter.java
package com.guan.contentproviderwork.contact;
import android.content.ContentUris;
import android.content.Context;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.provider.ContactsContract;
import android.support.v4.widget.CursorAdapter;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.guan.contentproviderwork.R;
import java.io.InputStream;
import java.util.ArrayList;
import butterknife.Bind;
import butterknife.ButterKnife;
/**
* 定義介面卡
* CursorAdapter為cursor和ListView提供了連線的橋樑
*
* @author Guan
* @file com.guan.contentproviderwork
* @date 2015/9/8
* @Version 1.0
*/
public class ContactAdapter extends CursorAdapter {
private Context mContext;
/**
* 聯絡人顯示名稱
*/
private static final int PHONES_DISPLAY_NAME_INDEX = 1;
/**
* 電話號碼
**/
private static final int PHONES_NUMBER_INDEX = 2;
/**
* 頭像ID
*/
private static final int PHONES_PHOTO_ID_INDEX = 3;
/**
* 聯絡人的ID
*/
private static final int PHONES_CONTACT_ID_INDEX = 4;
public ContactAdapter(Context context, Cursor cursor) {
super(context,cursor);
this.mContext = context;
}
@Override
public int getCount() {
if (mDataValid && mCursor != null) {
return mCursor.getCount();
} else {
return 0;
}
}
@Override
public Object getItem(int position) {
if (mDataValid && mCursor != null) {
mCursor.moveToPosition(position);
return mCursor;
} else {
return null;
}
}
@Override
public long getItemId(int position) {
if (mDataValid && mCursor != null) {
if ( mCursor.moveToPosition(position)) {
return mCursor.getLong( mRowIDColumn);
} else {
return 0;
}
} else {
return 0;
}
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view;
if (convertView == null) {
view = newView(mContext, mCursor, parent);
} else {
view = convertView;
}
bindView(view, mContext, mCursor);
return view;
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
ViewHolder viewholder = null;
View view = LayoutInflater.from(mContext).inflate(
R.layout.item_contact, null);
viewholder = new ViewHolder(view);
view.setTag(viewholder);
return view;
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
/**
* 獲取當前position
* final int position=cursor.getPosition();
*/
ViewHolder viewholder = (ViewHolder) view.getTag();
/**
* 得到聯絡人名稱
*/
viewholder.name.setText(cursor.getString(PHONES_DISPLAY_NAME_INDEX) + "");
/**
* 得到手機號碼
*/
viewholder.number.setText(cursor.getString(PHONES_NUMBER_INDEX) + "");
/**
* 得到聯絡人頭像
*/
// 得到聯絡人ID
Long contactid = cursor
.getLong(PHONES_CONTACT_ID_INDEX);
// 得到聯絡人頭像ID
Long photoid = cursor.getLong(PHONES_PHOTO_ID_INDEX);
// 得到聯絡人頭像Bitamp
Bitmap contactPhoto = null;
// photoid 大於0 表示聯絡人有頭像 如果沒有給此人設定頭像則給他一個預設的
if (photoid > 0) {
Uri uri = ContentUris.withAppendedId(
ContactsContract.Contacts.CONTENT_URI,
contactid);
InputStream input = ContactsContract.Contacts
.openContactPhotoInputStream(mContext.getContentResolver(), uri);
contactPhoto = BitmapFactory.decodeStream(input);
} else {
contactPhoto = BitmapFactory.decodeResource(
mContext.getResources(), R.mipmap.ic_launcher);
}
viewholder.ivHead.setImageBitmap(contactPhoto);
}
/**
* ViewHolder
*/
static class ViewHolder {
@Bind(R.id.iv_head)
ImageView ivHead;
@Bind(R.id.name)
TextView name;
@Bind(R.id.number)
TextView number;
ViewHolder(View view) {
ButterKnife.bind(this, view);
}
}
}
5、ContactActivity.java
package com.guan.contentproviderwork.contact;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.Intent;
import android.database.Cursor;
import android.database.CursorWrapper;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.telephony.PhoneNumberUtils;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import com.guan.contentproviderwork.R;
import butterknife.Bind;
import butterknife.ButterKnife;
public class ContactActivity extends Activity {
@Bind(R.id.lv_contact)
ListView lvContact;
/**
* 聯絡人組
*/
private static String[] PHONES_PROJECTION;
/**
* 聯絡人adapter
*/
private ContactAdapter mContactAdapter;
/**
* Curosr
*/
private Cursor mPhoneCursor;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_contact);
ButterKnife.bind(this);
// 初始化變數
initValiable();
// 獲取聯絡人Cursor
getCursor();
// 初始化listview
bindData();
// 初始化監聽
initListener();
}
/**
* 初始化變數
*/
private void initValiable() {
PHONES_PROJECTION = new String[]{
"_id", Phone.DISPLAY_NAME, Phone.NUMBER, Phone.PHOTO_ID, Phone.CONTACT_ID};
}
/**
* 獲取所有聯絡人Cursor
*/
private Cursor getCursor() {
ContentResolver resolver = getContentResolver();
mPhoneCursor = resolver.query(Phone.CONTENT_URI,
PHONES_PROJECTION, null, null, null);
return mPhoneCursor;
}
/**
* 繫結資料
*/
private void bindData() {
mContactAdapter = new ContactAdapter(ContactActivity.this, mPhoneCursor);
lvContact.setAdapter(mContactAdapter);
}
/**
* 初始化監聽
*/
private void initListener() {
lvContact.setOnItemClickListener(new onItemClickListener());
}
/**
* 點選監聽實現
* <p/>
*
* 實現:獲得選中項的電話號碼並撥號
*
* 注意:不能使用僅是繼承於BaseAdapter,因為Object物件不能轉型為Cursor。
* 所以:使用的Adapter是繼承於CursorAdapter,才能轉型為CursorWrapper。
*/
private class onItemClickListener implements OnItemClickListener {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//從指標的封裝類中獲得選中項的電話號碼並撥號
//返回值是Object類需要向下轉型成CursorWrapper型別
CursorWrapper wrapper = (CursorWrapper) lvContact.getItemAtPosition(position - 1);
//返回從0開始的索引,如果列名不存在將返回-1
int columnIndex = wrapper.getColumnIndex(Phone.NUMBER);
if (!wrapper.isNull(columnIndex)) {
String number = wrapper.getString(columnIndex);
// 判斷電話號碼的有效性
if (PhoneNumberUtils.isGlobalPhoneNumber(number)) {
Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel://" + number));
startActivity(intent);
}
}
}
}
@Override
protected void onDestroy() {
super.onDestroy();
mPhoneCursor.close();
}
/**
// * 獲取所有聯絡人
// */
// private void getPhoneContacts() {
//
// ContentResolver resolver = getContentResolver();
// try {
// // 獲取手機聯絡人
// mPhoneCursor = resolver.query(Phone.CONTENT_URI,
// PHONES_PROJECTION, null, null, null);
// if (mPhoneCursor != null) {
//
// while (mPhoneCursor.moveToNext()) {
//
// // 得到手機號碼
// String phoneNumber = mPhoneCursor
// .getString(PHONES_NUMBER_INDEX);
// // 當手機號碼為空的或者為空欄位 跳過當前迴圈
// if (TextUtils.isEmpty(phoneNumber))
// continue;
//
// // 得到聯絡人名稱
// String contactName = mPhoneCursor
// .getString(PHONES_DISPLAY_NAME_INDEX);
//
// // 得到聯絡人ID
// Long contactid = mPhoneCursor
// .getLong(PHONES_CONTACT_ID_INDEX);
//
// // 得到聯絡人頭像ID
// Long photoid = mPhoneCursor.getLong(PHONES_PHOTO_ID_INDEX);
//
// // 得到聯絡人頭像Bitamp
// Bitmap contactPhoto = null;
//
// // photoid 大於0 表示聯絡人有頭像 如果沒有給此人設定頭像則給他一個預設的
// if (photoid > 0) {
// Uri uri = ContentUris.withAppendedId(
// ContactsContract.Contacts.CONTENT_URI,
// contactid);
// InputStream input = ContactsContract.Contacts
// .openContactPhotoInputStream(resolver, uri);
// contactPhoto = BitmapFactory.decodeStream(input);
// } else {
// contactPhoto = BitmapFactory.decodeResource(
// getResources(), R.mipmap.ic_launcher);
// }
// ContactEntity mContact = new ContactEntity(contactName,
// phoneNumber, contactPhoto);
// mContacts.add(mContact);
// }
//// mPhoneCursor.close();
// }
// } catch (Exception e) {
// e.printStackTrace();
// }
// }
}
四、效果圖
五、推薦連結