1.1通讯录模型

symbian os手机的通讯录采用文件方式存储,就是通讯录数据库。每个个symbian os手机都有一个默认的通讯录数据库。symbian os 的手机通讯录在开发上的操作依靠symbian os通讯录模型(contacts model)来实现。contacts model由通讯录数据库,通讯录条目(项),通讯录域组成,

们之间的关系是:一个手机除了系统自带的默认通讯录数据库外还可以带多个通讯录数据库;一个通讯录数据库有多个通讯录条目组成,这里每个条目就是每个联系人,具体数量限制各个手机应该不一样;而一个通讯录条目又有多个通讯录域组成,好比有姓名、工作手机号码、家庭手机号码等等,每个项就是一个域。

在这里Symbian为了统一通讯录格式,所以将通讯录条目采用vCard格式MIME规范(RFC 1521)所定义的明码文本来定义域,具体的vCard简单介绍见附录。

Symbian OS通讯录操作API类

知道了Contacts Model的概念,Symbian OS将很多系统API操作封装为几个类:

      CContactDatabase(数据库类):负责新建、打开、关闭等基本数据库操作外,还负责数据库更新(通讯录条目的新建、修改、删除需要通过CContactDatabase类的操作才能实现)、排序和查找,另外还有一些建立快速拨号之类的操作也是通过它来实现

CContactItem(通讯录条目类):由唯一的一个TContactItemId(一个TInt32类型的宏定义)标识,负责具体一个通讯录条目的创建、修改,其直接管理每一个通讯录域。

  CContactItemField(域类):每一个域就是一个真实单一的数据,该数据的类型具有存储类型(TStorageType)和域类型(TFieldType)同时决定,具体的四种存储类型和多种域类型定义见系统头文件cntdef.h内的定义。

当然还有很多其它的类,比如CContactItemFieldSet(域集类)、CContactFieldStorage(与存储基类)、CContactTextFields(文本存储域类)、MContactDbObserver(通讯数据库观察类)等等

Symbian OS通讯录操作实例

1.1、       创建数据库

在symbian os中通过 CContactDatabase::CreateL()函数创建数据库。在创建之前数据库已经存在,CContactDatabase::CreatL()函数KErrAlreadyExists退出,如前所述,如果没有定义参数,CContactDatabase::CreatL()函数将创建一个默认的数据库。    为避免出现KErrAlreadyExists退出的情况 ,在创建数据库之前调用CContactDatabase::FindContactFile()函数给出了一个数据库文件的描述符,如果不存在默认数据库的话,该描述符就会返回该默认数据库的位置。

TFileName contactDbFilePath;

CContactDatabase* newDefaultContactDb;

//是否存在默认数据库

if(!CContactDatabase::FindContactFile(contactDbFilePath))

{

newDefaultContactDb = CContactDatabase::CreateL();

}

CleanupStack::PushL(newDefaultContactDb);

// 添加自己功能代码

CleanupStack::PopAndDestroy(newDefaultContactDb);

注:以上代码负责创建一个空的默认数据库。

1.2、       打开和关闭数据库

CContactDatabase::OpenL()函数有两个重载函数。如果该函数没有给出一个参数,就打开默认的数据库。另一种情况也可以传递一个有关数据库的路径和文件名,规定打开一个指定数据库。

(1)打开默认数据库

CContactDatabase* contactsDb = CContactDatabase::OpenL();

CleanupStack::PushL(contactsDb);

//取得当前数据库所有通讯条目数

TInt numberOfContacts = contactsDb->CountL();

//释放数据库

CleanupStack::PopAndDestroy(contactsDb);

要注意的是:某个通信录数据库并不具有Close()函数或类似的函数,否则我们压入清除栈时就得用CleanupClosePushL()函数了。

(2)打开指定的数据库

_LIT(KCntFile,"c:/private/100012a5/DBS_100065FF_Contacts.cbd");

CContactsDatabase* contactsDb= CContactsDatabase::OpenL(KCntFile);

CleanupStack::PushL(contactsDb);

//添加自己功能代码

CleanupStack::PopAndDestroy(contactsDb);//释放数据库

1.3、       新建通讯录条目

// 个人信息声明

_LIT(KForenameLabel,"Forename");//中文“名”

_LIT(KSurnameLabel,"Surname"); //中文“姓”

_LIT(KWorkPhoneLabel,"Work Phone");

_LIT(KForename,"Steve");

_LIT(KOtherForename,"Bob");

_LIT(KSurname,"Wilkinson");

_LIT(KWorkPhone,"+441617779700");

//以上定义的字符串,在以后例子中将直接使用,不再重新进行定义了

//打开默认数据库

CContactDatabase* contactsDb = CContactDatabase::OpenL();

CleanupStack::PushL(contactsDb);

// 建立一个新条目

CContactItem* contact = CContactCard::NewLC();

//创建一个新的文本存储类型的姓域

CContactItemField* field =

CContactItemField::NewLC(KStorageTypeText, KUidContactFieldFamilyName);

//将姓域建立与vCard的映射

field->SetMapping(KUidContactFieldVCardMapUnusedN);

//设置域标签

field->SetLabelL(KSurnameLabel);

//设置域值

field->TextStorage()->SetTextL(KSurname);

//把该域加入到新建的条目中

contact->AddFieldL(*field);

CleanupStack::Pop();

//添加文本存储类型的名域

field=CContactItemField::NewLC(KStorageTypeText, KUidContactFieldGivenName);

field->SetMapping(KUidContactFieldVCardMapUnusedN);

field->SetLabelL(KForenameLabel);

field->TextStorage()->SetTextL(KForename);

contact->AddFieldL(*field);

CleanupStack::Pop();

//添加文本存储类型的手机号码域

field=CContactItemField::NewLC(KStorageTypeText, KUidContactFieldPhoneNumber);

field->SetMapping(KUidContactFieldVCardMapTEL);

field->SetLabelL(KWorkPhoneLabel);

field->TextStorage()->SetTextL(KWorkPhone);

contact->AddFieldL(*field);

CleanupStack::Pop();

//把建立的新记录添加到数据库中

contactsDb->AddNewContactL(*contact);

contactsDb->SetOwnCardL(*contact);

CleanupStack::PopAndDestroy(2); // contact and contactsDb

1.4获取通讯录条目

//打开默认数据库

TInt  nCntCount = contactsDb->CountL();

//关闭默认数据库

1.5、       读取(遍历)通讯录条目

可以用TContactIter类(该类起到数据库操作中类似游标的作用)来遍历一个通信录数据库。这个类提供了一整套的函数,用于遍历所有的通信录项。所有的函数都用通信录项ID (TContactItemId) 进行操作,该ID 用于访问某个特定的通信录项。

// Open the default contacts database:

CContactDatabase* contactsDb = CContactDatabase::OpenL();

CleanupStack::PushL(contactsDb);

TContactIter iter(*contactsDb);

TContactItemId cardId;

//循环遍历

while( ( cardId = iter.NextL() ) != KNullContactId )

{

//读取相应项,这里之所以称其card,就是其实际相当于读一个完整的vCard条目

CContactItem* card = contactsDb->ReadContactL(cardId);

CleanupStack::PushL(card);

//添加自己功能代码

//……

contactsDb->CloseContactL(card->Id());

CleanupStack::PopAndDestroy(); // card

}

CleanupStack::PopAndDestroy(); // contactsDb

例5、       查找并更新通讯录条目

这个例子比较复杂,涉及的查找函数为FindAsyncL,该类函数实例有:

CContactIdArray * CContactDatabase::FindLC(const TDesC &aText, const CContactItemFieldDef *aFieldDef);

CIdleFinder * CContactDatabase::FindAsyncL(const TDesC &aText, const CContactItemFieldDef *aFieldDef, MIdleFindObserver *aObserver);

还有对应的FindInTextDefLC()和FindInTextDefAsyncL()各两组,具体参见sdk

下面是具体代码实例:

CContactDatabase*  iContactsDb = CContactDatabase::OpenL();

CleanupStack::PushL(iContactsDb);

CContactItemFieldDef*  iFieldDef = new (ELeave)CContactItemFieldDef();

CleanupStack::PushL(iFieldDef);

iFieldDef->AppendL(KUidContactFieldGivenName);

iFieldDef->AppendL(KUidContactFieldFamilyName);

_LIT(KFindToken, "Bond");

CIdleFinder * iFinder = iContactsDb->FindAsyncL( KFindToken, iFieldDef, this);

CleanupStack::PushL(iFinder);

if(iFinder->IsComplete())

{

if(iFinder->Error() == KErrNone)

{

CContactIdArray* result = iFinder->TakeContactIds();

CleanupStack:: PushL(result);

for(TInt i=0; i<result->Count(); i++)

{

TContactItemId cardId = (*result)[i];

CContactItem* ownCard = iContactsDb ->OpenContactL(cardId);

CleanupStack::PushL(ownCard);

TInt index =

ownCard->CardFields().Find(KUidContactFieldGivenName);

ownCard->CardFields()[index].TextStorage()->SetTextL(KOtherForename);

//提交所做的修改,如果这里不做更改可以调用CloseContactL直接关闭

//但是一旦用OpenContactL或OpenContactLX打开就必须调用两者之一关闭

iContactsDb ->CommitContactL(*ownCard);

CleanupStack::PopAndDestroy();// ownCard

}

CleanupStack::PopAndDestroy();//result;

}

}

CleanupStack::PopAndDestroy(3);// iContactsDb、iFieldDef、iFinder

例6、       导出所选通讯录条目到文件(vCard)

在这里,主要使用CContactDatabase类中ExportSelectedContactsL函数,关于该函数的定义可以查看SDK文档;而且在这里与前次遍历不一样的是,加了一个过滤器CCntFilter类,虽然取法仍然是所有通讯条目,但做法不一样,具体例程如下:

RFs fileSession;

//连接文件服务器

User::LeaveIfError(fileSession.Connect());

CleanupClosePushL(fileSession); //1

//打开默认数据库

CContactDatabase* contactDb = CContactDatabase::OpenL();

CleanupStack::PushL(contactDb); //2

//新建过滤器

CCntFilter* filter = CCntFilter::NewLC(); //3

filter->SetContactFilterTypeALL(EFalse);

//按vCard格式导出

filter->SetContactFilterTypeCard(ETrue);

//安装filter

contactDb->FilterDatabaseL(*filter);

//取出满足条件的记录数据项数组

CContactIdArray* exportContact = CContactIdArray::NewL(filter->iIds);

CleanupStack::PushL(exportContact); //4

RFile file;

//新建文件,aFileName是文件名字

file.Replace(fileSession,aFileName,EFileWrite);

CleanupClosePushL(file); //5

//声明文件流

RFileWriteStream outputStream(file);

CleanupClosePushL(outputStream); //6

TUid id;

id.iUid = KVersitEntityUidVCard;

//导出到文件

contactDb->ExportSelectedContactsL(id,*exportContact, aWriteStream, CContactDatabase::EExcludeUid);

CleanupStack::PopAndDestroy(6,contactDb);

Symbian S60独有通讯录操作API引擎

以上是适用于任何Symbian OS通讯录操作的方法,在S60平台SDK中nokia专门为我们建立了一个操作通讯录的引擎,以及相对应的产生了一些封装的类:

CPbkContactEngine(通讯录引擎类):如果已经存在一个缺省数据库,CPbkContactEngine::NewL()就连接到该数据库,否则创建该数据库。当然也可以传入文件名,打开一个指定的通讯录数据库,根据头文件cpbkcontactengine.h,他就是对CContactDatabase和观察器类MContactDbObserver封装了下并进行了一些优化,简便了我们操作时的一些代码,为此操作起来比较方便。

CPbkContactItem(通讯录条目类):该类头文件是CPbkContactItem.h,主要对通讯录条目类CContactItem的封装和优化,可以看出很多导出函数都是一致的。

TPbkContactItemField(域类):不用想也知道这个类是怎么来的了,该类的头文件tpbkcontactitemfield.h。有兴趣的可以去研究比照一下。

当然也有其他一些封装的类,只不过离通讯录模型比较远的,我们就不多展开了,在例子中看其使用。

例7、       新建通讯录条目

_LIT(KFName,"King");

_LIT(KLName,"Chai");

_LIT(KNumber,"13777777777");

//运用引擎打开默认通讯录

CPbkContactEngine* iPbkContactEngine = CPbkContactEngine::NewL();

CleanupStack::PushL(PbkContactEngine);//1

//新建一空通信录项

CPbkContactItem* contact = iPbkContactEngine->CreateEmptyContactL();

CleanupStack::PushL(contact); //2

//设置first name 域

TPbkContactItemField* field = contact->FindField(EPbkFieldIdFirstName);

CleanupStack::PushL(contact); //3

field->TextStorage()->SetTextL(KFName);

//设置last name 域

field = contact->FindField(EPbkFieldIdLastName);

field->TextStorage()->SetTextL(KLName);

//设置手机号码域

field = contact->FindField(EPbkFieldIdPhoneNumberMobile);

field->TextStorage()->SetTextL(KNumber);

//可以添加其他值域

//...

//修改后结果添加到数据库中,并返回这个通信录项的id,该id可以以后使用

TContactItemId Id = iPbkContactEngine->AddNewContactL(*contact);

CleanupStack::PopAndDestroy(3);

以上代码是否比例4的代码相对来说更简单些啊?

例8、       修改通讯录条目

实现修改和新建的代码类似,不同是你需要找到你要修改的通讯录条目aContactId,然后找到要修改的域进行修改,最后导入数据库。

_LIT(number,"13500000000");

TBuf<11> phonenumber(number);

CPbkContactEngine* iPbkContactEngine = CPbkContactEngine::NewL();

CleanupStack::PushL(PbkContactEngine);//1

//这里打开条目后加锁,以防其它客户端打开

CPbkContactItem* contact = iPbkContactEngine->OpenContactLCX(aContactId);

CleanupStack::PushL(contact); //2

//找到需要修改的field

TPbkContactItemField* field = contact->FindField(EPbkFieldIdPhoneNumberMobile);

CleanupStack::PushL(field); //3

//设置并确认修改

field->TextStorage()->SetTextL(phonenumber);

iPbkContactEngine ->CommitContactL(*contact);

CleanupStack::PopAndDestroy(2)

附录vCard:

手机应用开发中经常会遇到有关OBEX协议的问题,其实在通信录开发中也遵循这个协议,通信录中的数据是存在一个名叫vCard的载体里。vCard是一类电子名片,得到许多电子设备(如PDA和移动电话等)的支持。vCard的目的是:在这些设备之间用某些协议实现方便的通信录数据传递。可以将vCard编码成MIME规范(RFC 1521)所定义的明码文本。这种编码确保了各种vCard与限制为7位字符集(如在SMS消息中使用的编码)的传递编码的完全兼容。

一张vCard被格式化如下(说实话,下面这个vCard我也没看懂,有看懂的帮忙解释下):

BEGIN:VCARD

VERSION:2.1

N:Wilkinson;Steve

FN:Steve Wilkinson

ORG:EMCC Software Ltd.

TEL;WORK;VOICE:01617779700

ADR;WORK;ENCODING=QUOTED-PRINTABLE:;;108 Manchester

d.=0D=0ACarrington;Manchester;UK;M31 4BD;United Kingdom LABEL;WORK;ENCODING=QUOTED-PRINTABLE:108 Manchester Rd.=0D=0ACarrington=0D=0AManchester, UK M31 4BD=0D=0AUnited K= ingdom

EMAIL;PREF;INTERNET:steve.wilkinson@emccsoft.com

REV:20030909T164330Z

END:VCARD

通信录模型中的许多功能都与vCard的处理有关,以保证Symbian应用开发伙伴们能方便地编制符合电子名片及通讯录交换方面的工业标准的代码。

symbian os 通讯录引擎相关推荐

  1. Symbian OS通讯录

    Symbian OS通讯录模型 Symbian OS手机的通讯录采用文件方式存储,用symbian自己的说法就是通讯录数据库.每个Symbian OS手机都有一个默认的通讯录数据库,这个通讯录数据库在 ...

  2. Symbian OS 精要

    一般诀窍 1.'Symbian 开发师网络'提供大量信息资源,协助您为 Symbian OS 操作系统编写应用程序.您应经常访问 www.symbian.com/developer 网站以便获取最新的 ...

  3. Symbian OS应用编程图形篇之架构

    Symbian OS 9.5 版本中引入了ScreenPlay技术.ScreenPlay是一个新的图形架构,它可以使智能手机制造商充分利用软件性能的提升.硬件的加速及第三方的图形引擎.ScreenPl ...

  4. symbian OS 简单介绍

    symbian OS 就是symbian操作系统. 1 什么是symbian? 也被称作EPOC系统,这是最早由Psion公司开发的一个专门应用于手机等移动设备的操作系统.目前由诺基亚.爱立信.松下. ...

  5. Symbian OS

    目录·Symbian 概述 ·基于Symbian的UI ·Nokia开发的UI平台 ·UIQ开发的UI平台 ·Symbian智能手机 ·Series 60界面介绍 ·Symbian的特点 ·Symbi ...

  6. Symbian OS简介

    原文地址:http://blog.csdn.net/wh_xiexing/archive/2007/11/15/1887002.aspx 1.1.    Symbian系统简介        当前有很 ...

  7. Symbian OS SDKs简介(转)

    为Symbian OS开发应用程序的第一步就是获得一个SDK.Symbian OS SDKs支持基于Java和C++的开发. 这些SDK提供: 1.便于构建和开发Symbian OS应用程序的一组二进 ...

  8. Symbian OS C++程序员编码诀窍

    版权©属于诺基亚公司( 2003年),诺基亚公司保留全部权利 "诺基亚"及"诺基亚科技以人为本"是诺基亚公司的注册商标.Java和所有基于Java的标志是Sun ...

  9. Symbian OS on E65应用开发手记(3)——SDK注册及14天学习总结

    在环境搭建完成14天以后,今儿竟然神奇地提示我SDK已过期,需要注册--真吓人,你干吗我刚安装完的时候不提示我注册啊?折腾我!!!还以为我会从此找不到序列号,从此用不了了呢... 注册方法如下: 在对 ...

最新文章

  1. 作为国企程序员,是一种怎样的体验?
  2. Sharepoint项目周记一:关于开展MOSS项目的前期调查和需要解决的问题
  3. html-表单的应用
  4. Hello,Behavior
  5. 麦肯锡指出布局金融生态圈对中国国内银行意义重大
  6. ELK学习笔记之Elasticsearch启动常见错误
  7. 什么是5G?居然有人用漫画把它讲得如此接地气!
  8. Fintech生态报告:区块链是金融业革新的王牌技术
  9. vue电商网站后台管理系统模板
  10. 判断拐点的条件_拐点的定义
  11. 中国内地最高电影票房收入列表
  12. 计算机画图如何把二寸照片修改为一寸,win7使用自带画图工具把照片调整成2寸的方法...
  13. 华为手机计算机怎么开声音,怎么录音频-录屏录不到声音?华为的录屏功能了解一下!这才是正确的打开方式...
  14. Linux内核版本号的含义
  15. 关于谷歌浏览器加载不显示验证码的解决办法
  16. 08_Python算法+数据结构笔记-二叉搜索树查询/删除-AVL树旋转/插入/应用-贪心算法
  17. 一个码农关于足球的记忆
  18. cesium 模拟地球自转
  19. angular UI框架
  20. casio计算机按键,卡西欧四个按键功能

热门文章

  1. iptables nat 技术转发
  2. 数据分析师常用的数据分析方法有哪些?
  3. python字典遍历输出_详解Python字典的复制与遍历
  4. 计算机科学与技术0812和0775,计算机科学与技术考研,计算机科学学什么
  5. comsol图形无法即时显示问题
  6. 企业微信开发实战(一、相关说明及注册企业微信)
  7. 基于ISCSI共享存储的KVM高可用群集配置
  8. Linux配置网络信息(四种方法)
  9. 四年级计算机wps教案,四年级上册信息技术教案-《初识“WPS文字”》苏教版新版...
  10. wps两列数据分别作为xy轴_面对三维数据很慌张?气泡图了解一下