转载

android管理联系人操作

ContentProvider扩展之管理系统联系人

我们都知道ContentProvider是用来共享数据的,然而android本身就提供了大量的ContentProvider,例如联系人信息,系统的多媒体信息等,这些系统的ContentProvider都提供了供其他应用程序访问的Uri,开发者可以通过ContentResolver来调用系统的ContentProvider提供的insert()/update()/delete()/query()方法,从而实现自己的需求。

1、了解系统联系人的结构

(1)android系统对联系人管理提供了很多的Uri,其中用到最多的几个如下:

ContactsContract.Contacts.CONTENT_URI:管理联系人的Uri

ContactsContract.CommonDataKinds.Phone.CONTENT_URI:管理联系人电话的Uri

ContactsContract.CommonDataKinds.Email.CONTENT_URI:管理联系人邮箱的Uri

ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_URI:管理联系人地址的Uri

我们可以根据系统提供的这些Uri去操作系统联系人信息,具体的还有很多CONTENT_URI,可以到ContactsContract.class文件中去查看源码。

(2)表结构

我们之前说过,ContentProvider是以表的形式来存放这些数据的,系统联系人也是这样,一般存放在data/data/com.android.providers.contacts/databases/contacts2.db中,我们可以通过adb shell命令行的方式来看,也可以将这个contacts2.db文件导出,通过sqlite工具来查看,这里为了方便我们导出来看一下。

找到对应的文件,然后选中点击右上角的导出按钮,将文件导出到系统中的某一个地方

android管理联系人操作

将导出的文件用工具打开,我这里使用的是: Navicat Premium

表和视图:

android管理联系人操作 android管理联系人操作

我们经常用的到有:contacts、data、raw_contacts三张表:

contacts表:

_id :表的ID,主要用于其它表通过contacts 表中的ID可以查到相应的数据。

display_name: 联系人名称

photo_id:头像的ID,如果没有设置联系人头像,这个字段就为空

times_contacted:通话记录的次数

last_time_contacted: 最后的通话时间 

lookup :是一个持久化的储存 因为用户可能会改名子 但是它改不了lookup

android管理联系人操作

data表:

raw_contact_id:通过raw_contact_id可以找到 raw_contact表中相对的数据。

data1 到 data15 这里保存着联系人的信息 联系人名称 联系人电话号码 电子邮件 备注 等等

android管理联系人操作

raw_contacts表:

version :版本号,用于监听变化

deleted :删除标志, 0为默认 1 表示这行数据已经删除

display_name : 联系人名称

last_time_contacts : 最后联系的时间

android管理联系人操作

【说明:由于这些表的字段都特别多,截图不全,可以自己试着导出一份看看】

2、代码实现

(1)首先要在AndroidManifest.xml文件中配置对系统联系人的读写权限:

<!-- 添加操作联系人的权限 -->     <uses-permission android:name="android.permission.READ_CONTACTS" />     <uses-permission android:name="android.permission.WRITE_CONTACTS" />

(2)布局文件

首先是列表展示页面:

android管理联系人操作
<?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="vertical" >  <TextView   android:layout_width="fill_parent"   android:layout_height="50dp"   android:gravity="center_vertical"   android:text="我的联系人"   android:textSize="25dp" />  <LinearLayout   android:layout_width="fill_parent"   android:layout_height="wrap_content"   android:orientation="horizontal"   android:background="@android:color/darker_gray" >   <TextView    android:id="@+id/id"    android:layout_width="0dp"    android:layout_height="30dp"    android:layout_weight="1"    android:text="ID"    android:gravity="center" />   <TextView    android:id="@+id/name"    android:layout_width="0dp"    android:layout_height="30dp"    android:layout_weight="1"    android:text="姓名"    android:gravity="center" />   <TextView    android:id="@+id/phone"    android:layout_width="0dp"    android:layout_height="30dp"    android:layout_weight="1"    android:text="手机号码"    android:gravity="center" />  </LinearLayout>  <ListView   android:id="@+id/listview"   android:layout_width="fill_parent"   android:layout_height="wrap_content"   android:layout_gravity="center"   android:divider="#FF0000"   android:dividerHeight="1dp"   android:focusable="true"   android:minHeight="40dp"   android:footerDividersEnabled="false" >  </ListView> </LinearLayout> 
View Code

列表展示中需要用的listview页面布局:

android管理联系人操作
<?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" >  <TextView    android:id="@+id/id"   android:layout_width="0dp"   android:layout_weight="1"   android:gravity="center"   android:layout_height="40dp"   />  <TextView    android:id="@+id/name"   android:layout_width="0dp"   android:layout_weight="1"   android:gravity="center"   android:layout_height="40dp"   />  <TextView    android:id="@+id/phone"   android:layout_width="0dp"   android:layout_weight="1"   android:gravity="center"   android:layout_height="40dp"   /> </LinearLayout> 
View Code

添加联系人界面:

android管理联系人操作
<?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="vertical" >  <LinearLayout   android:layout_width="fill_parent"   android:layout_height="50dp"   android:layout_gravity="center"   android:orientation="horizontal" >   <TextView    android:layout_width="100dp"    android:layout_height="wrap_content"    android:layout_marginRight="20dp"    android:gravity="center_vertical|right"    android:text="姓名:"    android:textSize="20dp" />   <EditText    android:id="@+id/name"    android:layout_width="match_parent"    android:layout_height="wrap_content" />  </LinearLayout>  <LinearLayout   android:layout_width="fill_parent"   android:layout_height="50dp"   android:layout_gravity="center"   android:orientation="horizontal" >   <TextView    android:layout_width="100dp"    android:layout_height="wrap_content"    android:gravity="center_vertical|right"    android:layout_marginRight="20dp"    android:text="手机号码:"    android:textSize="20dp" />   <EditText    android:id="@+id/phone"    android:layout_width="match_parent"    android:layout_height="wrap_content" />  </LinearLayout>   <LinearLayout   android:layout_width="fill_parent"   android:layout_height="50dp"   android:layout_gravity="center"   android:gravity="center"   android:orientation="horizontal" >    <Button      android:id="@+id/save"     android:layout_width="wrap_content"     android:layout_height="wrap_content"     android:text="保存"     android:textSize="20sp"     />     <Button      android:id="@+id/cancel"     android:layout_width="wrap_content"     android:layout_height="wrap_content"     android:text="取消"     android:layout_marginLeft="30dp"     android:textSize="20sp"     />    </LinearLayout> </LinearLayout> 
View Code

联系人详细界面:

android管理联系人操作
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  android:layout_width="match_parent"  android:layout_height="wrap_content"  android:layout_marginBottom="10dp"  android:layout_marginLeft="10dp"  android:layout_marginRight="10dp"  android:layout_marginTop="10dp"  android:background="@android:color/darker_gray" >  <TextView   android:id="@+id/tv_name"   android:layout_width="80dp"   android:layout_height="wrap_content"   android:layout_marginTop="20dp"   android:background="@android:color/white"   android:gravity="center_vertical|right"   android:text="姓名:"   android:textSize="20sp" />  <TextView   android:id="@+id/et_name"   android:layout_width="match_parent"   android:layout_height="wrap_content"   android:layout_alignTop="@+id/tv_name"   android:layout_toRightOf="@+id/tv_name"   android:background="@android:color/white"   android:gravity="center_vertical"   android:text=""   android:textSize="20sp" />  <TextView   android:id="@+id/tv_phone"   android:layout_width="80dp"   android:layout_height="wrap_content"   android:layout_below="@+id/tv_name"   android:layout_marginTop="20dp"   android:background="@android:color/white"   android:gravity="center_vertical|right"   android:text="手机号:"   android:textSize="20sp" />  <TextView   android:id="@+id/et_phone"   android:layout_width="match_parent"   android:layout_height="wrap_content"   android:layout_alignTop="@+id/tv_phone"   android:layout_toRightOf="@+id/tv_phone"   android:background="@android:color/white"   android:gravity="center_vertical"   android:text=""   android:textSize="20sp" />  <TextView   android:id="@+id/tv_email"   android:layout_width="80dp"   android:layout_height="wrap_content"   android:layout_below="@+id/tv_phone"   android:layout_marginTop="20dp"   android:background="@android:color/white"   android:gravity="center_vertical|right"   android:text="Email:"   android:textSize="20sp" />  <TextView   android:id="@+id/et_email"   android:layout_width="match_parent"   android:layout_height="wrap_content"   android:layout_alignTop="@+id/tv_email"   android:layout_toRightOf="@+id/tv_email"   android:background="@android:color/white"   android:gravity="center_vertical"   android:text=""   android:textSize="20sp" />  <TextView   android:id="@+id/tv_address"   android:layout_width="80dp"   android:layout_height="wrap_content"   android:layout_below="@+id/tv_email"   android:layout_marginTop="20dp"   android:background="@android:color/white"   android:gravity="center_vertical|right"   android:text="地址:"   android:textSize="20sp" />  <TextView   android:id="@+id/et_address"   android:layout_width="match_parent"   android:layout_height="wrap_content"   android:layout_alignTop="@+id/tv_address"   android:layout_toRightOf="@+id/tv_address"   android:background="@android:color/white"   android:gravity="center_vertical"   android:text=""   android:textSize="20sp" /> </RelativeLayout> 
View Code

程序中需要用的menu菜单配置在menu文件中:

<?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" >  <group android:id="@+id/group1">   <item android:id="@+id/detail" android:title="详情"></item>   <item android:id="@+id/update" android:title="修改"></item>   <item android:id="@+id/delete" android:title="删除"></item>  </group> </menu> 

(3)Activity代码:

列表页面以及适配器Adapter

ContactsActivity.java

android管理联系人操作
package com.demo.contentprovider; import java.util.ArrayList; import android.app.Activity; import android.app.AlertDialog; import android.content.ContentResolver; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.content.Intent; import android.database.Cursor; import android.os.Bundle; import android.provider.ContactsContract; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemLongClickListener; import android.widget.ListView; import android.widget.PopupMenu; import android.widget.PopupMenu.OnMenuItemClickListener; import android.widget.Toast; import com.demo.adapter.ContactsAdapter; import com.demo.model.Contact; /**  * 手机联系人操作  * @author yinbenyang  */ public class ContactsActivity extends Activity {  private static final int ADD = 0;  private static final int REQUEST_ADD = 100;  // 存储联系人的列表  private ArrayList<Contact> contactList = null;  // 联系人适配器  private ContactsAdapter adapter;  private ListView listview;  // 弹出式菜单  public PopupMenu popupmenu = null;  @Override  protected void onCreate(Bundle savedInstanceState) {   super.onCreate(savedInstanceState);   setContentView(R.layout.contentprovider);   listview = (ListView) findViewById(R.id.listview);   init();   listview.setOnItemLongClickListener(new OnItemLongClickListenerImpl());   // registerForContextMenu(listview);  }  // ----------------------------------------------------选项菜单---------------------------------------------------  @Override  public boolean onCreateOptionsMenu(Menu menu) {   // TODO Auto-generated method stub   menu.add(0, ADD, 0, "添加");   return super.onCreateOptionsMenu(menu);  }  @Override  public boolean onOptionsItemSelected(MenuItem item) {   // TODO Auto-generated method stub   switch (item.getItemId()) {   case ADD:    Intent intent = new Intent(this, AddContactActivity.class);    startActivityForResult(intent, REQUEST_ADD);    break;   default:    break;   }   return true;  }  @Override  protected void onActivityResult(int requestCode, int resultCode, Intent data) {   // TODO Auto-generated method stub   switch (requestCode) {   case REQUEST_ADD:    init();    break;   default:    break;   }   super.onActivityResult(requestCode, resultCode, data);  }  // 初始化,获取联系人  private void init() {   ContentResolver resolver = getContentResolver();   /**    * ContactsContract.Contacts.CONTENT_URI:手机联系人的Uri:content://com.android    * .contacts/contacts    * sort_key_alt:它里面保存的是联系人名字的拼音字母,例如联系人名字是“李明”,则sort_key保存的是“LI李MING明”,    * 这样如果是按sort_key或sort_key_alt排序的话,就可以将联系人按顺序排列    */   Cursor cursor = resolver.query(ContactsContract.Contacts.CONTENT_URI,     null, null, null, "sort_key_alt");   contactList = new ArrayList<Contact>();   while (cursor.moveToNext()) {    Contact contact = new Contact();    String phoneNumber = null;    String name = cursor.getString(cursor      .getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));    String id = cursor.getString(cursor      .getColumnIndex(ContactsContract.Contacts._ID));    Cursor phoneCursor = resolver.query(      ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,      ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = "        + id, null, null);    while (phoneCursor.moveToNext()) {     phoneNumber = phoneCursor       .getString(phoneCursor         .getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));    }    contact.setId(Integer.parseInt(id));    contact.setName(name);    contact.setPhone(phoneNumber);    contactList.add(contact);   }   adapter = new ContactsAdapter(this, contactList);   listview.setAdapter(adapter);  }  private class OnItemLongClickListenerImpl implements    OnItemLongClickListener {   @Override   public boolean onItemLongClick(AdapterView<?> parent, View view,     final int position, long id) {    final ContentResolver resolver = getContentResolver();    popupmenu = new PopupMenu(ContactsActivity.this, listview);    popupmenu.getMenuInflater().inflate(R.menu.my_menu,      popupmenu.getMenu());    popupmenu.setOnMenuItemClickListener(new OnMenuItemClickListener() {     @Override     public boolean onMenuItemClick(MenuItem item) {      switch (item.getItemId()) {      case R.id.detail:       String id = contactList.get(position).getId() + "";       Intent intent = new Intent(ContactsActivity.this,         ContactDetailActivity.class);       intent.putExtra("id", id);       startActivity(intent);       break;      case R.id.update:       Toast.makeText(ContactsActivity.this, "执行修改操作",         Toast.LENGTH_SHORT).show();       break;      case R.id.delete:       new AlertDialog.Builder(ContactsActivity.this)         .setTitle("刪除联系人")         .setMessage("你确定要删除该联系人吗?")         .setPositiveButton("确定", new OnClickListener() {          @Override          public void onClick(DialogInterface dialog,            int which) {           int i = resolver             .delete(ContactsContract.RawContacts.CONTENT_URI,               ContactsContract.Data._ID                 + " = "                 + contactList                   .get(position)                   .getId(),               null);           Toast.makeText(ContactsActivity.this,             i == 1 ? "刪除成功!" : "刪除失敗!",             Toast.LENGTH_SHORT).show();           init();          }         })         .setNegativeButton("取消", new OnClickListener() {          @Override          public void onClick(DialogInterface dialog,            int which) {           dialog.dismiss();          }         }).create().show();       break;      default:       break;      }      // Toast.makeText(ContactsActivity.this,      // "你点击了:" + item.getTitle(), Toast.LENGTH_SHORT)      // .show();      // popupmenu.dismiss();      return true;     }    });    popupmenu.show();    return true;   }  } } /**  * <!-- 联系人相关的uri --> content://com.android.contacts/contacts 操作的数据是联系人信息Uri  * content://com.android.contacts/data/phones 联系人电话Uri  * content://com.android.contacts/data/emails 联系人Email Uri  */ 
View Code

ContactsAdapter.java

android管理联系人操作
package com.demo.adapter; import java.util.ArrayList; import android.content.Context; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView; import com.demo.contentprovider.R; import com.demo.model.Contact; /**  * 联系人的Adapter  *   * @author yinbenyang  */ public class ContactsAdapter extends BaseAdapter {  private Context context;  private ArrayList<Contact> listContact;  public ContactsAdapter(Context context, ArrayList<Contact> listContact) {   this.context = context;   this.listContact = listContact;  }  @Override  public int getCount() {   return listContact.size();  }  @Override  public Object getItem(int position) {   return listContact.get(position);  }  @Override  public long getItemId(int position) {   return position;  }  @Override  public View getView(int position, View convertView, ViewGroup parent) {   ViewHolder holder = null;   if (convertView == null) {    convertView = View      .inflate(context, R.layout.listview_contact, null);    holder = new ViewHolder();    holder.id = (TextView) convertView.findViewById(R.id.id);    holder.name = (TextView) convertView.findViewById(R.id.name);    holder.phone = (TextView) convertView.findViewById(R.id.phone);    convertView.setTag(holder);   } else {    holder = (ViewHolder) convertView.getTag();   }   Contact con = listContact.get(position);   holder.id.setText(con.getId().toString());   holder.name.setText(con.getName());   holder.phone.setText(con.getPhone());   return convertView;  }  static class ViewHolder {   TextView id;   TextView name;   TextView phone;  } } 
View Code

添加联系人Activity:

AddContactActivity.java

android管理联系人操作
package com.demo.contentprovider; import android.app.Activity; import android.content.ContentUris; import android.content.ContentValues; import android.net.Uri; import android.os.Bundle; import android.provider.ContactsContract; import android.provider.ContactsContract.CommonDataKinds.Phone; import android.provider.ContactsContract.CommonDataKinds.StructuredName; import android.provider.ContactsContract.Data; import android.provider.ContactsContract.RawContacts; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; /**  * 添加联系人信息  * @author yinbenyang  *  */ public class AddContactActivity extends Activity implements OnClickListener{  private EditText name,phone;  private Button save,cancel;  @Override  protected void onCreate(Bundle savedInstanceState) {   // TODO Auto-generated method stub   super.onCreate(savedInstanceState);   setContentView(R.layout.addcontact);   name = (EditText) findViewById(R.id.name);   phone = (EditText) findViewById(R.id.phone);   save = (Button) findViewById(R.id.save);   cancel = (Button) findViewById(R.id.cancel);   save.setOnClickListener(this);   cancel.setOnClickListener(this);  }  @Override  public void onClick(View v) {   // TODO Auto-generated method stub   switch (v.getId()) {   case R.id.save:    String _name = name.getText().toString().replaceAll(" ", "");    String _phone = phone.getText().toString().replaceAll(" ","");    ContentValues values = new ContentValues();     //首先向RawContacts.CONTENT_URI执行一个空值插入,目的是获取系统返回的rawContactId    Uri rawContactUri =getContentResolver().insert(RawContacts.CONTENT_URI, values);    long rawContactId = ContentUris.parseId(rawContactUri);    //往data表入姓名数据    values.clear();    values.put(Data.RAW_CONTACT_ID, rawContactId);    //设置内容类型    values.put(Data.MIMETYPE, StructuredName.CONTENT_ITEM_TYPE);    //设置内容名字    values.put(StructuredName.GIVEN_NAME, _name);    getContentResolver().insert(      ContactsContract.Data.CONTENT_URI, values);     //往data表入电话数据    values.clear();    values.put(Data.RAW_CONTACT_ID, rawContactId);    values.put(Data.MIMETYPE, Phone.CONTENT_ITEM_TYPE);    //设置电话号码    values.put(Phone.NUMBER, _phone);    //设置电话类型    values.put(Phone.TYPE, Phone.TYPE_MOBILE);    getContentResolver().insert(      ContactsContract.Data.CONTENT_URI, values);    this.finish();    break;   case R.id.cancel:    this.finish();    break;   default:    break;   }  } } 
View Code

联系人详细页面:

ContactDetailActivity.java

android管理联系人操作
package com.demo.contentprovider; import android.app.Activity; import android.content.ContentResolver; import android.content.Intent; import android.database.Cursor; import android.os.Bundle; import android.provider.ContactsContract; import android.widget.TextView; /**  * 联系人详细信息  *   * @author yinbenyang  *  */ public class ContactDetailActivity extends Activity {     private TextView et_name, et_phone, et_email, et_address;     @Override     protected void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  setContentView(R.layout.contactdetail);  et_name = (TextView) findViewById(R.id.et_name);  et_phone = (TextView) findViewById(R.id.et_phone);  et_email = (TextView) findViewById(R.id.et_email);  et_address = (TextView) findViewById(R.id.et_address);  Intent intent = getIntent();  String id = intent.getStringExtra("id");  ContentResolver resolver = getContentResolver();  // 查找姓名  Cursor nameCursor = resolver.query(   ContactsContract.Contacts.CONTENT_URI,   null,   ContactsContract.Contacts._ID + " = " + id,   null, null);  while(nameCursor.moveToNext()){      et_name.setText(nameCursor.getString(nameCursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME)));  }  // 查找手机号  Cursor phoneCursor = resolver.query(   ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,   ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = " + id,   null, null);  while (phoneCursor.moveToNext()) {      et_phone.setText(phoneCursor.getString(phoneCursor       .getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)));  }  // 查找邮箱  Cursor emailCursor = resolver.query(   ContactsContract.CommonDataKinds.Email.CONTENT_URI, null,   ContactsContract.CommonDataKinds.Email.CONTACT_ID + " = " + id,   null, null);  while (emailCursor.moveToNext()) {      et_email.setText(emailCursor.getString(emailCursor       .getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA)));  }  // 查找地址  Cursor addressCursor = resolver.query(   ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_URI,   null,   ContactsContract.CommonDataKinds.StructuredPostal.CONTACT_ID    + " = " + id, null, null);  while (addressCursor.moveToNext()) {      et_address       .setText(addressCursor.getString(addressCursor        .getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.DATA)));  }     } } 
View Code

最后效果图如下。可以实现联系人的添加,删除和修改功能:

android管理联系人操作 android管理联系人操作 android管理联系人操作

android管理联系人操作 android管理联系人操作 android管理联系人操作

正文到此结束
Loading...