蓝牙是一种低成本、短距离的无线通信技术。对于那些希望创建个人局域网(PANs)的人们来说,蓝牙技术已经越来越流行了。每个个人局域网都在独立设备的周围被动态地创建,并且为蜂窝式电话和PDA等设备提供了自动连接和即时共享数据的能力。
    为了在Java平台上开发支持蓝牙技术的软件,JCP定义了JSR82标准--Java蓝牙无线技术APIs(JABWT)。
    在这篇文章中,我将介绍一些关于蓝牙技术的背景,概述一下支持蓝牙技术的MIDlet应用程序的典型要素,然后介绍给你核心的Java蓝牙APIs。最后我们展示一些代码来演示如何使用这些APIs。
    实际上JSR82定义了两个独立的可选包:核心蓝牙API和对象交换(OBEX)API。这篇文章将对这两个中更为普遍的部分--核心蓝牙包javax.bluetooth进行详细地阐述,而OBEX API(对象交换),我们留到以后去讨论。

背景
    篮牙技术由蓝牙兴趣小组发展,其包括:
        .无线电技术
        .协议栈
        .互操作性profiles
    蓝牙无线电技术基于在工业、科学以及医学(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:一个典型的具有蓝牙功能的实际用例
    对这些用例的简要介绍:
        .初始化--所有具备蓝牙功能的应用程序必须先要初始化蓝牙栈。
        .客户端-- 一个客户对远端服务进行消费。首先它要发现所有附近的设备,然后对于每一个发现的设备搜索它感兴趣的服务。
        .服务器端-- 一个为客户端提供服务的服务器。它在服务发现数据库(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值;在Windows下则执行命令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地址给服务器主机来收集服务记录。
    .getHostDevice() 方法获取提供服务的远端设备。
    .populateRecord() 和 setAttributeValue()方法用来设置设备记录的属性。
    .setDeviceServiceClasses()方法设置服务的类。
图9显示了蓝牙本地设备和远端设备,以及SDDB还有服务记录之间的关系:

图 9: 使用远端设备,SDDB和服务记录进行服务发现

蓝牙中文API文档的更多相关文章

  1. Android多媒体--MediaCodec 中文API文档

    *由于工作需要,需要利用MediaCodec实现Playback及Transcode等功能,故在学习过程中翻译了Google官方的MediaCodec API文档,由于作者水平限制,文中难免有错误和不 ...

  2. Bootstrap FileInput中文API文档

    Bootstrap FileInput中文API整理 这段时间做项目用到bootstrap fileinput插件上传文件,在用的过程中,网上能查到的api都不是很全,所以想着整理一份比较详细的文档, ...

  3. POI中文API文档

    一. POI简介 Apache POI是Apache软件基金会的开放源码函式库,POI提供API给Java程序对Microsoft Office格式档案读和写的功能. 二. HSSF概况 HSSF 是 ...

  4. jquery.Inputmask 插件用法(中文API文档)

      jquery.Inputmask 可以算是input文本输入限制的神器了,内部融合了多种输入限制, 如金额,电话号码,身份证号,网关等..,并且还可以自定义规则. inputmask 据说最早起源 ...

  5. JspSmartUpload 简略中文API文档

    感谢原文作者:~数字人生~ 原文链接:https://www.cnblogs.com/mycodelife/archive/2009/04/26/1444132.html 一.JspSmartUplo ...

  6. Java-UrlRewrite中文api文档

    安装 1. 下载jar包, 并加入到WEB-INF/lib下 2. 在WEB-INF/web.xml中增加下面的配置 <filter> <filter-name>UrlRewr ...

  7. [转]Sequelize 中文API文档-4. 查询与原始查询

    本文转自:https://itbilu.com/nodejs/npm/VJIR1CjMb.html Sequelize中有两种查询:使用Model(模型)中的方法查询和使用sequelize.quer ...

  8. Sequelize 中文API文档-1. 快速入门、Sequelize类

    1. https://itbilu.com/nodejs/npm/VkYIaRPz-.html#api-init 2. http://docs.sequelizejs.com/manual/tutor ...

  9. (转载)中文Appium API 文档

    该文档是Testerhome官方翻译的源地址:https://github.com/appium/appium/tree/master/docs/cn官方网站上的:http://appium.io/s ...

随机推荐

  1. CentOS 7.4 下安装 Nginx

    CentOS 7.4 下安装 Nginx 安装所需环境 Nginx 是 C语言 开发,建议在 Linux 上运行,当然,也可以安装 Windows 版本,本篇则使用 CentOS 7 作为安装环境. ...

  2. 戴尔笔记本Inspiron 7560(灵越) 加装固态硬盘从选购固态硬盘到系统迁移到设置SSD为第一启动(受不了了,网上的教程就没有完整的)

    菜鸡我的笔记本为戴尔灵越Inpsiron 7560,其实Inspiron 15 7560 和Inspiron 7560是同一个型号. 电脑拆了安过内存条,换过电池,现在又加了一块固态硬盘. 因为不想安 ...

  3. Centos的 mysql for python的下载与安装

    mysql-python的安装包下载地址:http://sourceforge.net/projects/mysql-python/files/latest/download linux环境是 Cen ...

  4. #、##和__VA_ARGS__

    转自:http://www.cnblogs.com/zhujudah/admin/EditPosts.aspx?opt=1 1.#假如希望在字符串中包含宏参数,ANSI C允许这样作,在类函数宏的替换 ...

  5. J2EE技术架构

    一.简介 J2EE(Java 2 Platform, Enterprise Edition)是一个为大企业主机级的计算类型而设计的Java平台.Sun微系统(与其工业伙伴一起,例如IBM)设计了J2E ...

  6. WQS二分题集

    WQS二分,一种优化一类特殊DP的方法. 很多最优化问题都是形如“一堆物品,取与不取之间有限制.现在规定只取k个,最大/小化总收益”. 这类问题最自然的想法是:设f[i][j]表示前i个取j个的最大收 ...

  7. C++中的读入输出优化及清新脱俗的宏命令

    C和C++有了#define,从此它就变了模样 宏命令就是#define,#if,#error之类的 本文主要介绍宏命令和相关的骚操作 读入输出优化 inline int read() { int a ...

  8. 【二分答案】【最大流】[HNOI2007]紧急疏散EVACUATE

    [HNOI2007]紧急疏散EVACUATE 题目描述 发生了火警,所有人员需要紧急疏散!假设每个房间是一个N M的矩形区域.每个格子如果是'.',那么表示这是一块空地:如果是'X',那么表示这是一面 ...

  9. 抽象类(abstract class)和接口(interface)的异同

    抽象类和接口都不能够实例化,但可以定义抽象类和接口类型的引用.一个类如果继承了某个抽象类或者实现了某个接口都需要对其中的抽象方法全部进行实现,否则该类仍然需要被声明为抽象类. 接口比抽象类更加抽象,因 ...

  10. Educational Codeforces Round 9 D. Longest Subsequence dp

    D. Longest Subsequence 题目连接: http://www.codeforces.com/contest/632/problem/D Description You are giv ...