通信簿,电话簿

1.电话簿API也叫Contacts API,是SymbianOS的通信簿API在Series60上的实现.大部分通信簿引擎API与电话簿API是重复的,只有在电话簿API不能满足需要时才使用通信簿API.

2.Symbian OS手机的通讯录采用文件方式存储。 每个Symbian OS手机都有一个默认的通讯录数据库,在os7.0s中存在为c:/system/data/Contacts.cdb,在os9.0s中存在为c:/private/100012a5/DBS_100065FF_Contacts.cdb。

3.Symbian OS的手机通讯录在开发上的操作依靠Symbian OS通讯录模型(Contacts Model)实现。

    通讯录模型由通讯录数据库、通讯录条目(项)和通信录域三者组成.

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

4.Symbian OS将Contacts Model操作封装为几个类,主要有:

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

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

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

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

   (5).使用这些类需要包含一些头文件,如

       #include <CNTDB.H>  //for CContactDatabase
       #include <CNTITEM.H> //for CContactItem

       #include <CNTFIELD.H>//for CContactItemField
       #include <CNTFLDST.H>//for CContactTextField
       #include <CNTFILT.H> //for CCntFilter

       在.mmp文件中添加 LIBRARY cntmodel.lib

       另外需要添加一些能力: ReadUserData,WriteUserData

5.以下是对通讯录数据库的一些基本的操作:

(1).   打开和关闭数据库

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

 

    //打开默认数据库

    CContactDatabase* contactsDb = CContactDatabase::OpenL();

    CleanupStack::PushL(contactsDb);

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

    TInt numberOfContacts = contactsDb->CountL();

    //释放数据库

    CleanupStack::PopAndDestroy(contactsDb);

 

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

(2).  创建数据库

    CContactDatabase::CreateL()函数,如果该数据库已经存在,会以KErrAlreadyExists退出。而CContactDatabase::ReplaceL()函数结果总会创建或替换一个数据库,如果没有定义参数,这些函数将创建一个默认的数据库。CContactDatabase::FindContactFile()函数接受一个描述符,如果不存在默认数据库的话,该描述符就会返回该默认数据库的位置。在第三版中,这个函数的作用被ContactDatabaseExistsL()替代,它接受的参数类型是const的.

 _LIT(KDbFileName,"c:newdatabase.cdb");

 CContactDatabase* newDefaultContactDb;

 //是否存在默认数据库
 if(CContactDatabase::ContactDatabaseExistsL(KDbFileName)) //FindContactFile
 {
  newDefaultContactDb = CContactDatabase::ReplaceL(KDbFileName);
 }
 else
 {
  newDefaultContactDb = CContactDatabase::CreateL(KDbFileName);
 }

 CleanupStack::PushL(newDefaultContactDb);

 // 添加自己功能代码
 CleanupStack::PopAndDestroy(newDefaultContactDb);

 

结果在第三版模拟器运行时,会在/Epoc32/winscw/c/private/100012a5中创建DBS_100065FF_newdatabase.cdb

(3).  添加通讯录条目

    CContactDatabase* contactsDb = CContactDatabase::OpenL();
 CleanupStack::PushL(contactsDb);

 

 // 字符串声明
 _LIT(KForenameLabel,"Forename");//三个标签
 _LIT(KSurnameLabel,"Surname"); 

 _LIT(KWorkPhoneLabel,"Work Phone");
 _LIT(KForename,"Steve");//名,姓,电话号码
 _LIT(KSurname,"Wilkinson");
 _LIT(KWorkPhone,"+441617779700");

 

 // 建立一个新条目
 CContactItem* contact = CContactCard::NewLC();//CContactCard继续自CContactItem

 

 //创建一个新的文本存储类型的familyname域
 CContactItemField* field 

= CContactItemField::NewLC(KStorageTypeText, KUidContactFieldFamilyName);
 //将姓域建立与vCard的映射
 field->SetMapping(KUidContactFieldVCardMapUnusedN);
 //设置域标签
 field->SetLabelL(KSurnameLabel);
 //设置域值
 field->TextStorage()->SetTextL(KSurname);
 //把该域加入到新建的条目中
 contact->AddFieldL(*field); 
 CleanupStack::Pop();//*field的控制权交给了contact

 

 //添加文本存储类型的名域
 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(contact);

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

(4).  读取(遍历)通讯录条目

    使用TContactIter类(该类起到数据库操作中类似游标的作用)来遍历一个通信录数据库。它提供了一整套的函数,用于遍历所有的通信录项。所有的函数都用通信录项ID (TContactItemId) 进行操作,该ID 用于访问某个特定的通信录项。
 
 CContactDatabase* contactsDb = CContactDatabase::OpenL();
 CleanupStack::PushL(contactsDb);


 TContactIter iter(*contactsDb);
 TContactItemId cardId;

 

 RFileLogger log;
 log.Connect();
 log.CreateLog(_L("Log"),_L("Log.txt"),EFileLoggingModeAppend);

 

 //The count includes non-system template items
 TInt count=contactsDb->CountL();
 TInt templateCount=contactsDb->TemplateCount();
 log.WriteFormat(_L("count:%d"),count);
 log.WriteFormat(_L("templateCount:%d"),templateCount);


 //循环遍历
 while( ( cardId = iter.NextL() ) != KNullContactId )
 {
  //读取相应项,这里之所以称其card,就是其实际相当于读一个完整的vCard条目
  CContactItem* card = contactsDb->ReadContactL(cardId);
  CleanupStack::PushL(card);

 

  log.WriteFormat(_L("TContactItemId:%d"),cardId);

  //判断如果不是模板
  if (KErrNotFound==contactsDb->GetCardTemplateIdListL()->Find(card->Id()))
  {
   CContactItemFieldSet& fields=card->CardFields();
   TInt fieldCount=fields.Count();
   for (TInt i=0;i<fieldCount;i++)
   {
    CContactItemField& field=fields[i];

    //打印标签和值
    log.Write(field.Label());
    log.Write(field.TextStorage()->Text());
   }

   contactsDb->CloseContactL(card->Id());
   CleanupStack::PopAndDestroy(); // card
  }
 }

 log.CloseLog();
 log.Close();

 CleanupStack::PopAndDestroy();

(5).  查找并更新通讯录条目

   本实例采用查找函数FindAsyncL,该函数声明为:

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

   为了实现回调,把CContactDatabase* iContactsDb;CIdleFinder * iFinder; 定义为类的成员变量.

  void CContactEngine::FindContactL(MIdleFindObserver* aObserver)
  {
     iContactsDb = CContactDatabase::OpenL();

 

     CContactItemFieldDef*  iFieldDef = new (ELeave)CContactItemFieldDef();
     CleanupStack::PushL(iFieldDef);


     iFieldDef->AppendL(KUidContactFieldGivenName);
     iFieldDef->AppendL(KUidContactFieldFamilyName);


     _LIT(KFindToken, "Wilkinson");
     iFinder = iContactsDb->FindAsyncL( KFindToken, iFieldDef, aObserver);

 

     CleanupStack::PopAndDestroy();// iFieldDef
 }

再由观察者来调用如下函数,实现修改

void CContactEngine::EditContactL()
{
 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);
      _LIT(KGivenName,"weike");
      ownCard->CardFields()[index].TextStorage()->SetTextL(KGivenName);

 

      index = ownCard->CardFields().Find(KUidContactFieldFamilyName);
      _LIT(KFamilyName,"wang");
      ownCard->CardFields()[index].TextStorage()->SetTextL(KFamilyName);

 

      //提交所做的修改
      iContactsDb ->CommitContactL(*ownCard);
      //如果这里不做更改可以调用CloseContactL直接关闭
      //iContactsDb->CloseContactL(ownCard->Id());

 

      CleanupStack::PopAndDestroy();// ownCard
    }
    

    CleanupStack::PopAndDestroy();//result;
  }
 }
}

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

    使用了CContactDatabase类中ExportSelectedContactsL函数,与前次遍历方法不同,并且在取所有通讯条目前加了一个过滤器CCntFilter类,例程如下:

     void CContactEngine::ExportContactL(const TDesC& aFileName)
{
 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, outputStream, CContactDatabase::EExcludeUid);

 CleanupStack::PopAndDestroy(6);
}

使用时如: iContactEngine->ExportContactL(_L("c://mycards.txt"));

 

6.S60特有的通讯录操作API引擎

  nokia专门为S60平台SDK建立了一个操作通讯录的引擎,以及一些封装的类,主要有:

(1).CPbkContactEngine(通讯录引擎类):pbk是phone book的缩写,CPbkContactEngine即电话薄联系人引擎类。

CPbkContactEngine需要能力:ReadUserData WriteUserData ReadDeviceData WriteDeviceData
不然出错:kern-exec 0 错误,记得以前没能力是-46.

如果已经存在一个缺省数据库,CPbkContactEngine::NewL()

就连接到该数据库,否则创建该数据库。也可以传入文件名,打开一个指定的通讯录数据库.

    从它的头文件cpbkcontactengine.h可以看出,它是对CContactDatabase和观察器类MContactDbObserver封装了下并进行了一些优化,简便了我们操作时的一些代码,为此操作起来比较方便。

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

(3).TPbkContactItemField(域类):该类的头文件tpbkcontactitemfield.h。

 

使用这些类需要的能力有: ReadUserData WriteUserData ReadDeviceData WriteDeviceData

导入库 PbkEng.lib

(4)  新建通讯录条目

    _LIT(KFName,"andy");
 _LIT(KLName,"lau");
 _LIT(KNumber,"13794417723");

 //运用引擎打开默认通讯录
 CPbkContactEngine* iPbkContactEngine = CPbkContactEngine::NewL();
 CleanupStack::PushL(iPbkContactEngine);//1

 //新建一空通信录项
 CPbkContactItem* contact = iPbkContactEngine->CreateEmptyContactL();
 CleanupStack::PushL(contact); //2

 //设置first name 域
 TPbkContactItemField* field = contact->FindField(EPbkFieldIdFirstName);
 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(2);

(5).  修改通讯录条目

 _LIT(number,"13794417723");

 TBuf<11> phonenumber(number);

 CPbkContactEngine* iPbkContactEngine = CPbkContactEngine::NewL();
 CleanupStack::PushL(iPbkContactEngine);//1

 

 //需要提供一个通讯录条目id
 TContactItemId id(23);

 

 //这里打开条目后加锁,以防其它客户端打开
 CPbkContactItem* contact = iPbkContactEngine->OpenContactLCX(id); //aContactId

 //找到需要修改的field
 TPbkContactItemField* field = contact->FindField(EPbkFieldIdPhoneNumberMobile);

 //设置并确认修改
 field->TextStorage()->SetTextL(phonenumber);
 iPbkContactEngine ->CommitContactL(*contact);

 CleanupStack::PopAndDestroy(3);

7.

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值