Android通讯录管理(获取联系人、通话记录、短信消息)

2014年2月26日 通讯录开发研究学习
前言:前阵子主要是记录了如何对联系人的一些操作,比如搜索,全选、反选和删除等在实际开发中可能需要实现的功能,本篇博客是小巫从一个别人开源的一个项目抽取出来的部分内容,把它给简化出来,可以让需要的朋友清楚知道如何对Android数据库操作,异步查询数据库获取我们需要的内容。由于内容比较多,我将分三篇博客来讲述获取联系人、通话记录、短信消息的实现。
也许你根本就没耐心看,源码在这里http://download.csdn.net/detail/wwj_748/6962865,骚年去下吧。
上面的是获取联系人的界面效果,实现分组显示联系人,快速索引条查找联系人,下面是实现:
从权限开始:
    <!-- 读联系人权限 -->    <uses-permission android:name="android.permission.READ_CONTACTS" />    <!-- 写联系人权限 -->    <uses-permission android:name="android.permission.WRITE_CONTACTS" />    <!-- 拨号权限 -->    <uses-permission android:name="android.permission.CALL_PHONE" />    <!-- 读短信权限 -->    <uses-permission android:name="android.permission.READ_SMS" />

界面布局:
/Contact_Demo/res/layout/contact_list_view.xml
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:id="@+id/contact_list_view"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:background="#000000" >    <com.suntek.contact.view.SlidingLinearLayout        android:id="@+id/slidingview"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:layout_alignParentTop="true" >        <ListView            android:id="@+id/contact_list"            android:layout_width="match_parent"            android:layout_height="match_parent"            android:cacheColorHint="#000000"            android:divider="#00000000"            android:fadingEdge="none"            android:scrollbars="none"            android:scrollingCache="false"            android:visibility="visible" />    </com.suntek.contact.view.SlidingLinearLayout>    <com.suntek.contact.view.QuickAlphabeticBar        android:id="@+id/fast_scroller"        android:layout_width="22dp"        android:layout_height="match_parent"        android:layout_alignParentRight="true"        android:layout_gravity="top|right|center"        android:layout_marginTop="0dip"        android:background="@null"        android:scaleType="centerInside"        android:src="@drawable/dic_background" >    </com.suntek.contact.view.QuickAlphabeticBar>    <TextView        android:id="@+id/fast_position"        android:layout_width="70dip"        android:layout_height="70dip"        android:layout_centerInParent="true"        android:layout_gravity="center_horizontal|top"        android:layout_margin="34dip"        android:background="@drawable/sort_icon_bg_click"        android:gravity="center"        android:padding="2dip"        android:textColor="#404040"        android:textSize="48dip"        android:visibility="invisible" /></RelativeLayout>

/Contact_Demo/res/layout/contact_list_item.xml

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="wrap_content" >    <!-- 首字母 -->    <TextView        android:id="@+id/alpha"        android:layout_width="fill_parent"        android:layout_height="wrap_content"        android:background="#333333"        android:paddingLeft="10dip"        android:textColor="#FFFFFF"        android:visibility="gone" />    <!-- 联系人信息 -->    <QuickContactBadge        android:id="@+id/qcb"        android:layout_width="75dip"        android:layout_height="75dip"        android:layout_alignParentLeft="true"        android:layout_below="@+id/alpha"        android:layout_marginBottom="3dip"        android:layout_marginTop="3dip"        android:src="@drawable/touxiang" />    <TextView        android:id="@+id/name"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_centerVertical="true"        android:layout_marginLeft="5.0dip"        android:layout_toRightOf="@+id/qcb"        android:singleLine="true"        android:textAppearance="?android:textAppearanceLarge"        android:textColor="#FFFFFF" />    <TextView        android:id="@+id/number"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignParentBottom="true"        android:layout_marginLeft="5.0dip"        android:layout_toRightOf="@+id/qcb"        android:singleLine="true"        android:textAppearance="?android:textAppearanceSmall"        android:textColor="#FFFFFF" /></RelativeLayout>

代码实现:
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<ContactBean> list; private HashMap<String, Integer> alphaIndexer; // 字母索引 private String[] sections; // 存储每个章节 private Context ctx; // 上下文 public ContactListAdapter(Context context, List<ContactBean> list,   QuickAlphabeticBar alpha) {  this.ctx = context;  this.inflater = LayoutInflater.from(context);  this.list = list;  this.alphaIndexer = new HashMap<String, Integer>();  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<String> sectionLetters = alphaIndexer.keySet();  ArrayList<String> sectionList = new ArrayList<String>(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<ContactBean> list; private AsyncQueryHandler asyncQueryHandler; // 异步查询数据库类对象 private QuickAlphabeticBar alphabeticBar; // 快速索引条 private Map<Integer, ContactBean> 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<Integer, ContactBean>();    list = new ArrayList<ContactBean>();    cursor.moveToFirst(); // 游标移动到第一项    for (int i = 0; i < cursor.getCount(); i++) {     cursor.moveToPosition(i);     String name = cursor.getString(1);     String number = cursor.getString(2);     String sortKey = cursor.getString(3);     int contactId = cursor.getInt(4);     Long photoId = cursor.getLong(5);     String lookUpKey = cursor.getString(6);     if (contactIdMap.containsKey(contactId)) {      // 无操作     } else {      // 创建联系人对象      ContactBean contact = new ContactBean();      contact.setDesplayName(name);      contact.setPhoneNum(number);      contact.setSortKey(sortKey);      contact.setPhotoId(photoId);      contact.setLookUpKey(lookUpKey);      list.add(contact);      contactIdMap.put(contactId, contact);     }    }    if (list.size() > 0) {     setAdapter(list);    }   }   super.onQueryComplete(token, cookie, cursor);  } } private void setAdapter(List<ContactBean> 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<String, Integer> 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<String, Integer> 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 < letters.length) { // 防止越界   String key = letters[selectIndex];   if (alphaIndexer.containsKey(key)) {    int pos = alphaIndexer.get(key);    if (mList.getHeaderViewsCount() > 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 < letters.length) {     choose = selectIndex;     invalidate();    }   }   if (mHandler != null) {    mHandler.post(new Runnable() {     @Override     public void run() {      if (mDialogText != null        && mDialogText.getVisibility() == View.INVISIBLE) {       mDialogText.setVisibility(VISIBLE);      }     }    });   }   break;  case MotionEvent.ACTION_MOVE:   if (oldChoose != selectIndex) {    if (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();  } }}

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

Android通讯录管理(获取联系人 通话记录 短信消息)(一)相关推荐

  1. android通讯录管理(获取联系人,通话记录,短信消息),Android通讯录管理(获取联系人、通话记录、短信消息)(二)...

    Android通讯录管理(获取联系人.通话记录.短信消息)(二) 前言:上一篇博客介绍的是获取联系人的实现,本篇博客将介绍通话记录的实现. 界面布局: /Contact_Demo/res/layout ...

  2. Android通讯录管理 获取联系人 通话记录 短信消息 一

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! Andr ...

  3. Android通讯录管理(获取联系人 通话记录 短信消息)(三)

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! Andr ...

  4. Android手机拨打电话、手动发送短信与自动拨打电话、自动发送短信(代码很简单哦)

    Android实现手动拨打电话,即点击后跳转到手机默认电话号码输入页面,可以将相应号码传送过去: <span style="font-size:18px;"> Inte ...

  5. Android实现拨打电话和发送短信,Android手机拨打电话、手动发送短信与自动拨打电话、自动发送短信(代码很简单哦)...

    Android实现手动拨打电话,即点击后跳转到手机默认电话号码输入页面,可以将相应号码传送过去: Intent intent = new Intent(Intent.ACTION_DIAL, Uri. ...

  6. Android实战技巧之三十九:短信收发

    7月4日从广州出差回来就定下写作计划,但迟迟没有动笔.耽搁的原因还是老样子,工作上又有新任务,全部精力都投入过去了,每天精疲力竭的回来也打不起精神做其他事了.这就是精力管理不当所致,就像我把很多要做的 ...

  7. Android通讯录管理(获取联系人、通话记录、短信消息)(二)

    Android通讯录管理(获取联系人.通话记录.短信消息)(二) 前言:上一篇博客介绍的是获取联系人的实现,本篇博客将介绍通话记录的实现. 同样的,你可以到这里下载源码:http://download ...

  8. Android通讯录管理(获取联系人、通话记录、短信消息)(三)

    Android通讯录管理(获取联系人.通话记录.短信消息)(三) 这是通讯录管理的最后一篇,前面两篇已经把获取联系人和通话记录解决了,短息消息就相对来说要稍微复杂那么一点.我们先来看看效果图: 源码下 ...

  9. Android通讯录管理(获取联系人、通话记录、短信消息)

    前言:前阵子主要是记录了如何对联系人的一些操作,比如搜索,全选.反选和删除等在实际开发中可能需要实现的功能,本篇博客是小巫从一个别人开源的一个项目抽取出来的部分内容,把它给简化出来,可以让需要的朋友清 ...

最新文章

  1. MyEclipse的Java Web项目配置环境搭建-如何安装tomact
  2. Linux软件管理器(如何使用软件管理器来管理软件)
  3. idea 将普通Java项目打包成可直接执行的jar
  4. MyBatis-学习笔记12【12.Mybatis注解开发】
  5. 【嵌入式Linux】嵌入式Linux应用开发基础知识之输入系统应用编程
  6. 聊天机器人mysql数据_自己动手开发智能聊天机器人完全指南(附完整源码)
  7. 杰出企业家的20个好习惯
  8. Flutter 判断横竖屏(含尺寸、方向改变时触发)
  9. 几种蓝屏分析及解决汇总
  10. 聊斋志异读后感 [20180818]
  11. 算法设计与分析中用到的渐近记号:Θ、O、Ω、o和ω
  12. python输出欢迎某某某_python中怎么写注释
  13. 如何快速拆分PDF文件(照片快速转换成pdf)
  14. 在 iPhone 上体验安卓系统,无需越狱,免费
  15. java ico图标_javaweb中如何给自己的网站更改ico图标
  16. C语言中:的其中一种作用
  17. verilog乘法器以及booth编码改进
  18. 参加论文写作课后心得体会
  19. 【前端安全】密码安全
  20. Python控制安卓模拟器

热门文章

  1. 华为手机按下这个键,瞬间投屏到电视大屏幕,效果惊艳堪比电影院
  2. 一文读懂mysql主从复制机制
  3. 2345 看图王广告弹窗 删除
  4. 李行健教授畅谈成语规范
  5. php 伪静态 rewriterule,PHP实现伪静态 RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L] 是什么意思?...
  6. 埃隆·马斯克推荐的《你相信这台电脑吗?》上映,不火爆但AI威胁的论战又起(附视频地址)...
  7. Zynq7000简介
  8. WPF Border设置虚线边框
  9. Mpp 的一种 java 读写解决方案
  10. 程序员职业规划:30岁后如何实现质的突破!