文档章节

ContentProvider:读取手机通讯录、号码等信息(16)

f
 flyqilong
发布于 2016/02/20 16:52
字数 1343
阅读 62
收藏 0
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.Toast;

public class MainActivity extends Activity implements OnItemLongClickListener,
		OnItemClickListener {
	// 操作手机通讯录
	private String uri_contacts = "content://com.android.contacts/contacts";// 手机通讯录现在有的联系人
	private String uri_raw_contacts = "content://com.android.contacts/raw_contacts";// 原始的通讯录(包括已经删除的联系人)
	private String uri_data = "content://com.android.contacts/data";// 与raw_contacts关联的表,插入时除了更新raw_contacts还要更新data表
	private String uri_data_phone = "content://com.android.contacts/data/phones";//data/phones手机号信息
	private String uri_data_email = "content://com.android.contacts/data/emails";//data/emails信息
	private List<Map<String, String>> list;
	private SimpleAdapter adapter;
	private ContentResolver resolver;
	private ListView listview;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		listview = (ListView) this
				.findViewById(R.id.listView_main_contactslist);
		resolver = getContentResolver();
		list = roladDataFromTable(resolver);
		adapter = new SimpleAdapter(this, list, R.layout.item_listview_main,
				new String[] { "id", "displayname", "phones", "emails" },
				new int[] { R.id.text_item_id, R.id.text_item_displayname,
						R.id.text_item_phones, R.id.text_item_emails });
		listview.setAdapter(adapter);
		// 长按时删除
		listview.setOnItemLongClickListener(this);
		// 点击时修改
		listview.setOnItemClickListener(this);
	}

	// 查询所有没有被删除的联系人
	private List<Map<String, String>> roladDataFromTable(
			ContentResolver resolver) {
		List<Map<String, String>> list = new ArrayList<Map<String, String>>();
		// 查找没有删除的数据deleted=0;
		Cursor cursor_Contacts = resolver
				.query(Uri.parse(uri_raw_contacts), new String[] { "_id",
						"display_name" }, "deleted=0", null, null);
		while (cursor_Contacts.moveToNext()) {
			Map<String, String> map = new HashMap<String, String>();
			String raw_contacts_id = cursor_Contacts.getString(cursor_Contacts
					.getColumnIndex("_id"));
			String display_name = cursor_Contacts.getString(cursor_Contacts
					.getColumnIndex("display_name"));
			// 封装在map
			map.put("id", raw_contacts_id);
			map.put("display_name", display_name);
			// 根据raw_contact_id查询data表的phone的信息 , 注意uri路径
			Cursor cursorPhones = resolver.query(Uri.parse(uri_data_phone),
					new String[] { "data1" }, "raw_contact_id=?",
					new String[] { "raw_contact_id" }, null);
			StringBuilder sb = new StringBuilder();
			// 可能有多个号码
			while (cursorPhones.moveToNext()) {
				sb.append(cursorPhones.getString(0)).append(" ");
			}
			map.put("phones", sb.toString());
			cursorPhones.close();
			// // 根据raw_contact_id查询data表的email的信息 , 注意uri路径
			Cursor cursorEmail = resolver.query(Uri.parse(uri_data_email),
					new String[] { "data1" }, "raw_contact_id=?",
					new String[] { "raw_contact_id" }, null);
			StringBuilder sb2 = new StringBuilder();
			// 可能有多个邮箱
			while (cursorEmail.moveToNext()) {
				sb2.append(cursorEmail.getString(0)).append(" ");
			}
			// 封装在map
			map.put("emails", sb2.toString());
			cursorEmail.close();
			list.add(map);
		}
		cursor_Contacts.close();
		return list;
	}

	// 添加按钮事件,添加联系人
	public void clickButton(View view) {
		AlertDialog.Builder builder = createBuilder(R.drawable.ic_launcher,
				"添加联系人");
		View insertView = getLayoutInflater().inflate(
				R.layout.dialog_insert_info, null);
		final EditText contactname = (EditText) insertView
				.findViewById(R.id.editText_dialog_contactname);
		final EditText phone = (EditText) insertView
				.findViewById(R.id.editText_dialog_phone);
		final EditText email = (EditText) insertView
				.findViewById(R.id.editText_dialog_email);
		builder.setView(insertView);
		// 确定按钮事件
		builder.setPositiveButton("确定", new OnClickListener() {
			@Override
			public void onClick(DialogInterface dialog, int which) {
				Map<String, String> dataMap = new HashMap<String, String>();
				dataMap.put("display_name", contactname.getText().toString());
				dataMap.put("phone", phone.getText().toString());
				dataMap.put("email", email.getText().toString());
				boolean result = insertContact(resolver, dataMap);

				if (result) {
					Toast.makeText(MainActivity.this, "添加联系人成功!",
							Toast.LENGTH_SHORT).show();
					Intent intent = new Intent(MainActivity.this,
							MainActivity.class);
					startActivity(intent);// 添加成功跳回本页面
					finish();
				} else {
					Toast.makeText(MainActivity.this, "添加联系人失败!",
							Toast.LENGTH_SHORT).show();
				}
			}

		});
		builder.show();

	}

	// 添加联系人
	public boolean insertContact(ContentResolver resolver,
			Map<String, String> dataMap) {
		try {
			// 先插入一条raw_contacts数据 , 空数据
			ContentValues values = new ContentValues();
			Uri uri = resolver.insert(Uri.parse(uri_raw_contacts), values);// 该uri包含新增数据的id
			// 获取新插入raw_contacts的主键id,通过id查找关联表进行数据添加
			long id = ContentUris.parseId(uri);
			// 通过id还要更新其他的表
			// 插入data表联系人的姓名,要匹配id和表中的字段,不能随便取
			values.put("raw_contact_id", id);
			// 参考视图:view_data mimetype 是视图列名表示类型如姓名、email,等类型
			values.put("mimetype", "vnd.android.cursor.item/name");
			values.put("data1", dataMap.get("display_name"));
			values.put("data2", dataMap.get("display_name"));
			// 注意:不要传错uri !!!
			resolver.insert(Uri.parse(uri_data), values);
			// 插入data表联系人的电话
			values.clear();// 清空上次数据
			values.put("raw_contact_id", id);
			values.put("mimetype", "vnd.android.cursor.item/phone_v2");
			values.put("data1", dataMap.get("phone"));
			// 住宅电话为1;手机号码为2;单位电话为3.
			values.put("data2", 2);
			resolver.insert(Uri.parse(uri_data), values);
			// 插入data表联系人的email
			values.clear();
			values.put("raw_contact_id", id);
			values.put("mimetype", "vnd.android.cursor.item/email_v2");
			values.put("data1", dataMap.get("email"));
			values.put("data2", 1);
			resolver.insert(Uri.parse(uri_data), values);
			return true;
		} catch (Exception e) {
			Log.i("MainActivity", "插入异常" + e.getMessage());
			e.printStackTrace();
		}

		return false;
	}

	public Builder createBuilder(int icLauncher, String string) {
		AlertDialog.Builder builder = new AlertDialog.Builder(this);
		builder.setTitle(string);
		builder.setIcon(icLauncher);
		builder.setNegativeButton("取消", null);
		return builder;
	}

	// 短按点击修改联系人
	@Override
	public void onItemClick(AdapterView<?> parent, View view, int position,
			long id) {
		Map<String, String> mapItem = (Map<String, String>) parent
				.getItemAtPosition(position);
		String display_name = mapItem.get("display_name");
		final String raw_contact_id = mapItem.get("id");
		AlertDialog.Builder builder = createBuilder(R.drawable.ic_launcher,
				"修改联系人");
		View updateView = getLayoutInflater().inflate(
				R.layout.dialog_update_info, null);
		EditText text_id = (EditText) updateView
				.findViewById(R.id.editText_update_id);
		final EditText text_displayname = (EditText) updateView
				.findViewById(R.id.editText_update_displayname);
		builder.setView(updateView);
		text_id.setText(raw_contact_id);
		text_displayname.setText(display_name);
		builder.setPositiveButton("确定", new OnClickListener() {

			@Override
			public void onClick(DialogInterface dialog, int which) {
				boolean flag = updateContactName(resolver, raw_contact_id,
						text_displayname.getText().toString());
				if (flag) {
					Toast.makeText(MainActivity.this, "修改ok!",
							Toast.LENGTH_SHORT).show();
					Intent intent = new Intent(MainActivity.this,
							MainActivity.class);
					startActivity(intent);
					finish();
				} else {
					Toast.makeText(MainActivity.this, "修改失败!",
							Toast.LENGTH_SHORT).show();
				}

			}

		});
		builder.show();
	}

	// 修改联系人提取出来的方法
	private boolean updateContactName(ContentResolver resolver,
			String raw_contact_id, String display_name) {
		// 通过视图来修改: view_data view_raw_contacts
		ContentValues values = new ContentValues();
		values.put("display_name", display_name);
		values.put("display_name_alt", display_name);
		values.put("sort_key", display_name);
		values.put("sort_key_alt", display_name);
		resolver.update(Uri.parse(uri_raw_contacts), values, "_id=?",
				new String[] { raw_contact_id });
		values.clear();
		values.put("data1", display_name);
		values.put("data2", display_name);
		int row = resolver.update(Uri.parse(uri_data), values,
				"raw_contact_id=? and mimetype=?", new String[] {
						raw_contact_id, "vnd.android.cursor.item/name" });
		if (row > 0) {
			return true;
		}
		return false;
	}

	// 长按删除联系人
	@Override
	public boolean onItemLongClick(AdapterView<?> parent, View view,
			int position, long id) {
		Map<String, Object> map = (Map<String, Object>) parent
				.getItemAtPosition(position); // 获取adapter某一项对应的map

		final String raw_contact_id = (String) map.get("id");
		AlertDialog.Builder builder = createBuilder(R.drawable.ic_launcher,
				"提示:");
		builder.setMessage("确定要删除吗?");
		builder.setPositiveButton("确定", new OnClickListener() {

			@Override
			public void onClick(DialogInterface dialog, int which) {
				boolean flag = deleteContactsInfo(raw_contact_id);
				if (flag) {
					Toast.makeText(MainActivity.this, "删除成功!",
							Toast.LENGTH_SHORT).show();
					Intent intent = new Intent(MainActivity.this,
							MainActivity.class);
					// intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
					startActivity(intent);
					finish();
				} else {
					Toast.makeText(MainActivity.this, "删除失败!",
							Toast.LENGTH_SHORT).show();
				}
			}

		});
		builder.show();
		return true;// 注意长按是要改为true,否则会跳到短按点击那里。有关事件分发
	}

	public boolean deleteContactsInfo(String raw_contact_id) {
		// 删除只是把raw_contacts表中的外键contact_id设置为null,Contacts表中删除记录
		ContentResolver resolver = getContentResolver();
		int row = resolver.delete(Uri.parse(uri_raw_contacts), "_id=?",
				new String[] { raw_contact_id });
		if (row > 0) {
			return true;
		}
		return false;
	}
}

权限:android.permission.READ_CONTACTS

android.permission.WRITE_CONTACTS

android.permission.MOUNT_UNMOUNT_FILESYSTEMS

主布局:放的是一个button,一个listview  ,添加数据的主句放的是三个EditText


,添加联系人布局放的是三个EditText,修改布局放的是两个EditText,     


listview自定义布局放的是四个TextView


© 著作权归作者所有

f
粉丝 3
博文 93
码字总数 53900
作品 0
Android工程师
私信 提问
Android Content Provider(内容提供者)

什么是Content Provider 应用程序间共享数据的一种方式 为存储和获取数据提供了统一的接口 Android为常见的一些数据提供了默认的ContentProvider Uri : 通用资源标识符 创建和使用Content P...

lanyu96
2018/12/06
0
0
Android通讯录数据库操作(转)

可以参考 这个博客http://www.uml.org.cn/mobiledev/201110121.asp 对contact2.db中的几个比较常用的表进行总结: 包括 contacts表,rawcontacts表,data表,phonelookup表 希望大家参照源代...

xiahuawuyu
2012/09/29
0
0
IOS通讯录的隐藏标签(电话)的特殊功能

这功能比较适合有强迫症,爱折腾的人哈!! 规范了通讯录标签,以后可以轻松的知道别人是用短号还是亲情网给你打电话。 如果是长号还可以显示归属地。 也许从IOS8(不太清楚)开始自带了号码...

火冷
2016/06/27
723
0
基础总结篇之六:ContentProvider之读写联系人

今天我们来讲解一下如何利用ContentProvider机制读写联系人信息。 在Android中,ContentProvider是一种数据包装器,适合在不同进程间实现信息的共享。例如,在Android中SQLite数据库是一个典...

andy521zhu
2015/04/03
0
0
微信公众号获取精准粉丝方法?

     微信公众号获取精准粉丝方法?应该可以说粉丝就是公众号的生命,最近很多微信用户问我微信公众号获取精准粉丝方法?下面小编就带你了解一下微信公众号获取精准粉丝方法?      微信...

公众开发运营官网
2018/02/28
0
0

没有更多内容

加载失败,请刷新页面

加载更多

PostgreSQL如何实现跨平台代码

我们知道,PostgreSQL可以支持几乎(这个词似乎可以不要)所有主流平台,平台间尤其Windows与*nix之间的API差异巨大,PG是怎么做到的呢,用一个简单的例子解释。 前边我写怎么在Windows下编译...

有理想的猪
30分钟前
5
0
隐私政策声明

服务协议及隐私政策 为使用应用【随手记账本】(安卓包名:com.th.bk 以下简称“本软件”)服务,“厦门量子堆栈科技有限公司”以下简称“本公司”,除非你已阅读并接受本协议所有条款,否则...

Gemini-Lin
40分钟前
17
0
IT兄弟连 Java语法教程 流程控制语句 循环结构语句2

双重for循环 如果把一个循环放在另一个循环体中,那么就可以形成嵌套循环,也就是双重for循环,当然嵌套循环也可以是for循环嵌套while循环,也可以是while循环嵌套while循环……,即各种类型...

老码农的一亩三分地
46分钟前
15
0
访问LNMP虚拟主机出现报错:No input file specified.

之前一直是使用lnmp一键包,但是访问创建的虚拟主机,并没有出现过的错误:No input file specified. 网上的文章很多,但是都是转载,而且原因也很多,根本不适用 后面在lnmp一键包官网找到解...

wenzhizhong
今天
13
0
OSChina 周三乱弹 —— 你还能管得住观众愿意看谁吗

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @宇辰OSC :分享李宗盛的单曲《凡人歌 (电视剧《碧海情天》主题曲)》:你我皆凡人,生在人世间#今日歌曲推荐# 《凡人歌 (电视剧《碧海情天》主...

小小编辑
今天
1K
21

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部