首 页 | 新 闻 | Symbian | Android| Windows Mobile | J2ME | 下载中心 | 游戏策划招聘与求职 | 购书指南 | 视频教程
您现在的位置: 开发视界 >> Symbian >> Symbian开发 >> 正文
S60平台:Bluetooth API开发伙伴指南——服务搜索
作者:姜 译    文章来源:诺基亚    更新时间:2007-3-19 21:30:09
此文档为开发视界翻译转载者请注明出处(开发视界 www.sf.org.cn)否则追究法律责任
四、服务搜索
当得知了可用的设备和其地址的时候,客户端应用程序就向所提供的设备进行询问可提供什么服务。如果一个设备的可用的服务已经确定,客户端应用程序还将继续查询更多的信息。包括所提供的服务的属性。Symbian操作系统提供了服务搜索代理开发接口实现服务搜索。
本段将介绍Symbian蓝牙接口的很多新的部分。也将对第1章提到的定义作详细的解释。但是,本资料的目的是说明开发人员如何使用Symbian开发接口开发应用程序。关于蓝牙协议方面的信息,请参考http://www.bluetooth.org/spec/

1、CSdpAgent 和 MSdpAgentNotifier 类
使用蓝牙在一个微型网中搜索服务是一件非常耗费时间的事情。Symbian操作系统提供了一个异步的开发接口用于执行服务的搜索。因为该客户端应用程序是异步的,因此要求客户端应用程序必须提供回调函数。这些函数将指向那些搜索功能函数。
Symbian系统的蓝牙接口提供了一个搜索类叫MSdpAgentNotifier,该类定义了一些搜索功能需要客户端应用程序来执行。
所有的搜索请求都提交给CSdpAgent类,这个类在btsdp.h头文件中定义。CSdpAgent的公共接口代码如下所示:
class CSdpAgent : public CBase
{
public:
IMPORT_C static CSdpAgent* NewL(MSdpAgentNotifier& aNotifier,
const TBTDevAddr& aDevAddr);
IMPORT_C static CSdpAgent* NewLC(MSdpAgentNotifier& aNotifier,
const TBTDevAddr& aDevAddr);
IMPORT_C ~CSdpAgent();
IMPORT_C void SetRecordFilterL(const CSdpSearchPattern& aUUIDFilter);
IMPORT_C void SetAttributePredictorListL(const
CSdpAttrIdMatchList& aMatchList);
IMPORT_C void NextRecordRequestL();
IMPORT_C void AttributeRequestL(TSdpServRecordHandle aHandle,
TSdpAttributeID aAttrID);
IMPORT_C void AttributeRequestL(TSdpServRecordHandle aHandle,
const CSdpAttrIdMatchList& aMatchList);
IMPORT_C void AttributeRequestL(MSdpElementBuilder* aBuilder,
TSdpServRecordHandle aHandle, TSdpAttributeID aAttrID);
IMPORT_C void AttributeRequestL(MSdpElementBuilder* aBuilder,
TSdpServRecordHandle aHandle, const CSdpAttrIdMatchList& aMatchList);
IMPORT_C void Cancel();

};
CSdpAgent创建的时候必须指定一个MSdpAgentNotifier 搜索对象和蓝牙设备的地址。这个地址就是客户端想要搜索的蓝牙地址。搜索类MSdpAgentNotifier 定义在btsdp.h头文件中。
1)在客户端应用程序开始搜索可用服务以前,必须先创建一个实例运行MSdpAgentNotifier接口
MSdpAgentNotifier这个函数在第二章中已经介绍,其用于指定一个服务的序号。在远程SDP数据库中存储的所有服务记录中,任何包含这些序号的服务都可以被搜索到。
而且,创建CSdpAgent类的实例必须保证确认远程蓝牙的地址和创建一个对象运MSdpAgentNotifier接口。
一个客户端应用程序可以使用CSdpAgent的SetRecordFilterL 功能对其感兴趣的服务进行设置。这个功能于CSdpSearchPattern 对象相关。

2、运行服务搜索
客户端应用程序只需要调用CSdpAgent的NextRecordRequestL函数即可启动搜索过程。这将启动一个异步的搜索。操作系统将告知应用程序过程启动MSdpAgentNotifier类。
当服务搜索完成的时候,将调用MSdpAgentNotifier::NextRecordRequestComplete函数。他的参数指定了一个错误代码(aError),一个服务基础句柄(aHandle)和一个整形值(aTotalRecordsCount)。错误代码将包含标准的Symbian操作系统错误代码中的一个比如KErrNOne。这说明搜索操作成功。服务记录句柄将记录符合搜索过滤参数的记录。最后,整型数将记录符合搜索条件的服务的数量。

3、运行属性查询
NextRecordRequestComplete 启动的时候,客户端应用程序将向远程设备询问更多服务记录信息。
CSdpAgent的AttributeRequestL 函数代表属性搜索的开始。AttributeRequestL函数将接受或者搜索ID,无论是一个还是多个。
如果要指定一个ID的集合,需要使用CSdpAttrIdMatchList类,在第二章中提到,这个类允许客户端应用程序指定ID的范围。
用于开始属性搜索的AttributeRequestL函数也是异步的。每次针对不同的参数寻找服务的时候,操作系统都将启动一次MSdpAgentNotifier::AttributeRequestResult函数。
当所有符合搜索参数的属性都查找到后,MSdpAgentNotifier::AttributeRequestComplete启动。

4、蓝牙对话
S60第三版SDK提供了一个蓝牙对话。在这个对话里面,CChatBtServiceSearcher实际上运行的是MSdpAgentNotifier接口。该内容定义在series60Ex\Chat\inc\ChatBtServiceSearcher.h 头文件中。
CChatBtServiceSearcher既运行MSdpAgentNotifier接口也包含CSdpAgent 对象。CChatBtServiceSearcher 既负责发布搜索请求,也处理操作系统的反馈。
CChatBtServiceSearcher 类的内容可以从series60Ex\Chat\src\ChatBtServiceSearcher.cpp 中找到。其代码的结构与下面的相似。
FindServiceL函数说明了搜索服务初始化的过程。
void CChatBtServiceSearcher::FindServiceL( TRequestStatus& aObserverRequestStatus )
{
if ( !iResponse().IsValidBDAddr() )
{
User::Leave( KErrNotFound );
}
iHasFoundService = EFalse;
// delete any existing agent and search pattern
delete iSdpSearchPattern;
iSdpSearchPattern = NULL;
delete iAgent;
iAgent = NULL;
iAgent = CSdpAgent::NewL( *this, BTDevAddr() );
iSdpSearchPattern = CSdpSearchPattern::NewL();
iSdpSearchPattern->AddL( ServiceClass() );
// return code is the position in the list that the UUID is
// inserted at and is intentionally ignored
iAgent->SetRecordFilterL( *iSdpSearchPattern );
iStatusObserver = &aObserverRequestStatus;
iAgent->NextRecordRequestL();
}
CChatBtServiceSearcher::NextRecordRequestComplete函数用于处理服务记录查询的请求。
void CChatBtServiceSearcher::NextRecordRequestComplete(TInt aError, TSdpServRecordHandle aHandle, TInt aTotalRecordsCount)
{
其首先确定应用程序并没有接受到所有匹配的记录,而且要确保查询没有错误。
if ( aError == KErrEof )
{
Finished();
return;
}
if ( aError != KErrNone )
{
iLog.LogL( KErrNRRCErr, aError );
Finished( aError );
return;
}
if ( aTotalRecordsCount == 0 )
{
HBufC* errNRRCNoRecords = StringLoader
::LoadLC ( R_CHAT_ERR_NRRC_NO_RECORDS );
iLog.LogL( *errNRRCNoRecords );
CleanupStack::PopAndDestroy ( errNRRCNoRecords );
Finished( KErrNotFound );
return;
}
// Request its attributes
如果没有任何错误但是没有任何服务记录处理,应用程序将发送属性请求获取更多信息。
iAgent->AttributeRequestL( aHandle, KSdpAttrIdProtocolDescriptorList );
CChatBtServiceSearcher::AttributeRequestResult 用于处理原始的属性请求。他将分析属性值确定是否搜索到相关服务。
void CChatBtServiceSearcher::AttributeRequestResultL(
TSdpServRecordHandle /*aHandle*/,
TSdpAttributeID aAttrID,
CSdpAttrValue* aAttrValue )
{
__ASSERT_ALWAYS( aAttrID == KSdpAttrIdProtocolDescriptorList,
User::Leave( KErrNotFound ) );
TChatSdpAttributeParser parser( ProtocolList(), *this );
// Validate the attribute value, and extract
//the RFCOMM channel
aAttrValue->AcceptVisitorL( parser );
if ( parser.HasFinished() )
{
// Found a suitable record so change state
iHasFoundService = ETrue;
}
}
void CChatBtServiceSearcher::AttributeRequestComplete( TSdpServRecordHandle aHandle,
TInt aError )
{
TRAPD(error,AttributeRequestCompleteL( aHandle, aError ));
if ( error != KErrNone )
{
Panic(EChatBtServiceSearcherAttributeRequestComplete);
}
}
相关文章:
AO 框架简介
蓝牙API指南
S60平台:Bluetooth API开发伙伴指南——搜索和发布
S60平台:Bluetooth API开发伙伴指南——设备搜索
S60平台:Bluetooth API开发伙伴指南——蓝牙开发接口V2的结构
S60平台:Bluetooth API开发伙伴指南——常用蓝牙数据类型
S60平台:Bluetooth API开发伙伴指南——蓝牙的结构概述
S60平台:Bluetooth API开发伙伴指南——介绍
 

站点地图 | 加入收藏 | 联系站长 | 广告服务 |
QQ:280529124  Tel:0592-8271361 辽ICP备05021703号