Chinaunix首页 | 论坛 | 博客
  • 博客访问: 212999
  • 博文数量: 43
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 25
  • 用 户 组: 普通用户
  • 注册时间: 2015-09-27 21:31
文章分类
文章存档

2017年(1)

2016年(39)

2015年(3)

我的朋友

分类: Java

2016-06-19 14:15:52

原文地址:蓝牙开发(入门) 作者:linux_wuliqiang

 
 越来越多的移动手机开始支持java应用,应用于无线蓝牙技术标准的java APIs(JABWT),由JSR 82 规范定义,支持快速开发便捷、及用途广泛的蓝牙应用。无线设备生产商已对JABWT规范做出反应,他们宣布移动手机和其它产品将支持JABWT应用。

    本文我们首先介绍在移动设备上进行java开发的基本原理,然后描述如何为蓝牙通讯编写java应用。

    蓝牙 API

    蓝牙 API依赖java通用连接框架,一直一来这成为java 蓝牙API应用的一个局限。但是,人们建议将GCF加入到J2SE中。Java蓝牙API使得访问更多的系统成为可能。

    Java蓝牙API定义了两个包:一个是Java蓝牙API的核心javax.bluetooth,另一个是用于对象的javax.obex(OBEX)。

    根据JSR 82 规范,所有潜在蓝牙系统都必须支持蓝牙控制中心(BCC),该控制中心是一个控制面板,它的作用类似于可以让用户或OEM给堆栈中的某些配置参数定义具体值得应用程序,特别是,它将应用于堆栈初始化中。

    任何蓝牙应用都有以下这些组件:堆栈初始化组件,设备管理组件,设备发现组件,服务发现组件和通讯组件。

    堆栈初始化

    在开始无线通讯之前,你需要以销售商预订的方式初始化蓝牙设备。(具体的堆栈初始化步骤超出了蓝牙API规范的范围。)

    在一篇关于java与蓝牙技术起步的java.net文章中,Bruce Hopkins(java与蓝牙技术的作者)向我们介绍了在Atinav java蓝牙开发平台上是如何通过一系列设置完成初始化工作的。(见列表A),在JSR 82规范不包含这些调用,这一点很重要,因为其它的JSR82实现可能包括其它的初始化堆栈的方式。

    设备管理

    JSR82规范介绍了用于设备管理的两个类:LocalDevice 和 RemoteDevice.

    LocalDevice 允许你请求获得蓝牙设备的静态信息。它依靠javax.bluetooth.DeviceClass类来获得设备类型和它所提供的服务类型。

    RemoteDevice可用来获得蓝牙邻近区的设备信息(例如,某个远程蓝牙设备的地址)。它可以代表一台远程设备(例如,一台在可到达范围内的设备),并提供相应的方法来获得关于这台设备的有关信息,包括它的蓝牙地址名称

    每个蓝牙设备有一个唯一的硬件地址,像计算机的MAC地址一样。你可以设定设备发现的级别,通过调用LocalDevice 对象中的setDiscoverable()方法可以使得其它蓝牙设备发现当前设备。(见列表B)

    设备发现

    无线设备需要一种机制来允许它们发现其它的设备并访问它们的功能。核心蓝牙API的DiscoveryAgent 类和DiscoveryListener接口提供了需要的发现服务。有三种方式获得可访问设备列表。 DiscoveryAgent.startInquiry()方法可将设备设置为查询模式,为了充分利用这种模式,应用必须要指定一个事件监听器来对与查询相关的事件作出反应。当查询完成或取消时,会调用DiscoveryListener.inquiryCompleted()方法。

    如果一台设备不想等待发现其它的设备,可以使用DiscoveryAgent.retrieveDevices()方法来获得一个已经存在的列表。该方法或者返回一个在前面的查询中发现的设备列表,或者返回一个预知的设备列表,这些设备是由本地设备提前告诉蓝牙控制中心的它经常联系的设备。返回那种列表取决于传递的参数。列表C演示了最简单的一种方式,当检测到一台新的蓝牙设备时,对象需要使用DiscoveryAgent通过DiscoveryListener接口通知你。

    服务发现

    服务发现允许你发现附近的服务,而不管哪一台设备提供的该服务。DiscoveryAgent提供的方法可以用来发现蓝牙服务设备上的服务,并初始化服务发现事务。在服务可以被发现以前,必须首先在蓝牙服务设备上注册或广播该服务服务设备负责完成很多任务,包括创建描述所提供的服务的服务记录,接受来自客户端的连接,向服务设备的服务发现数据库(SDDB)添加新的服务记录。总之,它的工作类似于web。列表D是服务注册的一个例子。

    通讯

    两台设备必须共享通用的通讯才能通讯。为了应用能够访问更多的蓝牙服务,蓝牙java API提供了这样一个机制,它允许连接到使用RFCOMM, L2CAP, 或 OBEX的任何服务。如果服务使用了位于上面协议之上其它的协议(例如TCP/IP),只有在应用中利用CLDC通用连接框架实现额外的协议,才可以访问该服务。

    用于服务记录的URL包括数字和符号,大体是这样的结构:

    btspp://508031205080110F1B1B1D1C100:8.它的意思是客户应该使用蓝牙串口框架来建立到地址为508031205080110F1B1B1D1C100的设备的8号服务。设备地址和计算机的物理地址相似,列表E显示了简单的RFCOMM连接。

   



**********************************************************************************
**********************************************************************************
 蓝牙是一种低成本、短距离的无线通信技术。对于那些希望创建个人局域网(PANs)的人们来说,蓝牙技术已经越来越流行了。每个个人局域网都在独立设备的周围被动态地创建,并且为蜂窝式电话和PDA等设备提供了自动连接和即时共享数据的能力。
  
  为了在平台上开发支持蓝牙技术的软件,JCP定义了JSR82标准--蓝牙无线技术APIs(JABWT)。
  
  在这篇文章中,我将介绍一些关于蓝牙技术的背景,概述一下支持蓝牙技术的MIDlet应用程序的典型要素,然后介绍给你核心的Java蓝牙APIs。最后我们展示一些代码来演示如何使用这些APIs。
  
  实际上JSR82定义了两个独立的可选包:核心蓝牙API和对象(OBEX)API。这篇文章将对这两个中更为普遍的部分--核心蓝牙包javax.bluetooth进行详细地阐述,而OBEX API(对象),我们留到以后去讨论。
  
  蓝牙无线电技术基于在工业、科学以及医学(ISM)上公用的2.45GHz开放频段,这一频段无需授权并全球通用。当蓝牙设备互相连接时,他们将组成一个微微网(piconet),即以一个主设备和最大7个从设备的形式动态创建网络。蓝牙也支持piconet网之间的连接:当一个piconet中的主设备成为另一个piconet的从设备时,piconet与piconet间将形成桥接。
  
  蓝牙栈提供了一组的高层和API以完成发现服务和模拟串行I/O,还有一个关于包分割和重组的低层以及多路技术协议和质量服务。蓝牙互操作性profiles--不要与J2ME profiles搞混--它是用来描述跨平台互操作性和一致性需求的。
  
  蓝牙互操作性profiles包括三方面内容通用访问profile(GAP)定义了设备管理功能性;服务发现应用profiles定义了服务发现方面的内容串口profiles定义了互操作设备和模拟串口电缆的能力。你可以通过蓝牙规范(Bluetooth specification)学习这些和其它的profiles。蓝牙栈包含一个软件栈来映射一个固件栈(firmware),由图1所示:
   
  图片1:蓝牙协议栈
  
  JSR82揭示了蓝牙软件栈给Java平台的开发者。其中引起我们兴趣的是服务发现协议(SDP),用来模拟串口的串口profile RFCOMM,向上层协议提供诸如分割和重组等导向性连接的数据转换操作的逻辑链路控制及适配profile(L2CAP),以及多路技术协议。注意 JABWT不支持无连接L2CAP。
  
  JABWT也包括对象交换API。OBEX也是高层API,它用来交换对象数据,诸如电子商业卡和日历标签之间以vCard和vCalendar的格式进行数据传输。在蓝牙上,对象交换通过RFCOMM发生。OBEX在最开始时是由红外(IrDA)引入的,并且它可以在IrDA协议、TCP/IP或者是其他协议的顶层实现。
  
  典型的蓝牙应用程序实例
  
  一个开启蓝牙功能的应用可以作为一个服务端或是一个客户端--一个服务的提供者或是消费者,或者它可以作为一个真正的点对点终端同时表现出服务和客户的行为。图2所示一个蓝牙规范用例:
   
  图2:一个典型的具有蓝牙功能的实际用例
  
  对这些用例的简要介绍:
  
  .初始化--所有具备蓝牙功能的应用程序必须先要初始化蓝牙栈?lt;br>  
  .客户端--一个客户对远端服务进行消费。首先它要发现所有附近的设备,然后对于每一个发现的设备搜索它感兴趣的服务。
  
  .服务端--一个为客户端提供服务的。它在服务发现数据库(SDDB)中对客户端进行注册,对他们进行有效广播。然后等待引入的连接,在他们进入时接受他们并为他们提供服务。最后,当不再需要服务时,应用程序会在服务发现数据库(SDDB)中将他们移除。图三:用例中参与活动的图表:
   
  图 3: 蓝牙应用程序活动图
  
  蓝牙应用程序中的元素
  
  图4显示了在MIDlet中一个典型蓝牙功能应用程序中的一些元素:
   
  图4: 具有蓝牙功能的 MIDlet (高端组织)
  
  中间的是核心应用程序My Bluetooth MIDlet,它扩展自javax.microedition.midlet.MIDlet。没有显示出来的还有MIDlet中实现的 javax.microedition.lcdui.CommandListener以监听从用户接口中输入的命令。应用程序使用的剩余的类和接口都包含在了蓝牙规范中,像设备发现和服务,连接和服务消费,还有广播和提供服务。
  
  使用诸如MVC等设计模式是很好的实践。MVC把应用程序分解成用户接口(视图),应用程序行为和导航(控制器),以及数据(模型),当然在我们的案例中还要加上蓝牙API的支撑类和接口。像将分离的客户端、服务端行为构建成独立的类以便以后可以重用这些组件,也是很好的设计。
  
  Java蓝牙API核心概述
  
  JSR82需求的"最小公分母"是受限连接设备配置(CLDC),可靠连接设备配置(CDC)是CLDC的超集,所以JABWT可以同时在CLDC和CDC上实现,简要地说,你可以在使用任何J2ME profile的上使用JABWT。在javax.bluetooth中我们可以发现,Java蓝牙API可以被分解为三个部分,在下面我们将讨论到它们:发现、设备管理和通信。
 
  蓝牙发现API
  
  客户端程序使用蓝牙发现API以搜索在其附近的设备和服务。服务代理类(DiscoveryAgent)同时支持设备与服务的发现。当设备和服务被发现时,想得到通知的客户端应用程序必须实现并注册 DiscoveryListener接口,这个接口定义了设备发现通知和服务发现通知的回调。发现代理(DiscoveryAgent)与蓝牙客户端应用程序之间是典型的一对一的关系:
   
  图 5: DiscoveryAgent类和DiscoveryListener接口
  
  设备发现API
  
  你使用DiscoveryAgent类的"设备发现"方法来开始和取消设备发现:
  
  .retrieveDevices()重新获得已经发现或者附近的已知设备
  
  .startInquiry() 启动发现附近设备,也叫inquiry
  
  .cancelInquiry()取消当前进行的任何请求
  
  蓝牙发现代理在请求阶段的不同时候会分别调用DiscoveryListener(发现监听器)不同的回调方法:
  
  .deviceDiscovered() 指出是否有设备被发现。
  
  .inquiryCompleted() 指出是否请求已经成功、触发一个错误或已被取消。
  
  在图6中的状态图表阐明了设备发现的状态改变结束于相应的回调方法的返回。
   
  图 6: 设备发现状态表
  
  设备发现以调用startInquiry()函数开始。在请求进行时,蓝牙发现代理会在适当的时候调用回调方法DeviceDiscovered()和inquiryCompleted()。
  
  服务发现API
  
  你可以使用发现代理的服务发现方法来开始或取消服务发现:
  
  . selectService()启动服务发现搜索。(根据API手册应为尝试定位一个服务)
  
  . searchServices()启动服务发现搜索。
  
  . cancelServiceSearch()取消在正在进行中的任何的服务发现搜索操作。蓝牙发现代理在服务发现阶段的不同时候会分别调用DiscoveryListener的服务发现回调方法:
  
  . servicesDiscovered() 表示是否服务已被发现。
  
  . serviceSearchCompleted()表示服务发现是否已经完成。
  
  图7阐明了服务发现的状态改变结束于DiscoveryListener的回调方法的返回。
   
  图 7: 服务发现状态图表
  
  服务发现开始于对searchServices()的调用。当服务搜索进行时,蓝牙发现代理会在适当的时候回调servicesDiscovered()和 serviceSearchCompleted()方法。
  
  除了DiscoveryAgent和DiscoveryListener了,你在服务发现过程中还要使用到的类有UUID,ServiceRecord以及DataElement等。
  
  UUID类在蓝牙中,每个服务服务属性都唯一地由"全球唯一标识符"(UUID)来校验。正如它的名字所暗示的,每一个这样的标识符都要在时空上保证唯一。UUID类可表现为短整形(16或32位)和长整形(128位)UUID。
  
  他提供了分别利用String和16位或32位数值来创建类的构造函数,提供了一个可以比较两个UUID(如果两个都是128位)的方法,还有一个可以转换一个UUID为一个字符串的方法。UUID实例是不可改变的(immutable),只有被UUID标示的服务可以被发现。
  
  在Linux下你用一个命令uuidgen -t可以生成一个UUID值;在下则执行命令uuidgen 。UUID看起来就像如下的这个形式:2d266186-01fb-47c2-8d9f-10b8ec891363。当使用生成的UUID去创建一个 UUID对象,你可以去掉连字符。
  
  SDDB和ServiceRecord接口
  
  在服务发现的中心是服务发现数据库(SDDB)服务发现协议(SDP)。SDDB由蓝牙实现负责维护的数据库。它包含了服务记录(service records),后者代表了对客户端有效的服务。SDP对于基于JABWT应用程序来说是透明的;可以这么说,SDP是用于服务发现的。为重新获取服务纪录,一个本地设备SDP客户端会向一个远端设备上SDP服务器发出请求。
   
  图 8: SDDB
  
  每一笔服务记录都会由一个ServiceRecord的实例来表现。这个记录包含了描述服务细节的属性。这个类提供了几种有用的方法:
  
  .getAttributeIDs() 和 getAttributeValue()方法返回服务记录的属性。
  
  .getConnectionURL()方法获取链接的URL
 
*******************************************************************************
 
阅读(4535) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~