Symbian OS通讯录模型
Symbian OS手机的通讯录采用文件方式存储,用symbian自己的说法就是通讯录数据库。每个Symbian OS手机都有一个默认的通讯录数据库,这个通讯录数据库在2nd和3rd两个版本手机中的位置是不同的,前者是c:/ system/data/Contacts.cdb,后者是c:/private/100012a5/DBS_100065FF_Contacts.cdb。不管怎么说两者都在内部闪存中,也就是跟优盘差不多的介质,由于symbian OS的文件系统暂时还没有仔细拜读过,所以具体差别暂不知,总之掉电不会失去就是了。
Symbian OS的手机通讯录在开发上的操作依靠Symbian OS通讯录模型(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、       打开和关闭数据库
CContactDatabase::OpenL()函数有两个重载函数。如果该函数没有给出一个参数,就打开默认的数据库。另一种情况是,应用软件设计师也可以传递一个有关数据库的路径和文件名,规定打开一个指定数据库。
//打开默认数据库
CContactDatabase* contactsDb = CContactDatabase::OpenL();
CleanupStack::PushL(contactsDb);
//取得当前数据库所有通讯条目数
TInt numberOfContacts = contactsDb->CountL();
//释放数据库
CleanupStack::PopAndDestroy(contactsDb);
要注意的是:某个通信录数据库并不具有Close()函数或类似的函数,否则我们压入清除栈时就得用CleanupClosePushL()函数了。
 
例2、       创建数据库
CContactDatabase::CreateL()函数与CContactDatabase::ReplaceL()函数之间的唯一差别就是:如果该数据库已经存在,前者会以KErrAlreadyExists退出。如前所述,如果没有定义参数,这些函数将创建一个默认的数据库。CContactDatabase::FindContactFile()函数给出了一个描述符,如果不存在默认数据库的话,该描述符就会返回该默认数据库的位置。
// If one is found, replace it with a new empty default database.
// If no default database is found, create a new one.
TFileName contactDbFilePath;
CContactDatabase* newDefaultContactDb;
//是否存在默认数据库
if(CContactDatabase::FindContactFile(contactDbFilePath))
{
 newDefaultContactDb = CContactDatabase::ReplaceL();
}
else
{
 newDefaultContactDb = CContactDatabase::CreateL();
}
CleanupStack::PushL(newDefaultContactDb);
// 添加自己功能代码
CleanupStack::PopAndDestroy(newDefaultContactDb);
注:以上代码负责创建一个空的默认数据库。
 
例3、       读取(遍历)通讯录条目
可以用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
 
 
例4、       新建通讯录条目
// 字符串声明
_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 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应用开发伙伴们能方便地编制符合电子名片及通讯录交换方面的工业标准的代码。

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/Max__Payne/archive/2008/07/08/2624776.aspx

Symbian OS通讯录相关推荐

  1. symbian os 通讯录引擎

    1.1通讯录模型 symbian os手机的通讯录采用文件方式存储,就是通讯录数据库.每个个symbian os手机都有一个默认的通讯录数据库.symbian os 的手机通讯录在开发上的操作依靠sy ...

  2. symbian OS 简单介绍

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

  3. Symbian OS

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

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

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

  5. Symbian OS 精要

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

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

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

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

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

  8. Symbian OS 初探

    Symbian OS 初探 2008-12-22 20:56 Symbian OS 初探 tombkeeper@xfocus,http://hi.baidu.com/tombkeeper 2005.1 ...

  9. [图文]Symbian OS简介(转)

    1.1 Symbian操作系统的起源和现状 Symbian成立于1998年,由爱立信.诺基亚.摩托罗拉和Psion共同出资筹建.1999年,松下公司加入Symbian.2000年,世界上第一款采用Sy ...

最新文章

  1. uniapp中动态添加及修改导航栏
  2. css selector list
  3. rust军用船指令_RUST物品指令清单(英文版)
  4. 我们距离“云”还有多远?
  5. 旷视 AI 飞跃 | 研究生联合培养计划
  6. 创建 linuxrc 文件
  7. mysql整站源码安装_MySQL入门01-MySQL源码安装
  8. ASP中FSO的神奇功能(1)
  9. “国际通信展”十年的印记
  10. 20200714每日一句
  11. 怎样用Python识别条形码?
  12. 响铃:滴滴“资源向安全和客服体系倾斜”的不完全建议
  13. 天水市2021年高考成绩查询,2021年天水高考状元是谁分数多少分,历年天水高考状元名单...
  14. 大型机汇编HLASM - HOOK ISPF命令START(一)
  15. 从摩斯密码到UTF-8
  16. phy 驱动与 switch 驱动
  17. ITU-R BT.656和ITU-R BT.601
  18. python---做一个恶搞程序
  19. 3D地形编程——之GeoMipMap基础(1)
  20. linux cdc设备驱动,kernel linux 3.5使用USB CDC ACM驱动

热门文章

  1. 2020车载凯立德懒人包下载_华为HarmonyOS App开发工具DevEco Studio下载安装及第一个HarmonyOS App实战教程...
  2. PROFINET通信协议网关在汽车行业的应用介绍(内附详细说明)
  3. 多任务学习在推荐中的探索
  4. SIEMENS/西门子1200 总线控制V90伺服程序模板
  5. 灰点相机Spinnaker sdk的安装使用(一)环境配置
  6. 路由守卫 /路由拦截
  7. ip和端口号的正则表达式
  8. 单片机中代码生成.a文件
  9. 中国城市三级联动数据
  10. linux下的c开发工具,4.3.2 Linux下的C开发工具