【Android】12.5 利用Intent读取和更新通讯录
分类:C#、Android、VS2015;
创建日期:2016-02-23
修改日期:2016-03-08更正了未关闭cursor的bug。
一、简介
本节演示如何在安卓系统中通过用户配置文件(user profile)读取和更新该手机的所有联系人信息,以及如何导航到用户配置文件中的这些联系人。
二、基本概念
1、什么是 User Profile
用户配置文件(user profile)保存的是机主信息以及该手机中所有联系人的信息。
假定手机所有者的名字为“Mao mao yu”,那么,user profile保存的就是“Mao mao yu”的通讯录(即机主所有联系人的姓名、电话、邮箱、……等信息)。在Android 4中,这个保存联系人信息的应用程序称为“People app”,而在Android 5.0及更高版本中,这个应用程序又改称为“Contacts app” 。
Android 6.0(API 23)模拟器已经包含了【通讯录】功能,利用它可直接手工添加手机所有者姓名及其联系人,如下图所示:

单击【通讯录】中的某个联系人,例如单击机主的名字(或者其他联系人的名字),就可以在显示的界面中修改这个人的姓名、电话、邮箱、住址等信息,或者添加新联系人,这个功能大家在手机上用的太熟了,这里就不多说了。
我们这一节的目标就是学习如何在自己的应用程序中通过代码去添加或修改这个用户配置文件(user profile)中的信息,而不是用它自身提供的功能去编辑。
2、权限要求
要在你的程序中读和写手机所有联系人的数据,你的应用程序必须具有Read_Contacts和Write_Contacts权限。另外,要读取和编辑用户配置文件(user profile),你的应用程序必须具有Read_Profile和Write_Profile权限。
或者说,必须具有下面的权限才能读写通讯录和机主的用户配置文件:
READ_CONTACTS
READ_PROFILE
WRITE_CONTACTS
WRITE_PROFILE
实际上,你手机上下载的各类应用程序,只要有对应的权限,都可以获取和修改你的通讯录(一般手机用户都不是搞计算机的,因此也不太关心什么权限不权限,直接按下一步点下去,结果是默认都给这些程序赋予了完全的读写权限)。或者说,只要你给这些应用程序赋予了对应的读写权限,那么你的通讯录实际上就没有一点安全可言了,这些程序想什么时候获取就可以什么时候获取(泄露出去真是太简单了),这也是为什么有那么多免费的手机应用拼命让你去下载和使用的原因。
下图是在VS2015中设置Read_Contacts和Read_Profile的办法(通过单击主菜单【项目】下的【属性】弹出此界面):
按照同样的办法,可继续设置WRITE_CONTACTS和WRITE_PROFILE权限。
3、获取通讯录信息(Reading Profile Data)
安卓早期的版本是通过ContactContracts.Contacts类来获取手机上所有联系人的列表信息的。从Android 4开始又提供了一个新的ContactsContact.Profile类,该类提供了对设备所有者用户配置文件(user profile)的访问,利用它即可获取和修改所有联系人的名称、电话号码等数据。
向 ContactsContact.Profile.ContentUri 发出查询即可读取配置文件的数据。例如,下面的代码读取该用户配置文件的显示名称:
var uri = ContactsContract.Contacts.ContentUri;
string[] projection = {
ContactsContract.Contacts.InterfaceConsts.DisplayName
};
var cursor = ContentResolver.Query(uri, projection, null, null, null);
if (cursor.MoveToFirst ()) {
Console.WriteLine(cursor.GetString (cursor.GetColumnIndex (projection [0])));
}
4、更新联系人信息(Update the User's Profile)
应用程序只要有对应的读写权限,就可以像其他普通的应用程序一样与用户配置文件(user profile)中的数据进行交互。例如,调用ContentResolver.Update方法可更新配置文件中的显示名称,该方法通过ContactsContract.Profile.ContentRawContactsUri属性检索Uri,如下面的代码所示:
var values = new ContentValues ();
values.Put (ContactsContract.Contacts.InterfaceConsts.DisplayName, "Mao mao yu");
ContentResolver.Update (ContactsContract.Profile.ContentRawContactsUri,values, null, null);
注意:不能显式创建用户配置文件(user's profiile),否则将出现异常。
接下来,可创建一个ReadBackName方法,如下面的代码所示。调用此方法可验证添加到用户配置文件的名称是否确实被更新了。在这个方法中,首先获取用户的配置文件的 URI 并配置投影,从此配置文件中仅仅读取一列 (用户的显示名称)。为了访问用户的配置文件数据,接下来创建了一个游标对象。如果成功地初始化游标,则它被移动到用户配置文件中的第一项。在此位置 (用户显示名称) 的第一列中读取名称并将其打印到控制台。如果这些操作成功,ReadBackName 返回 true;否则返回 false。
bool ReadBackName()
{
Android.Net.Uri uri = ContactsContract.Profile.ContentUri;
string[] projection = { ContactsContract.Contacts.InterfaceConsts.DisplayName };
var cursor = ContentResolver.Query(uri, projection, null, null, null);
if (cursor != null)
{
if (cursor.MoveToFirst())
{
Console.WriteLine(cursor.GetString(cursor.GetColumnIndex(projection[0])));
return true;
}
}
return false;
}
添加一个ViewProfile方法,该方法会自动调用Contacts App显示user profile中的信息:
void ViewProfile ()
{
Intent intent = new Intent (Intent.ActionView, ContactsContract.Profile.ContentUri);
StartActivity (intent);
}
注意:仅在Android 4及更高版本中才可以使用手机所有者的用户配置文件。另外,在用户配置文件可以更新之前,必须先手动创建联系人。
关于ContactContracts.Profile 的更多信息,请参见 ContactsContract.Profile 类。
三、示例—ch1204ReadContacts
本示例演示如何获取通讯录中的联系人。
1、运行截图
单击【读取通讯录】按钮,即得到下面右侧的截图。

单击【修改机主信息】按钮,即得到下面的修改界面:
下图是在Android 4.4.2(API 19)下运行的结果:
2、主要设计步骤
(1)设置权限
在VS2015开发环境下,选择主菜单的【项目】à【ContactsDemo属性】,在弹出的窗口中勾选下面的权限:
READ_CONTACTS
READ_PROFILE
WRITE_CONTACTS
WRITE_PROFILE
或者在【解决方案资源管理器】中,鼠标双击项目的【Properties】进入设置界面,然后勾选上面的选项。
设置完毕后,在AndroidManifest.xml文件中就会自动添加下面的代码:
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.READ_PROFILE" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_PROFILE" />
(2)添加改ch1204_Main.axml文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:background="@android:color/background_light"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<Button
android:text="读取通讯录"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/btnRead" />
<Button
android:text="修改机主信息"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/btnUpdate" />
</LinearLayout>
(3)添加ch1204_ContactListItem.axml文件
在Resources/layout/下添加该文件。
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="15dip" />
(4)添加ch1204ReadContactActivity.cs文件
using System.Collections.Generic;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Widget;
using Android.Provider; namespace MyDemos.SrcDemos
{
[Activity(Label = "【例12-4】读取和更新通讯录")]
public class ch1204ReadContactActivity : ListActivity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
var uri = ContactsContract.Contacts.ContentUri;
string[] projection = {
ContactsContract.Contacts.InterfaceConsts.Id,
ContactsContract.Contacts.InterfaceConsts.DisplayName
};
var cursor = ContentResolver.Query(uri, projection, null, null, null);
var contactList = new List<string>();
if (cursor.MoveToFirst())
{
do
{
contactList.Add(cursor.GetString(cursor.GetColumnIndex(projection[1])));
} while (cursor.MoveToNext());
}
cuesor.Close();
ListAdapter = new ArrayAdapter<string>(this, Resource.Layout.ch1204_ContactListItem, contactList);
}
}
}
注意该类继承自ListActivity,不是继承自Activity。
(5)添加ch1204ReadContactsMain.cs文件
using Android.App;
using Android.Content;
using Android.OS;
using Android.Widget;
using Android.Provider; namespace MyDemos.SrcDemos
{
[Activity(Label = "【例12-4】读取和更新通讯录")]
public class ch1204ReadContactsMain : Activity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.ch1204_Main); var btnRead = FindViewById<Button>(Resource.Id.btnRead);
btnRead.Click += delegate
{
StartActivity(typeof(ch1204ReadContactActivity));
}; var btnUpdate = FindViewById<Button>(Resource.Id.btnUpdate);
btnUpdate.Click += delegate
{
NameOwner();
if (ReadBackName())
{
Intent intent = new Intent(Intent.ActionView, ContactsContract.Profile.ContentUri);
StartActivity(intent);
}
};
} /// <summary>
/// 定义手机机主的名字
/// </summary>
void NameOwner()
{
ContentValues values = new ContentValues();
//将“Rainmj”插入到已存在的user profile中
values.Put(ContactsContract.Contacts.InterfaceConsts.DisplayName, "Rainmj");
//更新user profile
ContentResolver.Update(ContactsContract.Profile.ContentRawContactsUri,
values, null, null);
} /// <summary>
/// 检查“更新user profile”是否成功
/// </summary>
/// <returns></returns>
bool ReadBackName()
{
//获取user profile的Uri
Android.Net.Uri uri = ContactsContract.Profile.ContentUri; //配置投影,指定准备从user profile中读取的列
string[] projection = {
ContactsContract.Contacts.InterfaceConsts.DisplayName
}; var cursor = ContentResolver.Query(uri, projection, null, null, null);
if (cursor != null)
{
if (cursor.MoveToFirst())
{
cursor.Close();
//Console.WriteLine(cursor.GetString(cursor.GetColumnIndex(projection[0])));
return true;
}
}
return false;
}
}
}
运行即得到截图所示的效果。
【Android】12.5 利用Intent读取和更新通讯录的更多相关文章
- 【Android】12.4 利用Intent读取图库中的图片
分类:C#.Android.VS2015: 创建日期:2016-02-23 一.简介 该示例演示如何从图库(Gallery)中读取图像并用ImageView将它显示出来. 二.示例-ch1203Rea ...
- 【Android基础】利用Intent在Activity之间传递数据
前言: 上一篇文章给大家聊了Intent的用法,如何用Intent启动Activity和隐式Intent,这一篇文章给大家聊聊如何利用Intent在Activity之间进行沟通. 从一个Activ ...
- 【Android】12.2 利用Intent启动和关闭Activity
分类:C#.Android.VS2015: 创建日期:2016-02-23 一.简介 Android应用程序中一般都有多个Activity,在Activity中,通过调用StartActivity方法 ...
- 【Android】12.6 利用Intent实现记事本功能(NotePad)
分类:C#.Android.VS2015: 创建日期:2016-02-23 一.简介 这个例子演示如何实现一个简单的记事本功能. 该例子提前使用了后面章节将要介绍的SQLLite数据库. 二.示例-c ...
- Android中,利用Intent传递对象值
在很多情况下,调用startActivity(Intent) 方法,跳转到另外一个Activity或其他component,需要传递一个对象给它. 可以让这个要传递的对象所属类实现Serializab ...
- Android开发值利用Intent进行put传值,setclass启动activity,并用get进行取值
传值方法一 [java] Intent intent = new Intent(); Bundle bundle = new Bundle(); //该类用作携带数据 bundle.putString ...
- Android开发探秘之四:利用Intent实现数据传递
在Android开发过程中,很多人都熟悉Intent,这是个用于在多个View之间共享数据的类.本节主要是继承上节,通过点选ListView中的文本,把文本中的URL加载到一个新的页面上,并且打印出来 ...
- Android利用Intent与其他应用交互
前言: 上一篇博客给大家聊了Intent的定义,分类.属性和功能,相信大家对于Intent在Android中的作用已经清楚,这一篇博客将会给大家聊Intent的用法. Android系统的一个重要特性 ...
- 008 Android activity实现多个界面的相互跳转(主要利用Intent)
1.activity介绍 一个activity就把他理解成一个页面 2.新建activity流程 如图所示在com.lucky.test06的目录下,右击new--->Activity---&g ...
随机推荐
- Makefile整理
Makefile里的subst 用法是$(subst FROM,TO,TEXT),即将TEXT中的东西从FROM变为TO Makefile中的字符串处理函数 格式: $(subst <from& ...
- php之快速入门学习-2
创建(声明)PHP 变量 PHP 没有声明变量的命令. 变量在您第一次赋值给它的时候被创建: <?php $txt="Hello world!"; $x=5; $y=10.5 ...
- 动态布局中RadioGroup的RadioButton有时候不相互排斥的原因
近期在做一个答题类的模块,有单选.简答.调查问卷等,我是用动态布局的方式生成答题项的.在弄单选的时候遇到一个比較奇葩的问题,在代码中生成RadioGroup和RadioButton的时候.会发现不能相 ...
- JSTL不同版本和EL表达式的关联
JSTL目前有3个版本:JSTL1.0.JSTL1.1.JSTL1.2 JSTL1.0和JSTL1.1包含jstl.jar和standard.jar这2个jar包,在j2ee4的版本中是需要单独引用这 ...
- Cygwin--unix/linux模拟环境
Cygwin是一个在windows平台上运行的类UNIX模拟环境,是cygnus solutions公司开发的自由软件(该公司开发了很多有用的工具,著名的还有eCos,不过现已被Redhat收购).它 ...
- 微信小程序条码、二维码生成模块
代码地址如下:http://www.demodashi.com/demo/13994.html 一.前期准备工作 软件环境:微信开发者工具 官方下载地址:https://mp.weixin.qq.co ...
- 微信小程序四(设置底部导航)
好了 小程序的头部标题 设置好了,我们来说说底部导航栏是如何实现的. 我们先来看个效果图 这里,我们添加了三个导航图标,因为我们有三个页面,微信小程序最多能加5个. 那他们是怎么出现怎么着色的呢?两步 ...
- Android学习系列(10)--App列表之拖拽ListView(上)
研究了很久的拖拽ListView的实现,受益良多,特此与尔共飨. 鉴于这部分内容网上的资料少而简陋,而具体的实现过程或许对大家才有帮助,为了详尽而不失真,我们一步一步分析,分成两篇文章. ...
- 2014年15款新评定的最佳PHP框架
通常,框架都会被认为是帮助开发者快速设计和开发动态网站的软件应用.每个月都有极大数量的新发布的 PHP 框架,使网站开发更简单更高效. 如果你是位 PHP 开发者,正在寻找当前最好的一些 PHP 框架 ...
- JS打开新窗口防止被浏览器阻止的方法[转]
本文实例讲述了JS打开新窗口防止被浏览器阻止的方法.分享给大家供大家参考.具体分析如下: 用传统的window.open()方式打开新窗口,会被浏览器阻止,那么,我们如何才能让JS打开新窗口不被浏览器 ...