废话就不多说了,主要用到了ContentProvider的相关知识。
//这是一个工具类,主要是将联系人的Name,phone ,email,address,放到List集合中。
package com.example.contact_content_provider; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import android.content.ContentResolver; import android.database.Cursor; import android.net.Uri; import android.provider.ContactsContract; public class ContactUtils { public static List<Map<String, Object>> getContactList(ContentResolver resolver) { List<Map<String, Object>>list=new ArrayList<Map<String,Object>>(); //对应表 raw_contacts String contactUriStr="content://com.android.contacts/raw_contacts";//帮助理解 Uri contactUri=ContactsContract.Contacts.CONTENT_URI; //对应data表 String dataUriStr="content://com.android.contacts/data"; //联系人电话 String phoneUriStr="content://com.android.contacts/data/phones"; Uri phoneUri=ContactsContract.CommonDataKinds.Phone.CONTENT_URI; //联系人email; String emailUriStr="content://com.android.contacts/data/emails"; Uri emailUri=ContactsContract.CommonDataKinds.Email.CONTENT_URI; //联系人的地址: String addressUriStr="content://com.android.contacts/data/postals"; Uri addressUri=ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_URI; Cursor contactCursor=resolver.query(contactUri, new String []{"_id","display_name"}, null, null, null); while (contactCursor.moveToNext()) { int contactId=contactCursor.getInt(0); String display_name=contactCursor.getString(1); Map<String , Object>map=new HashMap<String, Object>(); map.put(ContactsContract.Contacts.DISPLAY_NAME,display_name); map.put(ContactsContract.Contacts._ID, contactId); //查询联系人电话 Cursor phoneCursor=resolver.query(phoneUri, null, "raw_contact_id=?", new String []{contactId+""}, null); String phone=""; while(phoneCursor.moveToNext()) { phone=phoneCursor.getString(phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DATA)); } map.put("phone", phone); //查询联系人的邮箱 Cursor emailcCursor=resolver.query(emailUri, null, "raw_contact_id=?", new String []{contactId+""}, null); String email=""; while(emailcCursor.moveToNext()) { email=emailcCursor.getString(emailcCursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA)); } map.put("email", email); Cursor addCursor=resolver.query(addressUri, null, "raw_contact_id=?", new String [] {contactId+""}, null); String address=""; while(addCursor.moveToNext()) { address=addCursor.getString(addCursor.getColumnIndex("data1")); }//上面的ContactsContract.CommonDataKinds.Email.DATA/phone 都可以用data1代替 map.put("address", address); list.add(map); } return list; } }
------------------------------------------------------------------------------------------------
自定义适配器,继承了BaseAdapter。重写里面的四个方法。从而达到自己想要的布局。
这个东西很简单,就不做过多的解释了。
package com.example.contact_content_provider; import java.util.List; import java.util.Map; import android.content.Context; import android.provider.ContactsContract.Contacts; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView; public class MyAdapter extends BaseAdapter { ViewHolder holder; private List<Map<String, Object>>list; LayoutInflater inflater; public MyAdapter(Context context,List<Map<String, Object>>list) { inflater=LayoutInflater.from(context); this.list=list; } @Override public int getCount() { // TODO Auto-generated method stub return list.size(); } @Override public Object getItem(int arg0) { // TODO Auto-generated method stub return list.get(arg0); } @Override public long getItemId(int arg0) { // TODO Auto-generated method stub return arg0; } @Override public View getView(int arg0, View arg1, ViewGroup arg2) { if (arg1==null) { holder=new ViewHolder(); arg1=inflater.inflate(R.layout.item, null); holder.tvname=(TextView)arg1.findViewById(R.id.tv_name); holder.tvphone=(TextView)arg1.findViewById(R.id.tv_phone); holder.tvemail=(TextView)arg1.findViewById(R.id.tv_email); holder.tvaddress=(TextView)arg1.findViewById(R.id.tv_address); arg1.setTag(holder); }else { holder=(ViewHolder)arg1.getTag(); } holder.tvname.setText(list.get(arg0).get("display_name").toString()); holder.tvphone.setText(list.get(arg0).get("phone").toString()); holder.tvemail.setText(list.get(arg0).get("email").toString()); holder.tvaddress.setText(list.get(arg0).get("address").toString()); return arg1; } class ViewHolder { TextView tvname,tvphone,tvemail,tvaddress; } }
------------------------------------------------------------------------------------------------
这是主函数 ,里面的各项操作我已经做了详细的注释。
-------------------------------------------------------------------------------------------------------
package com.example.contact_content_provider; import java.util.ArrayList; import java.util.List; import java.util.Map; import android.R.integer; import android.app.Activity; import android.app.AlertDialog; import android.content.ContentResolver; import android.content.ContentUris; import android.content.ContentValues; import android.content.DialogInterface; import android.content.DialogInterface.OnClickListener; import android.net.Uri; import android.os.Bundle; import android.provider.ContactsContract; import android.view.ContextMenu; import android.view.MenuItem; import android.view.View; import android.view.ContextMenu.ContextMenuInfo; import android.widget.AdapterView.AdapterContextMenuInfo; import android.widget.EditText; import android.widget.ListView; import android.widget.Toast; public class MainActivity extends Activity { private MyAdapter adapter; private ListView listView; private List<Map<String, Object>>dataList; ContentResolver resolver; //数据解析器 boolean flag=true;//设置标志位 判断是进行添加还是修改操作 private AlertDialog edDialog,delDialog; //初始化对话框 private EditText ed_name,ed_phone,ed_email,ed_address; //初始化对话框里的编辑项 int position; //取到长按时ListView所在的位置 protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initData(); inInDialog(); } //初始化视图 public void initData() { listView=(ListView)findViewById(R.id.lv_showContacts); resolver=getContentResolver(); dataList=new ArrayList<Map<String,Object>>(); // dataList=ContactUtils.getContactList(resolver); adapter=new MyAdapter(this, dataList); listView.setAdapter(adapter); registerForContextMenu(listView); } //为搜索按钮设置监听事件 public void queryContacts(View v) { List<Map<String, Object>>list=ContactUtils.getContactList(resolver); dataList.clear();//不进行此操作的时候会使联系人重复出现 dataList.addAll(list); adapter.notifyDataSetChanged();//数据有变动时,执行唤醒操作,告诉数据库,我变了 } public void addContacts(View v) { flag=true; ed_address.setText(""); ed_email.setText(""); ed_name.setText(""); ed_phone.setText(""); edDialog.show(); } //初始化对话框 public void inInDialog() { View view=getLayoutInflater().inflate(R.layout.dialog_edit, null); ed_name=(EditText)view.findViewById(R.id.et_name); ed_phone=(EditText)view.findViewById(R.id.et_phone); ed_email=(EditText)view.findViewById(R.id.et_email); ed_address=(EditText)view.findViewById(R.id.et_address); edDialog=new AlertDialog.Builder(this).setView(view).setIcon(android.R.drawable.ic_input_add).setTitle("请选择你要编辑的选项"). setPositiveButton("确认", new OnClickListener() { @Override public void onClick(DialogInterface arg0, int arg1) { if (flag) { insertData(); //执行插入操作 }else { updateData(); //执行编辑或者修改操作 } } }).setNegativeButton("取消", new OnClickListener() { @Override public void onClick(DialogInterface arg0, int arg1) { // TODO Auto-generated method stub } }).create(); //初始化删除对话框 delDialog=new AlertDialog.Builder(this).setIcon(android.R.drawable.ic_input_add).setTitle("你确定要删除吗"). setPositiveButton("确认", new OnClickListener() { @Override public void onClick(DialogInterface arg0, int arg1) { int n= resolver.delete(ContactsContract.RawContacts.CONTENT_URI, "_id=?", new String[]{dataList.get(position).get("_id").toString()}); if (n>0) { Toast.makeText(getApplicationContext(), "删除成功", 1).show(); queryContacts(null); } } }).setNegativeButton("取消", new OnClickListener() { @Override public void onClick(DialogInterface arg0, int arg1) { } }).create(); } //为ListView的长按操作设置菜单选项 public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { // TODO Auto-generated method stub super.onCreateContextMenu(menu, v, menuInfo); getMenuInflater().inflate(R.menu.main,menu);//得到菜单视图 position=((AdapterContextMenuInfo)menuInfo).position; //获得选中的ListVIew的Id } public boolean onContextItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.update://执行修改操作 flag=false; //改变标志位 Map<String, Object>map=dataList.get(position); //得到选中的ListVIew的值 并且显示到编辑框 ed_address.setText(map.get("address").toString()); ed_email.setText(map.get("email").toString()); ed_name.setText(map.get("display_name").toString()); ed_phone.setText(map.get("phone").toString()); edDialog.show(); break; case R.id.delete: delDialog.show(); break; default: break; } return super.onContextItemSelected(item); } //插入操作 public void insertData() { String name=ed_name.getText().toString(); String phone=ed_phone.getText().toString(); String email=ed_email.getText().toString(); String address=ed_address.getText().toString(); ContentValues values=new ContentValues(); values.put("display_name", name); values.put("display_name_alt", name); //向 raw_contacts表中插入数据。获得新增行的_id; Uri uri=resolver.insert(Uri.parse("content://com.android.contacts/raw_contacts"), values); //获得_id long id=ContentUris.parseId(uri); //向表中插入数据display_name // values.clear(); values.put("data1", name); values.put("data2", name); values.put("raw_contact_id", id); values.put("mimetype", "vnd.android.cursor.item/name"); resolver.insert(ContactsContract.Data.CONTENT_URI, values); //插入phone // values.clear(); values.put("data1", phone); values.put("raw_contact_id", id); values.put("mimetype", "vnd.android.cursor.item/phone_v2"); resolver.insert(ContactsContract.Data.CONTENT_URI, values); //插入email values.clear(); values.put("data1",email); values.put("raw_contact_id", id); values.put("mimetype", "vnd.android.cursor.item/email_v2"); resolver.insert(ContactsContract.Data.CONTENT_URI, values); //插入Address values.clear(); values.put("data1", address); values.put("raw_contact_id", id); values.put("mimetype", "vnd.android.cursor.item/postal-address_v2"); resolver.insert(ContactsContract.Data.CONTENT_URI, values); queryContacts(null); } public void updateData() { //获得对话框填写的内容 String name=ed_name.getText().toString(); String phone=ed_phone.getText().toString(); String email=ed_email.getText().toString(); String address=ed_address.getText().toString(); //获得ListVIew Position位置上所对应的在data中的_id String _id=dataList.get(position).get("_id").toString(); //根据_id修改raw_contacts ContentValues values=new ContentValues(); values.put("display_name", name); values.put("display_name_alt", name);//x修改两次的原因是name在两个表中都存在 resolver.update(Uri.parse("content://com.android.contacts/raw_contacts"), values, "_id=?", new String []{_id}); //根据_id修改联系人姓名 values.clear(); values.put("data1", name); values.put("data2", name); int n1=resolver.update(Uri.parse("content://com.android.contacts/data"), values, "raw_contact_id=? and mimetype_id=?", new String[]{_id,7+""}); //根据_id修改联系人的phone values.clear(); values.put("data1", phone); int n2=resolver.update( ContactsContract.Data.CONTENT_URI,values, "raw_contact_id=? and mimetype_id=?", new String []{_id,5+""}); //根据id修改联系人的email values.clear(); values.put("data1", email); int n3=resolver.update(ContactsContract.Data.CONTENT_URI, values, "raw_contact_id=? and mimetype_id=?", new String []{_id,1+""}); //根据_id修改联系人的address; values.clear(); values.put("data1", address); int n4=resolver.update(ContactsContract.Data.CONTENT_URI, values, "raw_contact_id=? and mimetype_id=?", new String []{_id,8+""}); if (n1>0|n2>0|n3>0|n4>0) { Toast.makeText(this, "修改成功", 1).show(); queryContacts(null); } else { Toast.makeText(this, "修改失败", 1).show(); } } }
··········································································································
接下来的是布局文件 ,写的比较简单,也不美观。这种细致的工作有空自己慢慢玩。
这个布局是用来查询和新增联系人。
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <Button android:id="@+id/btn_query" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="queryContacts" android:text="查询联系人" /> <Button android:id="@+id/btn_add" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@id/btn_query" android:onClick="addContacts" android:text="新增联系人" /> <ListView android:id="@+id/lv_showContacts" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@id/btn_query"></ListView> </RelativeLayout>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <Button android:id="@+id/btn_query" android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="queryContacts" android:text="查询联系人" /> <Button android:id="@+id/btn_add" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@id/btn_query" android:onClick="addContacts" android:text="新增联系人" /> <ListView android:id="@+id/lv_showContacts" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@id/btn_query"></ListView> </RelativeLayout>
---------------------------------------------------------------------------------------------------------------------
这是联系人的查询显示界面。。
<?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="match_parent" > <TextView android:id="@+id/tv_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="name"/> <TextView android:id="@+id/tv_phone" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:text="phone"/> <TextView android:id="@+id/tv_address" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/tv_name" android:text="address"/> <TextView android:id="@+id/tv_email" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/tv_name" android:layout_alignParentRight="true" android:text="email"/> </RelativeLayout>
。还有一点,要对手机里的联系人进行操作,必须要在清单文件中加入两个权限。
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.WRITE_CONTACTS"/>