Android通訊錄管理(獲取聯系人、通話記錄、短信消息)(一)

Android通訊錄管理(獲取聯系人、通話記錄、短信消息)


2014年2月26日 通訊錄開發研究學習

前言:前陣子主要是記錄瞭如何對聯系人的一些操作,比如搜索,全選、反選和刪除等在實際開發中可能需要實現的功能,本篇博客是小巫從一個別人開源的一個項目抽取出來的部分內容,把它給簡化出來,可以讓需要的朋友清楚知道如何對Android數據庫操作,異步查詢數據庫獲取我們需要的內容。由於內容比較多,我將分三篇博客來講述獲取聯系人、通話記錄、短信消息的實現。

也許你根本就沒耐心看,源碼在這裡https://download.csdn.net/detail/wwj_748/6962865,騷年去下吧。

上面的是獲取聯系人的界面效果,實現分組顯示聯系人,快速索引條查找聯系人,下面是實現:

從權限開始:vc3Ryb25nPgo8cHJlIGNsYXNzPQ==”brush:java;”>

界面佈局:
/Contact_Demo/res/layout/contact_list_view.xml



    

        
    

    
    

    

/Contact_Demo/res/layout/contact_list_item.xml



    

    

    

    

    

    

代碼實現:

1. 先定義一個實體類,用來保存聯系人信息
/Contact_Demo/src/com/suntek/contact/model/ContactBean.java

package com.suntek.contact.model;

public class ContactBean {

	private int contactId; //id
	private String desplayName;//姓名
	private String phoneNum; // 電話號碼
	private String sortKey; // 排序用的
	private Long photoId; // 圖片id
	private String lookUpKey; 
	private int selected = 0;
	private String formattedNumber;
	private String pinyin; // 姓名拼音

	public int getContactId() {
		return contactId;
	}

	public void setContactId(int contactId) {
		this.contactId = contactId;
	}

	public String getDesplayName() {
		return desplayName;
	}

	public void setDesplayName(String desplayName) {
		this.desplayName = desplayName;
	}

	public String getPhoneNum() {
		return phoneNum;
	}

	public void setPhoneNum(String phoneNum) {
		this.phoneNum = phoneNum;
	}

	public String getSortKey() {
		return sortKey;
	}

	public void setSortKey(String sortKey) {
		this.sortKey = sortKey;
	}

	public Long getPhotoId() {
		return photoId;
	}

	public void setPhotoId(Long photoId) {
		this.photoId = photoId;
	}

	public String getLookUpKey() {
		return lookUpKey;
	}

	public void setLookUpKey(String lookUpKey) {
		this.lookUpKey = lookUpKey;
	}

	public int getSelected() {
		return selected;
	}

	public void setSelected(int selected) {
		this.selected = selected;
	}

	public String getFormattedNumber() {
		return formattedNumber;
	}

	public void setFormattedNumber(String formattedNumber) {
		this.formattedNumber = formattedNumber;
	}

	public String getPinyin() {
		return pinyin;
	}

	public void setPinyin(String pinyin) {
		this.pinyin = pinyin;
	}

}

適配器:
/Contact_Demo/src/com/suntek/contact/adapter/ContactListAdapter.java

package com.suntek.contact.adapter;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;

import android.content.ContentUris;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.provider.ContactsContract;
import android.provider.ContactsContract.Contacts;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.QuickContactBadge;
import android.widget.TextView;

import com.suntek.contact.R;
import com.suntek.contact.model.ContactBean;
import com.suntek.contact.view.QuickAlphabeticBar;

public class ContactListAdapter extends BaseAdapter {
	private LayoutInflater inflater;
	private List list;
	private HashMap alphaIndexer; // 字母索引
	private String[] sections; // 存儲每個章節
	private Context ctx; // 上下文

	public ContactListAdapter(Context context, List list,
			QuickAlphabeticBar alpha) {
		this.ctx = context;
		this.inflater = LayoutInflater.from(context);
		this.list = list;
		this.alphaIndexer = new HashMap();
		this.sections = new String[list.size()];

		for (int i = 0; i < list.size(); i++) {
			// 得到字母
			String name = getAlpha(list.get(i).getSortKey());
			if (!alphaIndexer.containsKey(name)) {
				alphaIndexer.put(name, i);
			}
		}

		Set sectionLetters = alphaIndexer.keySet();
		ArrayList sectionList = new ArrayList(sectionLetters);
		Collections.sort(sectionList); // 根據首字母進行排序
		sections = new String[sectionList.size()];
		sectionList.toArray(sections);

		alpha.setAlphaIndexer(alphaIndexer);

	}

	@Override
	public int getCount() {
		return list.size();
	}

	@Override
	public Object getItem(int position) {
		return list.get(position);
	}

	@Override
	public long getItemId(int position) {
		return position;
	}

	public void remove(int position) {
		list.remove(position);
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		ViewHolder holder;
		if (convertView == null) {
			convertView = inflater.inflate(R.layout.contact_list_item, null);
			holder = new ViewHolder();
			holder.quickContactBadge = (QuickContactBadge) convertView
					.findViewById(R.id.qcb);
			holder.alpha = (TextView) convertView.findViewById(R.id.alpha);
			holder.name = (TextView) convertView.findViewById(R.id.name);
			holder.number = (TextView) convertView.findViewById(R.id.number);
			convertView.setTag(holder);
		} else {
			holder = (ViewHolder) convertView.getTag();
		}

		ContactBean contact = list.get(position);
		String name = contact.getDesplayName();
		String number = contact.getPhoneNum();
		holder.name.setText(name);
		holder.number.setText(number);
		holder.quickContactBadge.assignContactUri(Contacts.getLookupUri(
				contact.getContactId(), contact.getLookUpKey()));
		if (0 == contact.getPhotoId()) {
			holder.quickContactBadge.setImageResource(R.drawable.touxiang);
		} else {
			Uri uri = ContentUris.withAppendedId(
					ContactsContract.Contacts.CONTENT_URI,
					contact.getContactId());
			InputStream input = ContactsContract.Contacts
					.openContactPhotoInputStream(ctx.getContentResolver(), uri);
			Bitmap contactPhoto = BitmapFactory.decodeStream(input);
			holder.quickContactBadge.setImageBitmap(contactPhoto);
		}
		// 當前字母
		String currentStr = getAlpha(contact.getSortKey());
		// 前面的字母
		String previewStr = (position - 1) >= 0 ? getAlpha(list.get(
				position - 1).getSortKey()) : " ";

		if (!previewStr.equals(currentStr)) {
			holder.alpha.setVisibility(View.VISIBLE);
			holder.alpha.setText(currentStr);
		} else {
			holder.alpha.setVisibility(View.GONE);
		}
		return convertView;
	}

	private static class ViewHolder {
		QuickContactBadge quickContactBadge;
		TextView alpha;
		TextView name;
		TextView number;
	}

	/**
	 * 獲取首字母
	 * 
	 * @param str
	 * @return
	 */
	private String getAlpha(String str) {
		if (str == null) {
			return "#";
		}
		if (str.trim().length() == 0) {
			return "#";
		}
		char c = str.trim().substring(0, 1).charAt(0);
		// 正則表達式匹配
		Pattern pattern = Pattern.compile("^[A-Za-z]+$");
		if (pattern.matcher(c + "").matches()) {
			return (c + "").toUpperCase(); // 將小寫字母轉換為大寫
		} else {
			return "#";
		}
	}
}

/Contact_Demo/src/com/suntek/contact/ContactListActivity.java

package com.suntek.contact;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.app.Activity;
import android.content.AsyncQueryHandler;
import android.content.ContentResolver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.view.View;
import android.widget.ListView;

import com.suntek.contact.adapter.ContactListAdapter;
import com.suntek.contact.model.ContactBean;
import com.suntek.contact.view.QuickAlphabeticBar;

/**
 * 聯系人列表
 * 
 * @author Administrator
 * 
 */
public class ContactListActivity extends Activity {

	private ContactListAdapter adapter;
	private ListView contactList;
	private List list;
	private AsyncQueryHandler asyncQueryHandler; // 異步查詢數據庫類對象
	private QuickAlphabeticBar alphabeticBar; // 快速索引條

	private Map contactIdMap = null;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.contact_list_view);
		contactList = (ListView) findViewById(R.id.contact_list);
		alphabeticBar = (QuickAlphabeticBar) findViewById(R.id.fast_scroller);

		// 實例化
		asyncQueryHandler = new MyAsyncQueryHandler(getContentResolver());
		init();

	}

	/**
	 * 初始化數據庫查詢參數
	 */
	private void init() {
		Uri uri = ContactsContract.CommonDataKinds.Phone.CONTENT_URI; // 聯系人Uri;
		// 查詢的字段
		String[] projection = { ContactsContract.CommonDataKinds.Phone._ID,
				ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME,
				ContactsContract.CommonDataKinds.Phone.DATA1, "sort_key",
				ContactsContract.CommonDataKinds.Phone.CONTACT_ID,
				ContactsContract.CommonDataKinds.Phone.PHOTO_ID,
				ContactsContract.CommonDataKinds.Phone.LOOKUP_KEY };
		// 按照sort_key升序查詢
		asyncQueryHandler.startQuery(0, null, uri, projection, null, null,
				"sort_key COLLATE LOCALIZED asc");

	}

	/**
	 * 
	 * @author Administrator
	 * 
	 */
	private class MyAsyncQueryHandler extends AsyncQueryHandler {

		public MyAsyncQueryHandler(ContentResolver cr) {
			super(cr);
		}

		@Override
		protected void onQueryComplete(int token, Object cookie, Cursor cursor) {
			if (cursor != null && cursor.getCount() > 0) {
				contactIdMap = new HashMap();
				list = new ArrayList();
				cursor.moveToFirst(); // 遊標移動到第一項
				for (int i = 0; i  0) {
					setAdapter(list);
				}
			}

			super.onQueryComplete(token, cookie, cursor);
		}

	}

	private void setAdapter(List list) {
		adapter = new ContactListAdapter(this, list, alphabeticBar);
		contactList.setAdapter(adapter);
		alphabeticBar.init(ContactListActivity.this);
		alphabeticBar.setListView(contactList);
		alphabeticBar.setHight(alphabeticBar.getHeight());
		alphabeticBar.setVisibility(View.VISIBLE);
	}
}

自定義組件:

package com.suntek.contact.view;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.LinearLayout;

public class SlidingLinearLayout extends LinearLayout {

	public SlidingLinearLayout(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		return super.onInterceptTouchEvent(ev);
	}

}

/Contact_Demo/src/com/suntek/contact/view/QuickAlphabeticBar.java

package com.suntek.contact.view;

import java.util.HashMap;

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.TextView;

import com.suntek.contact.R;

/**
 * 字母索引條
 * 
 * @author Administrator
 * 
 */
public class QuickAlphabeticBar extends ImageButton {
	private TextView mDialogText; // 中間顯示字母的文本框
	private Handler mHandler; // 處理UI的句柄
	private ListView mList; // 列表
	private float mHight; // 高度
	// 字母列表索引
	private String[] letters = new String[] { "#", "A", "B", "C", "D", "E",
			"F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R",
			"S", "T", "U", "V", "W", "X", "Y", "Z" };
	// 字母索引哈希表
	private HashMap alphaIndexer;
	Paint paint = new Paint();
	boolean showBkg = false;
	int choose = -1;

	public QuickAlphabeticBar(Context context) {
		super(context);
	}

	public QuickAlphabeticBar(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
	}

	public QuickAlphabeticBar(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	// 初始化
	public void init(Activity ctx) {
		mDialogText = (TextView) ctx.findViewById(R.id.fast_position);
		mDialogText.setVisibility(View.INVISIBLE);
		mHandler = new Handler();
	}

	// 設置需要索引的列表
	public void setListView(ListView mList) {
		this.mList = mList;
	}

	// 設置字母索引哈希表
	public void setAlphaIndexer(HashMap alphaIndexer) {
		this.alphaIndexer = alphaIndexer;
	}

	// 設置字母索引條的高度
	public void setHight(float mHight) {
		this.mHight = mHight;
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		int act = event.getAction();
		float y = event.getY();
		final int oldChoose = choose;
		// 計算手指位置,找到對應的段,讓mList移動段開頭的位置上
		int selectIndex = (int) (y / (mHight / letters.length));

		if (selectIndex > -1 && selectIndex  0) { // 防止ListView有標題欄,本例中沒有
					this.mList.setSelectionFromTop(
							pos + mList.getHeaderViewsCount(), 0);
				} else {
					this.mList.setSelectionFromTop(pos, 0);
				}
				mDialogText.setText(letters[selectIndex]);
			}
		}
		switch (act) {
		case MotionEvent.ACTION_DOWN:
			showBkg = true;
			if (oldChoose != selectIndex) {
				if (selectIndex > 0 && selectIndex  0 && selectIndex < letters.length) {
					choose = selectIndex;
					invalidate();
				}
			}
			break;
		case MotionEvent.ACTION_UP:
			showBkg = false;
			choose = -1;
			if (mHandler != null) {
				mHandler.post(new Runnable() {

					@Override
					public void run() {
						if (mDialogText != null
								&& mDialogText.getVisibility() == View.VISIBLE) {
							mDialogText.setVisibility(INVISIBLE);
						}
					}
				});
			}
			break;
		default:
			break;
		}
		return super.onTouchEvent(event);
	}

	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		int height = getHeight();
		int width = getWidth();
		int sigleHeight = height / letters.length; // 單個字母占的高度
		for (int i = 0; i < letters.length; i++) {
			paint.setColor(Color.WHITE);
			paint.setTextSize(20);
			paint.setTypeface(Typeface.DEFAULT_BOLD);
			paint.setAntiAlias(true);
			if (i == choose) { 
				paint.setColor(Color.parseColor("#00BFFF")); // 滑動時按下字母顏色
				paint.setFakeBoldText(true);
			}
			// 繪畫的位置
			float xPos = width / 2 - paint.measureText(letters[i]) / 2;
			float yPos = sigleHeight * i + sigleHeight;
			canvas.drawText(letters[i], xPos, yPos, paint);
			paint.reset();
		}
	}

}

發佈留言