android开发之经典蓝牙安卓平台包括支持蓝牙网络协议栈,它允许设备与其他蓝牙设备进行无线交换数据。 应用程序框架提供通过安卓蓝牙接口访问蓝牙功能。 这些应用程序的无线连接到其他蓝牙设备,使点对点和多点的无线功能。
使用蓝牙接口,安卓应用程序可以执行以下:本文档介绍了如何使用经典蓝牙。 经典蓝牙是更为正确的选择,更多的电池密集的操作,如流媒体和通信之间的安卓设备。 对于低功耗的蓝牙设备,安卓4.3(原料药18)对蓝牙低能量的支持。 要了解更多,见蓝牙低能量。
- 扫描其他蓝牙设备
- 查询本地蓝牙适配器,用于配对蓝牙设备
- 建立RFCOMM通道
- 通过服务发现连接到其他设备
- 向其他设备传送数据
- 管理多个连接
基础
本文档介绍了如何使用安卓的蓝牙接口来完成四个主要任务所需的通信使用蓝牙:设置蓝牙,寻找设备,无论是配对或可在本地区,连接设备,设备之间传输数据。
所有的蓝牙API可在android.bluetooth包。这里的类和接口,您将需要创建蓝牙连接的总结:
具体流程:
BluetoothAdapter:表示本地蓝牙适配器(蓝牙收音机)。对于任务是所有蓝牙互动的切入点。利用这一点,你会发现其他的蓝牙设备,查询列表(配对)保税设备,实例化一个蓝牙设备使用一个已知的MAC地址,并创建一个bluetoothserversocket听来自其他设备的通信。
BluetoothDevice
:表示远程蓝牙设备。使用此请求与远程设备的连接通过一个BluetoothSocket或查询有关的装置,如名称、地址、类别信息,并结合状态。BluetoothSocket:
代表一个蓝牙套接字接口(类似于TCP套接字)。这是连接点,允许一个应用程序与另一个蓝牙设备通过InputStream和OutputStream交换数据BluetoothServerSocket
:代表一个打开服务器套接字侦听传入的请求(类似于一个TCP ServerSocket)。为了连接2个安卓设备,一个设备必须打开一个与这个类的服务器套接字。当一个远程蓝牙设备进行连接请求的这种装置的bluetoothserversocket将返回一个BluetoothSocket连接时连接被接受BluetoothClass
:描述蓝牙设备的一般特性和功能。这是一组只读的属性,定义设备的主要和次要设备类及其服务。然而,这并不能可靠地描述设备所支持的所有蓝牙配置文件和服务,但对设备类型的提示是有用的BluetoothProfile
:表示蓝牙配置文件的接口。蓝牙配置文件是一种基于蓝牙的设备之间的无线接口规范。一个例子是双手自由配置文件。对于配置文件的更多讨论,请参见使用配置文件BluetoothHeadset
:提供了对蓝牙耳机的支持。这包括蓝牙耳机和免提(V1.5)简介。BluetoothA2dp
:定义如何高质量的音频可以从一个设备传输到另一个蓝牙连接。”A2DP”代表先进的音频分布。BluetoothHealth
:表示控制蓝牙服务的健康设备配置文件代理。BluetoothHealthCallback
:一个抽象类,您使用来实现bluetoothhealth回调。您必须扩展这个类并实现回调方法以接收应用程序注册状态和蓝牙信道状态的变化的更新。BluetoothHealthAppConfiguration
:表示蓝牙健康第三方应用程序注册与远程蓝牙健康设备通信的应用程序配置。BluetoothProfile.ServiceListener
:一个界面,通知bluetoothprofile IPC客户当他们已连接或断开了与服务(即内部服务运行一个特定的配置文件)。
(1)流程图
(2).具体实例
1.蓝牙权限
为了在您的应用程序中使用蓝牙功能,您必须声明蓝牙允许蓝牙。您需要此权限来执行任何蓝牙通信,例如请求连接、接受连接和传输数据。
如果你想让你的应用启动设备发现或操纵蓝牙设置,你也必须申报bluetooth_admin许可。大多数应用程序都需要这个权限,完全可以发现本地蓝牙设备的能力。除非该应用程序是一个“电源管理器”,在用户请求上修改蓝牙设置,否则无法使用该权限授予的其他能力。注意:如果你使用bluetooth_admin许可,那么你也必须有蓝牙许可。
在应用程序清单文件中声明蓝牙权限。例如:
2.设置蓝牙:
在您的应用程序可以通过蓝牙进行通信之前,您需要验证设备上是否有蓝牙支持,如果是这样,确保它被启用。
如果不支持蓝牙,那么你应该优雅地禁用蓝牙功能。如果支持蓝牙,但禁用了,那么你可以请求用户启用蓝牙而不留你的应用程序。这个设置是在两个步骤来完成,使用蓝牙适配器。
2.1.获得蓝牙适配器蓝牙适配器是任何和所有蓝牙活性所必需的。要获得蓝牙适配器就要调用静态方法getdefaultadapter()。这将返回一个BluetoothAdapter表示设备的蓝牙适配器(蓝牙无线电)。整个系统有一个蓝牙适配器,您的应用程序可以使用这个对象进行交互。如果getdefaultadapter()返回null,则该设备不支持蓝牙和你的故事在这里结束。例如:
2.2启用蓝牙:
接下来,您需要确保启用蓝牙。电话isenabled()检查蓝牙目前是否启用。如果该方法返回假,则禁用蓝牙。要求蓝牙启用,电话startactivityforresult()与action_request_enable动作意图。这将发出一个请求,使蓝牙通过系统设置(不停止您的应用程序)。例如:
图1
一个对话框会出现请求用户允许启用蓝牙,如图1所示。如果用户回答“是的”,系统将开始启用蓝牙和焦点将返回到您的应用程序的过程中完成(或失败)。
通过startactivityforresult()的request_enable_bt常数是一个本地定义的整数(必须大于0),这个系统通过在你的onactivityresult()实施你的requestCode参数。
如果成功开启蓝牙,你的活动在onactivityresult()回调接收result_ok结果代码。如果没有启用蓝牙是由于一个错误(或用户回答“不”)结果代码result_canceled。
或者,您的应用程序也可以听的action_state_changed广播意图,该系统将在蓝牙状态改变的时候广播。 这广播包含额外的领域extra_state和extra_previous_state,包含新的和旧的蓝牙状态,分别。 这些额外的字段可能的值是state_turning_on,state_on,state_turning_off,和state_off。 听了这个广播可以是有用的检测到蓝牙状态的变化,而你的应用程序正在运行。
提示:启用程序会自动启用蓝牙。如果你打算开启设备的可见性,可以跳过上面的2步。
3.找到设备:
使用蓝牙适配器,您可以通过查询名单发现远程蓝牙设备配对,通过设备发现或(保税)设备。
设备发现是一个扫描程序,搜索本地区的蓝牙功能的设备,然后请求一些信息,每一个(这是有时被称为“发现”,“查询”或“扫描”)。然而,局域网内的蓝牙设备将响应发现请求只有在能够被发现。如果一个设备可以被发现,它会响应发现请求并共享一些信息,比如设备名称、类别,并以其独特的MAC地址。使用此信息,该设备执行发现可以选择启动一个连接到所发现的设备。
一旦一个连接是与远程设备的第一次,一个配对请求是自动提交给用户。当一个设备配对时,该设备(如设备名称、类别和苹果地址等)的基本信息被保存,并且可以使用蓝牙接口进行读取。使用已知的远程设备的苹果地址,一个连接可以在任何时候开始,它在任何时候没有进行发现(假设设备是在范围内)。
记住,作为一个被连接的人是有区别的。 成对的意思是,2个设备都知道彼此的存在,有一个共享的密钥,可用于身份验证,并能够建立一个加密连接。 要连接意味着目前的设备共享一个RFCOMM通道可以互相传递数据。 目前安卓蓝牙API的设备需要被配对在RFCOMM连接可以建立。 (在启动与蓝牙接口的加密连接时自动执行配对)。
下面的章节将介绍如何找到已配对的设备,或者使用设备发现发现新设备。
注:Android设备都无法发现的默认。 用户可以使设备能在有限的时间内通过系统设置,或应用程序可以要求用户使能见度没有离开应用。4.查询配对设备:
在进行设备发现之前,它的值查询一组配对的设备,以查看所需的设备是否已经知道。这样做,叫getbondeddevices()。这将返回一组代表配对设备的蓝牙设备。例如,你可以查询所有配对设备,然后给每个设备的名称的用户,使用一个ArrayAdapter:
所有的需要的对象初始化一个连接蓝牙设备的MAC地址。在这个例子中,它是保存为一个ArrayAdapter,显示给用户的一部分。可后来被提取的苹果地址,以便启动连接。你可以在连接设备的部分中了解更多关于创建连接的关系。
5.发现设备
开始发现设备,简单的叫startdiscovery()。过程是异步的,该方法将立即返回一个布尔指示是否已成功启动。发现过程通常包括约12秒的调查扫描,然后通过每一个页面扫描发现设备检索其蓝牙名称。
你的应用程序必须注册为action_found意图接收有关每个设备发现BroadcastReceiver。对每一个设备,系统将播出action_found意图。这种意图进行额外的领域extra_device和extra_class,包含一个蓝牙设备和蓝牙类,分别。例如,这里的你可以如何注册来处理设备被发现时的广播:
所有的需要的对象初始化一个连接蓝牙设备的MAC地址。在这个例子中,它是保存为一个ArrayAdapter,显示给用户的一部分。可后来被提取的苹果地址,以便启动连接。你可以在连接设备的部分中了解更多关于创建连接的关系。
警告:执行设备发现是蓝牙适配器的一个很重的程序,它将消耗大量的资源。一旦你找到了一个设备连接,可以肯定,你总是站canceldiscovery()发现与之前的连接。此外,如果你已经与一个设备连接,然后执行发现可以显着地减少可用的连接的带宽,所以你不应该执行发现,同时连接
其中可发现:
如果你想使本地设备可被其他设备,调用startActivityForResult(意图,int)与action_request_discoverable动作意图。这将发出一个请求,通过系统设置使发现模式(没有停止你的应用)。默认情况下,该设备将成为明显的120秒。您可以通过添加额外的extra_discoverable_duration意图定义一个不同的时间。一个应用程序可以设置最大持续时间为3600秒,和0的值表示设备总是发现。任何值低于0或高于3600自动设置为120秒)。例如,这段代码设置持续时间为300:
会显示一个对话框,要求用户权限使设备发现的,如图2所示。如果用户回答“是的,”然后设备将成为可在指定的时间量。你的活动会收到电话的onactivityresult())回调,结果代码等于设备是可发现的时间。如果用户回答“不”或如果出现错误,结果代码将result_canceled。
注意:如果蓝牙尚未启用的设备,并使设备可发现将自动启用蓝牙。
该装置会静静地停留在发现模式的时间。 如果你想被通知当发现模式发生了变化,你可以注册一个BroadcastReceiver的action_scan_mode_changed意图。 这将包含额外的字段extra_scan_mode和extra_previous_scan_mode,告诉你的新的和旧的扫描方式,分别为。 对于每个可能的值是scan_mode_connectable_discoverable,scan_mode_connectable,或scan_mode_none,表明该装置是在发现模式,不可发现模式但仍能接收连接,或不可发现模式和无法接收连接,分别 。你不需要如果你将发起连接到远程设备,使设备可发现。 其中可发现只有必要的时候,你希望你的应用程序主机将接受传入的连接,因为远程设备必须能够发现设备才可以启动连接。
6.连接装置:
为了创建应用程序在设备上的连接,必须实现服务器端和客户端机制,因为一个设备必须打开服务器套接字,另一个必须启动连接(使用服务器设备的苹果地址来启动连接)。 服务器和客户端是连接到对方时,他们都有一个BluetoothSocket连接在相同的RFCOMM通道。 在这一点上,每个设备可以得到输入和输出流和数据传输可以开始,这是讨论在有关管理连接部分。 本节介绍如何启动设备之间的连接。
服务器装置和客户端装置各获得所需的BluetoothSocket的方式不同。 当接收连接被接受时,服务器将接收它。 客户将收到它时,它打开一个RFCOMM通道到服务器。
一种实现技术是自动将每个设备作为服务器来准备,以便每个人都有一个服务器套接字打开和侦听连接。 然后,任何一个设备可以启动一个连接,成为客户端。 另外,一个设备可以显式地“主机”的连接,打开一个服务器套接字上的需求和其他设备可以简单地启动连接。
注:如果这2个设备以前没有配对,那么安卓框架将在连接过程中自动向用户显示一个配对请求通知或对话框,如图3所示。因此,当尝试连接设备时,您的应用程序不需要关注设备是否配对。你的RFCOMM连接尝试将阻塞直到用户成功配对,或者如果用户拒绝配对失败,或者如果配对失败或超时。
6.1连接作为服务器
当你想要连接的两个设备,一个必须通过举行开放bluetoothserversocket服务器。服务器套接字的目的是用于侦听传入的连接请求,当一个人接受,提供一个BluetoothSocket连接。当BluetoothSocket从bluetoothserversocket后天的bluetoothserversocket可以(也应该)被丢弃,除非你想接受更多的连接。
关于UUID
通用唯一标识符(UUID)是一个字符串ID用来唯一标识信息标准化128位格式。一个UUID的一点是,它足够大,你可以选择任意的,它不会有冲突。在这种情况下,它是用来唯一识别您的应用程序的蓝牙服务。得到一个UUID来使用你的应用,你可以使用一个随机的UUID生成器在网上,然后初始化一个UUID和fromstring(字符串)。
这里的基本程序是建立一个服务器套接字并接受连接:
1,通过调用listenusingrfcommwithservicerecord得到bluetoothserversocket(String,UUID)。
字符串是你服务的一个可识别的名称,该系统会自动写入到一个新的服务发现协议(SDP)设备上的数据库条目(名称是任意的,可以简单地将你的应用程序的名称)。UUID也包括在SDP条目并将与客户设备的连接协议的基础。那是,当客户端试图与该设备连接,它将携带一个UUID唯一标识服务,它要连接。这些UUID必须要接受的连接(下一步)。
2。开始监听连接请求()的调用。
这是一个阻塞调用。当一个连接被接受或发生异常时,它将返回。一个连接被接受,只有当一个远程设备发送连接请求一个UUID匹配一个注册服务器套接字这听。成功时,()将返回一个BluetoothSocket连接。
3。除非你想接受更多的连接,称为()。
这个版本的服务器套接字和它所有的资源,但不关闭连接BluetoothSocket的()返回的。不同于TCP/IP、RFCOMM只允许一个连接的客户端每信道在一个时间,所以在大多数情况下是有意义的呼吁bluetoothserversocket()立即接受一个socket连接后。
()调用不应执行的主要活动在UI线程,因为它是一个阻塞调用,将防止任何其他相互作用中的应用。它通常就在一个新的线程的应用程序管理bluetoothserversocket或BluetoothSocket做所有的工作。放弃一个阻塞呼叫如(),呼吁bluetoothserversocket()(或BluetoothSocket)从另一个线程阻塞的调用将立即返回。注意在bluetoothserversocket或BluetoothSocket所有的方法都是线程安全的。
这里是接受传入连接的服务器组件的一个简化的线程:
在这个例子中,只有一个传入的连接是需要的,所以当一个连接被接受和BluetoothSocket是后天获得的,应用程序将获得的BluetoothSocket到一个单独的线程,关闭bluetoothserversocket和破环。
注意,当()返回BluetoothSocket,套接字已连接,所以你不应该叫connect()(和你的客户端)。
manageconnectedsocket()在应用程序将数据传输启动线程一个虚构的方法,这一节中所讨论的关于管理连接。
通常你应该闭上你的bluetoothserversocket只要你完成侦听传入的连接。在这个例子中,()称为尽快获得BluetoothSocket。你也可能想在你的线程提供公共方法可以关闭的事件,你需要停止侦听服务器套接字BluetoothSocket的私人。
6.2连接作为客户端
为了启动与远程设备的连接(一个装置保持开放的服务器套接字),你必须首先获得一个蓝牙设备对象表示远程设备。(得到一个蓝牙设备是覆盖在上面的部分找到设备。)你必须使用蓝牙设备来获取一个BluetoothSocket和启动连接。
这里的基本程序:
1。使用蓝牙设备,通过调用createrfcommsockettoservicerecord得到一个BluetoothSocket(UUID)。
这个初始化一个BluetoothSocket,将连接到蓝牙设备。UUID路过这里必须匹配使用的服务器设备,当它张开它的bluetoothserversocket UUID(与listenusingrfcommwithservicerecord(String,UUID))。使用相同的UUID是一件简单的事,硬编码字符串的UUID到您的应用程序中引用它,然后从服务器和客户端的代码。
2,通过调用connect()启动连接。
在这个调用,系统将以遥控器匹配的UUID进行SDP查找。如果查找成功,远程设备接收连接,它将分享RFCOMM通道使用的连接和connect()期间将返回。这种方法是一种阻塞调用。如果因为任何原因,连接失败或connect()方法的时间(约12秒后),然后将抛出一个异常。
因为connect()是阻塞调用,这个连接的过程应该是一个从主要活动线程独立的线程中执行。
注意:你应该始终确保设备不执行设备发现你打电话时connect()。如果发现正在进行中,则连接尝试将显著放缓,更容易失败。
这里是一个线程的基本例子,启动蓝牙连接
注意,canceldiscovery()是连接之前叫。你应该做这个连接是安全的调用而不检查它是否正在运行或不前(如果你想检查,称isdiscovering())。
manageconnectedsocket()在应用程序将数据传输启动线程一个虚构的方法,这一节中所讨论的关于管理连接。
当你完成了你的BluetoothSocket,总是叫()清理。这样做将立即关闭连接的套接字和清理所有内部资源。
7. 管理连接:当您已成功连接的两个(或更多)的设备,每一项都会有一个连接BluetoothSocket。这是有趣的开始,因为你可以在设备之间共享数据。使用BluetoothSocket,传输任意数据的一般程序是简单的:
1。把处理传输通过套接字的InputStream和OutputStream,通过getinputstream()和getoutputstream(),分别。
2、读写数据到流读(字节)和写(字节)。
这是它。
有,当然,执行细节考虑。首先,你应该使用一个专门的线程来进行所有的流读写。这是很重要的,因为这两个读(字节)和写(字节)的方法是阻塞调用。读(字节)将阻止,直到有一些从流读取。写(字节)不通常块,但可以块的流量控制,如果远程设备不调用读(字节)的速度快,中间缓冲区是充分。所以,你的线程中的主回路应致力于从输入流读取。在一个单独的线程的公共方法可以用来启动写入输出流。
例子
下面是一个例子,这可能是如何看:
构造函数分配必要的溪流,一旦执行,线程会等待数据来通过InputStream。当读(字节)返回与字节的流,数据被发送到主活动使用的成员从父类的处理程序。然后,它会返回,等待更多的字节流。
输出数据为调用线程的write()方法从主要活动和传递的字节被发送的简单。这个方法,然后简单地调用写(字节)发送数据到远程设备。
线程的cancel()方法很重要,连接可以终止在任何时间通过关闭BluetoothSocket。当您使用蓝牙连接时,该调用始终被调用。
用于演示使用蓝牙接口,见蓝牙聊天示例应用程序。
课外拓展:
与公司合作
从安卓3开始,蓝牙接口包括支持蓝牙配置文件。蓝牙配置文件是一种基于蓝牙的设备之间的无线接口规范。一个例子是双手自由配置文件。对于一个移动电话连接到无线耳机,这两个设备必须支持的手自由配置文件。例如,这段代码显示了如何连接到一个bluetoothheadset代理对象使您可以控制耳机模式:
命令的供应商:
从Android 3开始,应用程序可以注册在发送命令接收耳机预先定义的特定于供应商的系统广播(如缤特力+ XEvent命令)。例如,一个应用程序可以接收广播,表示连接的设备的电池水平,可以通知用户或采取其他行动所需要的。创建用于处理特定厂商在耳机的命令action_vendor_specific_headset_event意图广播接收器。
健康设备简介
Android 4(API Level 14)介绍了蓝牙医疗设备配置文件支持(HDP)。这使您可以创建使用蓝牙与健康支持蓝牙的设备进行通信的应用程序,如心率监视器,血米,温度计,刻度。蓝牙API包括健康类bluetoothhealth,bluetoothhealthcallback,和bluetoothhealthappconfiguration,这是最基本的描述。
在使用蓝牙健康API,了解这些关键期的概念是很有帮助的
创建一个HDP的应用
这是参与创建一个Android应用程序的基本步骤,HDP:
1,得到一个参考的bluetoothhealth代理对象。
类似于普通的耳机和A2DP设备,你必须调用getprofileproxy()与bluetoothprofile.servicelistener和健康档案类型建立档案代理对象连接。
2。创建一个bluetoothhealthcallback和注册一个应用程序的配置(bluetoothhealthappconfiguration)作为健康沉。
3、建立一个连接到健康的设备。一些设备将启动连接。没有必要对这些设备进行这一步。
4、当连接到一个健康设备,读/写的健康设备使用的文件描述符。
接收到的数据需要用它实现了IEEE 11073- xxxxx规格卫生经理解释。
5。完成后,关闭健康频道和注销申请。通道也关闭时,有延长闲置。
一个完整的代码示例说明了这些步骤,看到蓝牙HDP(卫生设备配置文件)。