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工具来查看,这里为了方便我们导出来看一下。

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

 

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

表和视图:

 

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

contacts表:

  _id :表的ID,主要用于其它表通过contacts 表中的ID可以查到相应的数据。
  display_name: 联系人名称
  photo_id:头像的ID,如果没有设置联系人头像,这个字段就为空
  times_contacted:通话记录的次数
  last_time_contacted: 最后的通话时间 
  lookup :是一个持久化的储存 因为用户可能会改名子 但是它改不了lookup

data表:

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

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

raw_contacts表:

   version :版本号,用于监听变化
  deleted :删除标志, 0为默认 1 表示这行数据已经删除
  display_name : 联系人名称
  last_time_contacts : 最后联系的时间

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

2、代码实现

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

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

(2)布局文件

  首先是列表展示页面:

<?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>

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

<?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>

  添加联系人界面:

<?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>

  联系人详细界面:

<?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>

  程序中需要用的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

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
*/

ContactsAdapter.java

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;
}

}

  添加联系人Activity:

AddContactActivity.java

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;
}
}
}

  联系人详细页面:

ContactDetailActivity.java

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)));
}
}
}

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

 

本文链接:android管理联系人操作,转载请注明。



You must enable javascript to see captcha here!

Copyright © All Rights Reserved · Green Hope Theme by Sivan & schiy · Proudly powered by WordPress

无觅相关文章插件,快速提升流量