先附上Android官方蓝牙聊天Demo示例下载:http://download.csdn.net/detail/gh8609123/9557547
蓝牙权限
为了使用应用程序中的蓝牙功能,您必须声明蓝牙权限BLUETOOTH
。你需要这个权限才能执行任何蓝牙通信,比如请求连接,接受连接,传输数据。
如果你希望你的应用程序启动设备搜索或操作蓝牙设置,您还必须声明BLUETOOTH_ADMIN
权限。大多数应用程序仅在搜索蓝牙设备的时候需要这个权限。不应该使用此权限来获取其他功能,除非应用程序是一个能根据用户请求来修改蓝牙设置的“功能管理器”,如果你使用BLUETOOTH_ADMIN
权限,则还必须具备BLUETOOTH
权限。
在您的应用程序的manifest文件中声明蓝牙权限(S)。例如:
<manifest ... >
<uses-permission android:name="android.permission.BLUETOOTH" />
...
</manifest>
请参阅<uses-permission>有关声明应用程序权限的详细信息参考。
设置蓝牙
在应用程序通过蓝牙通信之前,您需要验证设备是否支持蓝牙,如果支持,请确保它已启用。
如果不支持蓝牙,那么你应该优雅地禁用任何蓝牙功能。如果支持蓝牙,但被禁用,则可以在程序内要求用户开启蓝牙。这个设置需使用BluetoothAdapter
分两个步骤来完成 。
- 获取
BluetoothAdapter
所有的蓝牙活动都需要
。要获得BluetoothAdapter
BluetoothAdapter
,调用静态的getDefaultAdapter()
方法。它将返回一个BluetoothAdapter
表示设备自身的蓝牙适配器(蓝牙无线电)。整个系统有一个蓝牙适配器,应用程序可以使用这个对象与它进行交互。如果
返回null,则该设备不支持蓝牙,你可以歇歇了。例如:getDefaultAdapter()
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); if (mBluetoothAdapter == null) { // Device does not support Bluetooth }
- 启用蓝牙
接下来,您需要确保蓝牙已启用。 调用
isEnabled()
检查蓝牙当前是否启用。如果此方法返回false,那么蓝牙被禁用。要请求蓝牙启用,调用
与startActivityForResult()
ACTION_REQUEST_ENABLE
这个action来开启。它将发出一个请求,通过系统设置来启用蓝牙(无需停止应用程序)。例如:if (!mBluetoothAdapter.isEnabled()) { Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT); }
图1:启用蓝牙对话框。
此时将出现一个对话框,请求用户启用蓝牙功能,如图1。如果用户点击“是”,系统将开始启用蓝牙,一旦处理完成(或失败)焦点将返回到应用程序。传递给startActivityForResult()
的REQUEST_ENABLE_BT
常量是在本地定义的整数(必须大于0),系统将在你的onActivityResult()
实现中将它作为
requestCode
参数传回给你。
如果启用蓝牙成功,你的Activity的onActivityResult()
回调中将收到RESULT_OK
结果代码。如果蓝牙由于错误没有启用(或用户点击“否”),那么结果代码为
。 RESULT_CANCELED
或者,您的应用程序还可以侦听ACTION_STATE_CHANGED
广播意图,每当蓝牙状态发生变化,系统将发出广播。此广播包含了额外的字段
和EXTRA_STATE
EXTRA_PREVIOUS_STATE
,分别包含蓝牙的新、旧状态。 这些额外字段可能的值是STATE_TURNING_ON
,STATE_ON
,STATE_TURNING_OFF
和
STATE_OFF
。 当您的应用程序正在运行时侦听此广播可以非常有效的检测蓝牙状态的改变。
提示:启用蓝牙可发现会自动启用蓝牙。如果您计划在执行蓝牙活动前始终启用蓝牙可发现,你可以跳过上面的步骤2。阅读关于启用可发现,见下文。
查找设备
使用BluetoothAdapter
,无论是通过设备搜索,还是通过查询配对(绑定)的蓝牙设备列表都可以发现远程蓝牙设备。
设备搜索是一个搜索局部区域内蓝牙设备然后请求每部设备一些信息(这有时被称为“发现”,“查询”或“扫描”)的扫描过程。然而,只有当当前局部区域内的蓝牙设备已启用可被发现才会对请求作出响应。如果一个设备是可发现,它会通过共享一些信息,例如设备名称,类和其特有的MAC地址对发现请求作出响应。使用该信息,该设备执行搜索随后可以选择和所发现的设备创建连接。
一旦和远程设备创建连接,配对请求会自动呈现给用户。当一个设备完成配对,关于该设备的基本信息(例如设备名称,类和MAC地址)将被保存,并且可以使用蓝牙API来读取。为远程设备使用已知的MAC地址,可以在任何时候连接它而不必执行搜索(假设设备在范围内)。
记得连接和配对之间是有差别的。 进行配对意味着两个设备都知道彼此的存在,具有可以用于认证的共享链接密钥,并且能够建立与彼此的加密连接。要连接意味着设备目前共享一个RFCOMM信道,并且能够彼此传输数据。目前Android蓝牙API的要求建立一个RFCOMM连接之前设备必须配对。(当你使用蓝牙API的一个加密连接时会自动进行配对。)
以下部分描述了如何找到已配对的设备,或使用设备发现发现新的设备。
注:Android系统的设备默认情况下不会被发现。用户可以通过系统设置使设备在有限的时间内可发现,或者应用程序可以要求用户能够发现能力,而无需离开应用程序。如何启用可发现见下面讨论。
查询配对设备
执行设备搜索之前,查询想要找的设备是否已配对是很有用的。要做到这一点,调用
这将返回一组getBondedDevices()
BluetoothDevice
代表已配对设备。例如,您可以查询所有配对设备,然后显示每个设备的用户名,使用ArrayAdapter:
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
// If there are paired devices
if (pairedDevices.size() > 0) {
// Loop through paired devices
for (BluetoothDevice device : pairedDevices) {
// Add the name and address to an array adapter to show in a ListView
mArrayAdapter.add(device.getName() + "\n" + device.getAddress());
}
}
创建连接所需的只有
对象的MAC地址。在这个例子中,它做为显示给用户的一个ArrayAdapter的一部分而储存起来。MAC地址可在之后被提取以创建连接。您可以了解更多有关于创建连接的知识在连接设备 。 BluetoothDevice
发现设备
要开始查找设备,只需调用
,这个过程是异步的,该方法将立即返回一个布尔值来指示是否搜索已成功启动。搜索过程通常需要约12秒的查询扫描,接着会用一个页面展示每个扫描到的设备的蓝牙名称。startDiscovery()
您的应用程序必须注册一个BroadcastReceiver 来使
接收发现的每个设备的有关信息。对于每个设备,该系统将播出ACTION_FOUND
ACTION_FOUND
意图。此意图携带额外的字段EXTRA_DEVICE
和
,分别包含EXTRA_CLASS
BluetoothDevice
和
。例如,下面是当设备被发现时,你如何注册处理广播:BluetoothClass
// Create a BroadcastReceiver for ACTION_FOUND
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
// When discovery finds a device
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// Get the BluetoothDevice object from the Intent
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// Add the name and address to an array adapter to show in a ListView
mArrayAdapter.add(device.getName() + "\n" + device.getAddress());
}
}
};
// Register the BroadcastReceiver
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter); // Don't forget to unregister during onDestroy
创建连接所需的只有BluetoothDevice
对象的MAC地址。在这个例子中,它做为显示给用户的一个ArrayAdapter的一部分而储存起来。 MAC地址可在之后被提取以创建连接。您可以了解更多有关于创建连接的知识在连接设备。
注意:执行设备搜索是蓝牙适配器一个重要的步骤,会消耗大量的资源。一旦你找到了要连接的一个设备,请确认你总是在尝试连接前使用cancelDiscovery()
来停止搜索。此外,如果你已经持有一个设备的连接,然后执行搜索会显著减少用于连接的带宽,所以你不应该在已经连接时执行搜索。
启用可发现
如果你想使本地设备可被其他设备发现,调用
与startActivityForResult(Intent,int)
ACTION_REQUEST_DISCOVERABLE
。这将发出一个请求,来让系统设置启用发现模式(无需停止应用程序)。默认情况下,该设备将保持可发现120秒。您可以通过添加EXTRA_DISCOVERABLE_DURATION
来规定不同的期限。一个应用程序可以设置的最长持续时间为3600秒,值为0意味着设备总是发现。低于0或高于3600的任何值会自动设置为120秒)。例如,该片段设置期限为300:
Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
startActivity(discoverableIntent);
图2:启用可发现对话框。
将显示一个对话框,要求用户权限,使设备可发现,如图2。如果用户回答“是”,则该设备在指定的时间内将成为可发现设备。那么你的Activity将接收到
的回调,结果代码等于该设备可发现的持续时间。如果用户回答“否”,或者如果发生错误,结果代码将为onActivityResult())
RESULT_CANCELED
。
注意:如果蓝牙尚未在设备上启用,则使设备可发现会自动启用蓝牙。
该设备会在指定的时间内保持可发现性。如果您希望发现模式改变时得到通知,你可以为一个名为ACTION_SCAN_MODE_CHANGED
的Intent注册BroadcastReceiver。这将包含额外的字段
和EXTRA_SCAN_MODE
,分别通知你新、旧扫描模式。可能的扫描模式有EXTRA_PREVIOUS_SCAN_MODE
SCAN_MODE_CONNECTABLE_DISCOVERABLE
,
或SCAN_MODE_CONNECTABLE
,它们分别表明该设备是可发现模式,不是可发现模式但仍然能够接收连接,或者不是可发现模式且无法接收连接。SCAN_MODE_NONE
在创建到远程设备的连接时你不需要启用设备可发现。当你想你的应用程序管理服务器套接字并接受传入的连接时启用可发现才是必要的,因为远程设备必须能够发现设备才可以创建连接。
连接设备
为了建立两个设备的应用程序之间的连接,必须同时实现服务器端和客户端的机制,因为一台设备必须打开一个服务器套接字,另一个必须发起连接(使用服务器设备的MAC地址启动连接)。当服务器和客户端在相同的RFCOMM信道上都具有一个BluetoothSocket
时,被认为是彼此连接的。在这一点上,每个设备都可以获取输入和输出流,数据传输可以开始,这是在管理连接部分讨论过的。本节将介绍如何启动两个设备之间的连接。
服务器设备和客户端设备获得所需BluetoothSocket
的方式不同。服务器在传入的连接被接受时得到它。客户端打开一个到服务器的RFCOMM通道时得到它。
一种实现方法是将每个设备作为服务器来自动准备,让每个设备都有一个服务器套接字打开并侦听连接。然后其中一个可以发起与其他设备的连接,并成为客户端。另外,一台设备可以明确的“主持”连接,并打开需求的服务器套接字以让其他设备可以简单地启动连接。
注意:如果两个设备没有进行过配对,那么Android框架会在连接过程中自动显示配对请求通知或对话框给用户,如图3所示。所以当尝试连接设备时,你的应用程序不需要关注设备是否被配对。你的RFCOMM连接尝试将阻塞,直到用户已成功配对,或者如果用户拒绝配对,如果配对失败或者超时就会失败。
关于UUID
通用唯一标识符(UUID)是用来唯一标识信息的标准化128位格式的字符串ID。 关于一个UUID最重要的一点是,它大到你可以选择任何随机值也不会发生冲突。 在这种情况下,它用来唯一标识应用程序的蓝牙服务。要获取UUID并在你的应用程序中使用,可以使用Web上的众多随机UUID生成器之一,然后通过fromString(String)初始化一个UUID 。
作为服务器连接
当你想连接两个设备,一个作为服务器必须担任公开的BluetoothServerSocket
。 服务器套接字的目的是监听传入的连接请求,当一个请求被接受时,提供一个连接
。 当从BluetoothSocket
BluetoothServerSocket
获得
BluetoothSocket
后 ,该
可以(应该)被丢弃,除非你想接受更多的连接。BluetoothServerSocket
这里是建立一个服务器套接字并接受连接的基本步骤:
-
通过调用
listenUsingRfcommWithServiceRecord(String,UUID)
.获取BluetoothServerSocket
该字符串是你服务的确认名称
,系统会自动将它写入到设备上的一个新的Service Discovery Protocol(SDP)数据库条目(名称是任意的,可以简单地使用您的应用程序名称)。UUID包含在SDP条目中,且将作为与客户端设备连接协议的基础。也就是说,当客户端试图与此设备连接时,其将携带一个UUID唯一标识它要连接的服务。这些的UUID必须匹配以使连接被接受(在下一步骤)。 - 开始调用
accept()
来监听连接请求这是一个阻塞调用过程。 直到任一连接被接受或者发生异常时才返回。只有当远程设备发出的连接请求中包含的一个UUID与此监听服务器套接字中注册的一个相匹配时连接被接受。如果成功,
accept()
将返回一个连接
。BluetoothSocket
- 除非你想接受更多的连接,否则调用
close()
这将释放服务器套接字及其所有资源,但不会关闭由
accept()
返回的连接BluetoothSocket
,不像TCP / IP,RFCOMM每个通道同一时间只允许一个客户端连接,因此在多数情况下接受连接套接字之后调用
的BluetoothServerSocket
close()
是有意义的。
accept()
调用不应在主Activity的UI线程执行,因为它是一个阻塞调用,会阻止其它任何与应用程序的交互行为。通常正确的做法是在您应用程序的一个新线程中使用
或BluetoothServerSocket
来完成所有工作。要中止阻塞调用,如BluetoothSocket
,从另一线程调用accept()
BluetoothServerSocket
(或
)的BluetoothSocket
close()
,阻塞调用将立即返回。请注意,在
或BluetoothServerSocket
BluetoothSocket
里的所有方法是线程安全的。
例子
下面是接受传入连接的服务器组件的简单线程:
private class AcceptThread extends Thread {
private final BluetoothServerSocket mmServerSocket;
public AcceptThread() {
// Use a temporary object that is later assigned to mmServerSocket,
// because mmServerSocket is final
BluetoothServerSocket tmp = null;
try {
// MY_UUID is the app's UUID string, also used by the client code
tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
} catch (IOException e) { }
mmServerSocket = tmp;
}
public void run() {
BluetoothSocket socket = null;
// Keep listening until exception occurs or a socket is returned
while (true) {
try {
socket = mmServerSocket.accept();
} catch (IOException e) {
break;
}
// If a connection was accepted
if (socket != null) {
// Do work to manage the connection (in a separate thread)
manageConnectedSocket(socket);
mmServerSocket.close();
break;
}
}
}
/** Will cancel the listening socket, and cause the thread to finish */
public void cancel() {
try {
mmServerSocket.close();
} catch (IOException e) { }
}
}
在本示例中,只需要一个传入连接,所以只要有一个连接被接受并且BluetoothSocket
被获取时,应用程序会发送所获取的
到一个单独的线程,关闭BluetoothSocket
并中断循环。BluetoothServerSocket
请注意,当accept()
返回
后 ,套接字已连接,所以你不应该调用BluetoothSocket
connect()
(如同你在客户端做的)。manageConnectedSocket()
是应用中为了创建用于传送数据的线程而使用的方法,有关部分的讨论在管理连接 中。
通常只要你侦听到传入连接,你应该关闭BluetoothServerSocket
。在这个例子中,一旦
BluetoothSocket
被获取将调用
close()
。您可能想要在你的线程中提供一个公开的方法,可以在您需要停止监听服务器套接字的事件中关闭私有
。BluetoothSocket
作为客户端连接
为了与远程设备(设备保持一个开放的服务器套接字)连接,必须先获得一个BluetoothDevice
表示远程设备对象。(获取一个
是包含在上述发现设备部分 )。然后,您必须使用BluetoothDevice
BluetoothDevice
获取BluetoothSocket
,并启动连接。
这里的基本步骤:
-
使用
这将初始化一个连接到BluetoothDevice 的BluetoothSocket。这里传递的UUID必须和打开了BluetoothServerSocket的服务器设备使用的UUID相匹配(通过listenUsingRfcommWithServiceRecord(String, UUID)) 。使用相同的UUID是一个简单将UUID字符串硬编码到您的应用程序的事情,然后在服务器端和客户端的代码都引用它。BluetoothDevice
,通过调用createRfcommSocketToServiceRecord(UUID)
得到BluetoothSocket
-
通过调用
在调用时,系统会在远程设备上执行SDP查找以匹配UUID。 如果查找成功且远程设备接受连接,它会在连接过程中共享RFCOMM通道,connect()将返回。这种方法是一个阻塞调用。如果因任何原因,连接失败或connect()方法超时(约12秒后),那么它会抛出异常。
创建连接connect()
由于connect()是一个阻塞调用,这个连接过程应始终在一个与主Activity线程分离的线程执行。
注意:当你调用connect()时您应始终确保设备未进行设备搜索,如果正在进行搜索,那么连接尝试将显著减缓,更可能失败。
例子
这里是发起蓝牙连接线程的一个基本例子:
private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
public ConnectThread(BluetoothDevice device) {
// Use a temporary object that is later assigned to mmSocket,
// because mmSocket is final
BluetoothSocket tmp = null;
mmDevice = device;
// Get a BluetoothSocket to connect with the given BluetoothDevice
try {
// MY_UUID is the app's UUID string, also used by the server code
tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) { }
mmSocket = tmp;
}
public void run() {
// Cancel discovery because it will slow down the connection
mBluetoothAdapter.cancelDiscovery();
try {
// Connect the device through the socket. This will block
// until it succeeds or throws an exception
mmSocket.connect();
} catch (IOException connectException) {
// Unable to connect; close the socket and get out
try {
mmSocket.close();
} catch (IOException closeException) { }
return;
}
// Do work to manage the connection (in a separate thread)
manageConnectedSocket(mmSocket);
}
/** Will cancel an in-progress connection, and close the socket */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
}
注意cancelDiscovery()
是在连接之前被调用。你应该总是连接之前做到这一点,它总是安全调用的,无需实际检查它是否正在运行与否(但如果你想查询,调用
是应用中为了创建用于传送数据的线程而使用的方法,有关部分的讨论在管理连接中。当你使用完isDiscovering()
),manageConnectedSocket()
,应始终调用BluetoothSocket
close()
来清理。这样做将立即关闭连接套接字,并清理所有内部资源。
管理连接
当您成功的连接两个(或多个)设备,每个设备都会有一个BluetoothSocket
。这是个有趣的开始,因为你可以在设备之间共享数据。使用
来传输任意类型数据的通常步骤是这样的: BluetoothSocket
-
通过
和getInputStream()
getOutputStream()
获取
InputStream
和
OutputStream
,来处理通过套接字的传输。
-
使用
和read(byte[])
读取和写入数据流。write(byte[])
就酱。
这里当然有些实现的细节需要考虑。首先,你应该为所有流的读取和写入使用一个专用的线程。这一点很重要,因为
和read(byte[])
write(byte[])
这两个方法都阻塞调用。read(byte[])
会阻塞,直到有东西从流中读取出来。
write(byte[])
通常不会阻塞,但如果远程设备调用
read(byte[])
的速度不够快并且中间缓冲区已满的话会因流量控制而阻塞。所以,你的线程的主循环应专注于读取InputStream
。在线程里单独建立一个公共方法用于向OutputStream
写入数据。
例子
这里有一个如何这么做的示例:
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket) {
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
// Get the input and output streams, using temp objects because
// member streams are final
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) { }
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
byte[] buffer = new byte[1024]; // buffer store for the stream
int bytes; // bytes returned from read()
// Keep listening to the InputStream until an exception occurs
while (true) {
try {
// Read from the InputStream
bytes = mmInStream.read(buffer);
// Send the obtained bytes to the UI activity
mHandler.obtainMessage(MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
} catch (IOException e) {
break;
}
}
}
/* Call this from the main activity to send data to the remote device */
public void write(byte[] bytes) {
try {
mmOutStream.write(bytes);
} catch (IOException e) { }
}
/* Call this from the main activity to shutdown the connection */
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) { }
}
}
构造函数获取必要的数据流,一旦执行,该线程将等待通过InputStream的数据。当read(byte[])
返回从流中读取的字节后,使用从父类获得的成员Handler将数据发送到主Activity。之后它将返回,并等待从流中获取更多的字节。
发送输出数据只需在主Activity调用线程的
write()
方法,并传递要发送的字节。然后,此方法会调用write(byte[])
来发送数据到远程设备。
线程的cancel()
方法是很重要的,可以通过它在任何时候关闭BluetoothSocket
来终止连接。当你使用完蓝牙连接后请务必调用这个方法。
对于使用蓝牙API的演示,请参见该蓝牙聊天示例应用 。
使用配置文件
从Android 3.0开始,蓝牙API包含了对使用蓝牙配置文件的支持。蓝牙配置文件是基于蓝牙通信的设备间的无线接口规范。免提模式是一个例子。一个手机想要连接到一个无线耳机,这两个设备必须都支持免提模式。
您可以通过实现BluetoothProfile
接口,编写自己的类来支持特定的Bluetooth配置文件。Android的蓝牙API为以下蓝牙规范提供实现:
- 耳机 。耳机配置文件提供了对手机使用蓝牙耳机的支持。Android提供了
BluetoothHeadset
类,它是通过进程间通信(IPC )控制蓝牙耳机服务的代理。 它包括蓝牙耳机和免提(V1.5)模式。该BluetoothHeadset
类包括了对AT命令的支持。有关此主题的更多讨论,请参阅供应商特定AT命令 - A2DP。高级音频传输模式(A2DP)配置文件定义了如何让高品质音频文件通过蓝牙连接从一个设备串流到另一个。Android提供了
BluetoothA2dp
类,它是通过IPC控制A2DP蓝牙服务的代理。 - 健康设备 。Android 4.0(API级别14)引入了对蓝牙健康设备规范(HDP)的支持。这使您可以创建应用,使用蓝牙与支持蓝牙的健康设备进行蓝牙通讯,如心脏速率监视器,血糖仪,温度计,体重秤等。对于支持的设备及其相应的设备数据专业化代码的列表,请参阅蓝牙编号分配www.bluetooth.org 。请注意,这些值也在ISO / IEEE 11073-20601 [7]规范作为MDC_DEV_SPEC_PROFILE_ *的命名代码附件中引用。对于HDP的更多讨论,请参见健康设备规范 。
下面是用配置文件工作的基本步骤:
- 获取默认的适配器,如设置蓝牙中所述。
- 使用
建立与配置文件相关的配置文件代理对象的连接。在下面的例子中,配置文件代理对象是一个getProfileProxy()
实例。BluetoothHeadset
- 设置一个
BluetoothProfile.ServiceListener
。当
的IPC客户端与服务器连接或断开连接时,监听器会通知它们 。BluetoothProfile
- 在
onServiceConnected()
中得到一个配置文件代理对象的句柄。
- 一旦你拥有配置代理对象,你可以用它来监听连接的状态,并执行该配置文件相关的操作。
例如,下面的代码片段展示了如何连接到一个
代理对象,这样就可以控制耳机配置文件:BluetoothHeadset
BluetoothHeadset mBluetoothHeadset;
// Get the default adapter
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
// Establish connection to the proxy.
mBluetoothAdapter.getProfileProxy(context, mProfileListener, BluetoothProfile.HEADSET);
private BluetoothProfile.ServiceListener mProfileListener = new BluetoothProfile.ServiceListener() {
public void onServiceConnected(int profile, BluetoothProfile proxy) {
if (profile == BluetoothProfile.HEADSET) {
mBluetoothHeadset = (BluetoothHeadset) proxy;
}
}
public void onServiceDisconnected(int profile) {
if (profile == BluetoothProfile.HEADSET) {
mBluetoothHeadset = null;
}
}
};
// ... call functions on mBluetoothHeadset
// Close proxy connection after use.
mBluetoothAdapter.closeProfileProxy(mBluetoothHeadset);
供应商特定的AT命令
从Android 3.0开始,应用可以注册接收系统广播预定义的通过耳机发送的供应商特定的AT(如Plantronics的+ XEVENT命令)命令。例如,应用程序可以接收表明某一连接设备电池电量的广播,并可以通知用户根据需要采取其他行动。创建用于ACTION_VENDOR_SPECIFIC_HEADSET_EVENT
意图的广播接收器处理耳机厂商特定的AT命令。
健康设备规范
Android 4.0(API级别14)引入了对蓝牙健康设备规范(HDP)的支持。这使您可以创建应用,使用蓝牙与支持蓝牙的健康设备进行蓝牙通讯,如心脏速率监视器,血糖仪,温度计。蓝牙健康API包括类BluetoothHealth
,BluetoothHealthCallback
和
,这在基础中有描述 。BluetoothHealthAppConfiguration
为了更好使用蓝牙健康API,理解下面这些关键HDP概念很有必要:
概念 | 描述 |
---|---|
资源 | 在HDP中定义的角色。 资源是一种健康设备,传输医疗数据(计重秤,血糖仪,温度计等)给智能设备如Android手机或平板电脑。 |
接收器 | 在HDP中定义的角色。 在HDP中,接收器是接收医疗数据的智能设备。在一个Android HDP应用中,接收器由一个
BluetoothHealthAppConfiguration 对象表示。 |
注册 | 是指注册接收器到特定健康设备。 |
连接 | 指的是打开一个健康设备和智能设备之间的信道,例如Android手机或平板电脑。 |
创建HDP应用
以下是参与创建一个Android HDP应用程序的基本步骤:
- 获得一个
BluetoothHealth
代理对象的引用。类似普通耳机和A2DP功能的设备,你必须
使用
BluetoothProfile.ServiceListener
和
配置类型来调用HEALTH
,建立与配置代理对象的连接。getProfileProxy()
- 创建
BluetoothHealthCallback
,注册一个应用程序配置(
BluetoothHealthAppConfiguration
)充当健康接收器。 - 建立到健康设备的连接。 有些设备将启动连接。有些设备不需要进行此步骤。
- 当成功地连接到一个健康设备,使用文件描述符来读/写健康设备。
所接收的数据需要使用实现了IEEE 11073-XXXXX规格的健康管理器来解释。
- 完成后,关闭健康通道并取消注册应用程序。有扩展活动的通道也关闭。
对于说明了这些步骤的完整代码示例,请参阅蓝牙HDP (健康设备配置文件)