android--加载本地联系人
首先先建布局文件,界面很简单,就是一个搜索框和下面的联系人列表:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#FFD3D7DF" android:orientation="vertical" android:padding="0dip" > <RelativeLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginLeft="3dip" android:layout_marginRight="3dip" android:layout_marginTop="3dip" > <EditText android:id="@+id/search_view" android:layout_width="fill_parent" android:layout_height="wrap_content" android:hint="@string/hint_search_contacts" android:paddingLeft="32dip" android:singleLine="true" android:textSize="16sp" /> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@id/search_view" android:layout_centerVertical="true" android:layout_marginLeft="3dip" android:src="@drawable/contacts" /> </RelativeLayout> <ListView android:id="@+id/contact_list" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginBottom="0dip" android:layout_marginLeft="0dip" android:layout_marginRight="0dip" android:layout_marginTop="0dip" android:layout_weight="1.0" android:cacheColorHint="#00000000" android:divider="#00000000" android:dividerHeight="0.1px" android:fadingEdge="none" android:footerDividersEnabled="false" android:listSelector="@null" android:paddingBottom="0dip" android:paddingLeft="0dip" android:paddingRight="0dip" android:paddingTop="0dip" /></LinearLayout>
<?xml version="1.0" encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:orientation="horizontal"android:layout_height="wrap_content"android:layout_width="fill_parent"android:paddingTop="2dip"android:paddingBottom="2dip"android:background="@color/list_item_background"><ImageViewandroid:id="@+id/photo"android:layout_height="wrap_content" android:layout_width="wrap_content"android:layout_marginLeft="5dip"android:layout_gravity="center_vertical"android:layout_weight="1"android:src="@drawable/default_avatar"/><LinearLayoutandroid:orientation="vertical"android:layout_height="wrap_content"android:layout_width="wrap_content"android:layout_gravity="center_vertical"android:layout_marginLeft="5dip"android:layout_weight="100"><TextView android:id="@+id/text1" android:typeface="serif"android:singleLine="true"style="@style/list_font_main_text" /><LinearLayoutandroid:orientation="horizontal"android:layout_height="wrap_content"android:layout_width="wrap_content"android:layout_marginTop="3dip"><TextView android:id="@+id/text2" android:typeface="serif"android:singleLine="true"style="@style/list_font_detail_text" /><TextView android:id="@+id/text3" android:ellipsize="marquee"android:layout_marginLeft="3dip"android:marqueeRepeatLimit="marquee_forever"android:scrollHorizontally="true"style="@style/list_font_detail_text" /></LinearLayout></LinearLayout></LinearLayout>
然后是点击事件:(点击后要把选择的联系人号码返回到输入框里)

// 获取联系人按钮对象并绑定onClick单击事件phoneButton = (Button) findViewById(R.id.find_phone);phoneButton.setOnClickListener(new OnClickListener() {public void onClick(View v) {// 从联系人选择号码,再通过onActivityResult()方法处理回调结果Intent intent = new Intent(context, ContactsActivity.class);startActivityForResult(intent, REQUEST_CODE);}});/** * 选择联系人的回调处理函数 */@Overridepublic void onActivityResult(int reqCode, int resultCode, Intent data) {super.onActivityResult(reqCode, resultCode, data);if (resultCode == RESULT_OK) {switch (reqCode) {case REQUEST_CODE:String phone = data.getStringExtra("phone");phoneEditText.setText(phone);break;}}}

下面就是联系人界面的activity了:
/** * 显示用户手机上的联系人 * * @author Mr.Z * @time 2012-3-21 * */public class ContactsActivity extends Activity {private Context ctx = ContactsActivity.this;private TextView topTitleTextView;private ListView listView = null;List<HashMap<String, String>> contactsList = null;private EditText contactsSearchView;private ProgressDialog progressDialog = null;// 数据加载完成的消息private final int MESSAGE_SUCC_LOAD = 0;// 数据查询完成的消息private final int MESSAGE_SUCC_QUERY = 1;private Handler handler = new Handler() {@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);switch (msg.what) {case MESSAGE_SUCC_LOAD:listView.setAdapter(new ContactsAdapter(ctx));progressDialog.dismiss();break;case MESSAGE_SUCC_QUERY:listView.setAdapter(new ContactsAdapter(ctx));break;}}};protected void onCreate(Bundle savedInstanceState) {requestWindowFeature(Window.FEATURE_NO_TITLE);getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);super.onCreate(savedInstanceState);this.setContentView(R.layout.contacts);// 使用listView显示联系人listView = (ListView) findViewById(R.id.contact_list);loadAndSaveContacts();// 绑定listView item的单击事件listView.setOnItemClickListener(new OnItemClickListener() {@SuppressWarnings("unchecked")public void onItemClick(AdapterView<?> adapterView, View view, int position, long _id) {HashMap<String, String> map = (HashMap<String, String>) adapterView.getItemAtPosition(position);String phone = map.get("phone");// 对手机号码进行预处理(去掉号码前的+86、首尾空格、“-”号等)phone = phone.replaceAll("^(\\+86)", "");phone = phone.replaceAll("^(86)", "");phone = phone.replaceAll("-", "");phone = phone.trim();// 如果当前号码并不是手机号码if (!SaleUtil.isValidPhoneNumber(phone))SaleUtil.createDialog(ctx, R.string.dialog_title_tip, getString(R.string.alert_contacts_error_phone));else {Intent intent = new Intent();intent.putExtra("phone", phone);setResult(RESULT_OK, intent);// 关闭当前窗口finish();}}});contactsSearchView = (EditText) findViewById(R.id.search_view);contactsSearchView.addTextChangedListener(new TextWatcher() {public void afterTextChanged(Editable s) {}public void beforeTextChanged(CharSequence s, int start, int count, int after) {}public void onTextChanged(CharSequence s, int start, int before, int count) {queryContacts(s.toString());}});}/** * 加载并存储联系人数据 */private void loadAndSaveContacts() {progressDialog = ProgressDialog.show(ctx, null, "正在加载联系人数据...");new Thread() {@Overridepublic void run() {// 获取联系人数据contactsList = findContacts();// 临时存储联系人数据DBHelper.saveContacts(ctx, contactsList);// 发送消息通知更新UIhandler.sendEmptyMessage(MESSAGE_SUCC_LOAD);}}.start();}/** * 根据条件从本地临时库中获取联系人 * * @param keyWord 查询关键字 */private void queryContacts(final String keyWord) {new Thread() {@Overridepublic void run() {// 获取联系人数据contactsList = DBHelper.findContactsByCond(ctx, keyWord);// 发送消息通知更新UIhandler.sendEmptyMessage(MESSAGE_SUCC_QUERY);}}.start();}/** * 获取手机联系人信息 * * @return List<HashMap<String, String>> */public List<HashMap<String, String>> findContacts() {List<HashMap<String, String>> list = new ArrayList<HashMap<String, String>>();// 查询联系人Cursor contactsCursor = ctx.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI, null, null, null, PhoneLookup.DISPLAY_NAME + " COLLATE LOCALIZED ASC");// 姓名的索引int nameIndex = 0;// 联系人姓名String name = null;// 联系人头像IDString photoId = null;// 联系人的ID索引值String contactsId = null;// 查询联系人的电话号码Cursor phoneCursor = null;while (contactsCursor.moveToNext()) {nameIndex = contactsCursor.getColumnIndex(PhoneLookup.DISPLAY_NAME);name = contactsCursor.getString(nameIndex);photoId = contactsCursor.getString(contactsCursor.getColumnIndex(PhoneLookup.PHOTO_ID));contactsId = contactsCursor.getString(contactsCursor.getColumnIndex(ContactsContract.Contacts._ID));phoneCursor = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = " + contactsId, null, null);// 遍历联系人号码(一个人对应于多个电话号码)while (phoneCursor.moveToNext()) {HashMap<String, String> phoneMap = new HashMap<String, String>();// 添加联系人姓名phoneMap.put("name", name);// 添加联系人头像phoneMap.put("photo", photoId);// 添加电话号码phoneMap.put("phone", phoneCursor.getString(phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)));// 添加号码类型(住宅电话、手机号码、单位电话等)phoneMap.put("type", getString(ContactsContract.CommonDataKinds.Phone.getTypeLabelResource(phoneCursor.getInt(phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE)))));list.add(phoneMap);}phoneCursor.close();}contactsCursor.close();return list;}/** * 获取联系人头像 * * @param context 上下文环境 * @param photoId 头像ID * @return Bitmap */public static Bitmap getPhoto(Context context, String photoId) {Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.default_avatar);if (photoId != null && "".equals(photoId)) {String[] projection = new String[] { ContactsContract.Data.DATA15 };String selection = "ContactsContract.Data._ID = " + photoId;Cursor cur = context.getContentResolver().query(ContactsContract.Data.CONTENT_URI, projection, selection, null, null);if (cur != null) {cur.moveToFirst();byte[] contactIcon = null;contactIcon = cur.getBlob(cur.getColumnIndex(ContactsContract.Data.DATA15));if (contactIcon != null) {bitmap = BitmapFactory.decodeByteArray(contactIcon, 0, contactIcon.length);}}}return bitmap;}/** * 自定义联系人Adapter */class ContactsAdapter extends BaseAdapter {private LayoutInflater inflater = null;public ContactsAdapter(Context ctx) {inflater = LayoutInflater.from(ctx);}public int getCount() {return contactsList.size();}public Object getItem(int position) {return contactsList.get(position);}public long getItemId(int position) {return position;}public View getView(int position, View convertView, ViewGroup parent) {ViewHolder holder = null;if (convertView == null) {holder = new ViewHolder();convertView = inflater.inflate(R.layout.contacts_listview_item, null);holder.text1 = (TextView) convertView.findViewById(R.id.text1);holder.text2 = (TextView) convertView.findViewById(R.id.text2);holder.text3 = (TextView) convertView.findViewById(R.id.text3);convertView.setTag(holder);} else {holder = (ViewHolder) convertView.getTag();}holder.text1.setText(contactsList.get(position).get("name"));holder.text2.setText(contactsList.get(position).get("type"));holder.text3.setText(contactsList.get(position).get("phone"));return convertView;}public final class ViewHolder {private TextView text1;private TextView text2;private TextView text3;}}}
查询方法语句:
/** * 根据条件查询联系人数据 * * @param context 上下文环境 * @param keyWord 查询关键字 * @return List<HashMap<String, String>> */public static List<HashMap<String, String>> findContactsByCond(Context context, String keyWord) {List<HashMap<String, String>> list = new ArrayList<HashMap<String, String>>();SQLiteDatabase db = DBHelper.getSQLiteDb(context);String sql = "select * from contacts where name like '" + keyWord + "%' or name_alias like '" + keyWord + "%' order by _id";// 查询数据Cursor cursor = db.rawQuery(sql, null);while (cursor.moveToNext()) {HashMap<String, String> map = new HashMap<String, String>();map.put("name", cursor.getString(cursor.getColumnIndex("name")));map.put("phone", cursor.getString(cursor.getColumnIndex("phone")));map.put("type", cursor.getString(cursor.getColumnIndex("type")));map.put("photo", cursor.getString(cursor.getColumnIndex("photo")));list.add(map);}cursor.close();db.close();return list;}/** * 存储联系人信息 * * @param context 上下文环境 * @param contactsList 联系人列表 */public static void saveContacts(Context context, List<HashMap<String, String>> contactsList) {SQLiteDatabase db = DBHelper.getSQLiteDb(context);// 开启事务控制db.beginTransaction();try {// 先将联系人数据清空db.execSQL("drop table if exists contacts");db.execSQL("create table contacts(_id integer not null primary key autoincrement, name varchar(50), name_alias varchar(10), phone varchar(30), type varchar(50), photo varchar(50))");String sql = null;for (HashMap<String, String> contactsMap : contactsList) {sql = String.format("insert into contacts(name,name_alias,phone,type,photo) values('%s','%s','%s','%s','%s')", contactsMap.get("name"), SaleUtil.getPinYinFirstAlphabet(contactsMap.get("name")), contactsMap.get("phone"), contactsMap.get("type"), contactsMap.get("photo"));db.execSQL(sql);}// 设置事务标志为成功db.setTransactionSuccessful();} finally {// 结束事务db.endTransaction();db.close();}}
工具类:
/** * 判断客户手机号码是否符合规则 * * @param userPhone 客户手机号码 * @return true | false */public static boolean isValidPhoneNumber(String userPhone) {if (null == userPhone || "".equals(userPhone))return false;Pattern p = Pattern.compile("^0?1[0-9]{10}");Matcher m = p.matcher(userPhone);return m.matches();}/** * 获取中文的拼音首字母 * * @param chinese 中文 * @return 拼音首字母 */public static String getPinYinFirstAlphabet(String chinese) {String convert = "";for (int j = 0; j < chinese.length(); j++) {char word = chinese.charAt(j);String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(word);if (pinyinArray != null) {convert += pinyinArray[0].charAt(0);} else {convert += word;}}return convert;}
最后加上权限就行了;
<!-- 访问联系人的权限 --> <uses-permission android:name="android.permission.READ_CONTACTS" />