Android蓝牙开发

来源:互联网 发布:github tensorflow 编辑:程序博客网 时间:2024/06/03 07:33

    先附上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分两个步骤来完成

  1. 获取BluetoothAdapter

    所有的蓝牙活动都需要BluetoothAdapter要获得BluetoothAdapter,调用静态的getDefaultAdapter()方法。它将返回一个BluetoothAdapter表示设备自身的蓝牙适配器(蓝牙无线电)。整个系统有一个蓝牙适配器,应用程序可以使用这个对象与它进行交互。如果getDefaultAdapter()返回null,则该设备不支持蓝牙,你可以歇歇了。例如:

  2. BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();if (mBluetoothAdapter == null) {    // Device does not support Bluetooth}
  3. 启用蓝牙

    接下来,您需要确保蓝牙已启用。 调用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_STATEEXTRA_PREVIOUS_STATE ,分别包含蓝牙的新、旧状态。 这些额外字段可能的值是STATE_TURNING_ON,STATE_ONSTATE_TURNING_OFFSTATE_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 devicesif (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());    }}

创建连接所需的只有BluetoothDevice对象的MAC地址。在这个例子中,它做为显示给用户的一个ArrayAdapter的一部分而储存起来MAC地址可在之后被提取以创建连接。您可以了解更多有关于创建连接的知识在连接设备 。


发现设备

要开始查找设备,只需调用startDiscovery(),这个过程是异步的,该方法将立即返回一个布尔值来指示是否搜索已成功启动。搜索过程通常需要约12秒的查询扫描,接着会用一个页面展示每个扫描到的设备的蓝牙名称。

您的应用程序必须注册一个BroadcastReceiver 来使ACTION_FOUND接收发现的每个设备的有关信息。对于每个设备,该系统将播出ACTION_FOUND意图。此意图携带额外的字段EXTRA_DEVICEEXTRA_CLASS,分别包含BluetoothDeviceBluetoothClass例如,下面是当设备被发现时,你如何注册处理广播:

// Create a BroadcastReceiver for ACTION_FOUNDprivate 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 BroadcastReceiverIntentFilter 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_MODEEXTRA_PREVIOUS_SCAN_MODE分别通知你新、旧扫描模式。可能的扫描模式有SCAN_MODE_CONNECTABLE_DISCOVERABLESCAN_MODE_CONNECTABLESCAN_MODE_NONE,它们分别表明该设备是可发现模式,不是可发现模式但仍然能够接收连接,或者不是可发现模式且无法接收连接。

在创建到远程设备的连接时你不需要启用设备可发现当你想你的应用程序管理服务器套接字并接受传入的连接时启用可发现才是必要的,因为远程设备必须能够发现设备才可以创建连接。


连接设备


为了建立两个设备的应用程序之间的连接,必须同时实现服务器端和客户端的机制,因为一台设备必须打开一个服务器套接字,另一个必须发起连接(使用服务器设备的MAC地址启动连接)。服务器和客户端在相同的RFCOMM信道上都具有一个BluetoothSocket时,被认为是彼此连接的在这一点上,每个设备都可以获取输入和输出流,数据传输可以开始,这是在管理连接部分讨论过的。本节将介绍如何启动两个设备之间的连接。

服务器设备和客户端设备获得所需BluetoothSocket的方式不同。服务器在传入的连接被接受时得到它。客户端打开一个到服务器的RFCOMM通道时得到它。


图3:蓝牙配对对话框。

一种实现方法是将每个设备作为服务器来自动准备,让每个设备都有一个服务器套接字打开并侦听连接。然后其中一个可以发起与其他设备的连接,并成为客户端。另外,一台设备可以明确的“主持”连接,并打开需求的服务器套接字以让其他设备可以简单地启动连接。

注意:如果两个设备没有进行过配对,那么Android框架会在连接过程中自动显示配对请求通知或对话框给用户,如图3所示。所以当尝试连接设备时,你的应用程序不需要关注设备是否被配对。你的RFCOMM连接尝试将阻塞,直到用户已成功配对,或者如果用户拒绝配对,如果配对失败或者超时就会失败。



关于UUID

通用唯一标识符(UUID)是用来唯一标识信息的标准化128位格式的字符串ID。 关于一个UUID最重要的一点是,它大到你可以选择任何随机值也不会发生冲突。 在这种情况下,它用来唯一标识应用程序的蓝牙服务。要获取UUID并在你的应用程序中使用,可以使用Web上的众多随机UUID生成器之一,然后通过fromString(String)初始化一个UUID



作为服务器连接

当你想连接两个设备,一个作为服务器必须担任公开的BluetoothServerSocket 服务器套接字的目的是监听传入的连接请求,当一个请求被接受时,提供一个连接BluetoothSocket 当从BluetoothServerSocket获得BluetoothSocket后 ,该BluetoothServerSocket可以(应该)被丢弃,除非你想接受更多的连接。

这里是建立一个服务器套接字并接受连接的基本步骤

  1. 通过调用listenUsingRfcommWithServiceRecord(String,UUID).获取BluetoothServerSocket

    该字符串是你服务的确认名称,系统会自动将它写入到设备上的一个新的Service Discovery Protocol(SDP)数据库条目(名称是任意的,可以简单地使用您的应用程序名称)。UUID包含在SDP条目中,且将作为与客户端设备连接协议的基础。也就是说,当客户端试图与此设备连接时,其将携带一个UUID唯一标识它要连接的服务这些的UUID必须匹配以使连接被接受(在下一步骤)。

  2. 开始调用accept()来监听连接请求

    这是一个阻塞调用过程。 直到任一连接被接受或者发生异常时才返回只有当远程设备发出的连接请求中包含的一个UUID与此监听服务器套接字中注册的一个相匹配时连接被接受如果成功,accept()将返回一个连接BluetoothSocket

  3. 除非你想接受更多的连接,否则调用close()

    这将释放服务器套接字及其所有资源,但不会关闭由accept()返回的连接BluetoothSocket,不像TCP / IP,RFCOMM每个通道同一时间只允许一个客户端连接,因此在多数情况下接受连接套接字之后调用BluetoothServerSocketclose()是有意义的

       accept()调用不应在主Activity的UI线程执行,因为它是一个阻塞调用,会阻止其它任何与应用程序的交互行为通常正确的做法是在您应用程序的一个新线程中使用BluetoothServerSocketBluetoothSocket来完成所有工作。要中止阻塞调用,如accept(),从另一线程调用BluetoothServerSocket(或BluetoothSocket)的close(),阻塞调用将立即返回。请注意,在BluetoothServerSocketBluetoothSocket里的所有方法是线程安全的。

例子

下面是接受传入连接的服务器组件的简单线程:

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 ,并启动连接。

这里的基本步骤:                                               

  1. 使用BluetoothDevice,通过调用createRfcommSocketToServiceRecord(UUID)得到BluetoothSocket

     这将初始化一个连接到BluetoothDevice 的BluetoothSocket​​。这里传递的UUID必须和打开了BluetoothServerSocket的服务器设备使用的UUID相匹配(通过listenUsingRfcommWithServiceRecord(String, UUID)) 。使用相同的UUID是一个简单将UUID字符串硬编码到您的应用程序的事情,然后在服务器端和客户端的代码都引用它。
  2. 通过调用connect()创建连接

      在调用时,系统会在远程设备上执行SDP查找以匹配UUID。 如果查找成功且远程设备接受连接,它会在连接过程中共享RFCOMM通道,connect()将返回。这种方法是一个阻塞调用。如果因任何原因,连接失败或connect()方法超时(约12秒后),那么它会抛出异常。
    由于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 来传输任意类型数据的通常步骤是这样的:

  1. 通过getInputStream()getOutputStream()获取InputStreamOutputStream,来处理通过套接字的传输

  2. 使用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的更多讨论,请参见健康设备规范 。

下面是用配置文件工作的基本步骤:

  1. 获取默认的适配器,如设置蓝牙中所述
  2. 使用getProfileProxy()建立与配置文件相关的配置文件代理对象的连接。在下面的例子中,配置文件代理对象是一个BluetoothHeadset实例
  3. 设置一个BluetoothProfile.ServiceListenerBluetoothProfile的IPC客户端与服务器连接或断开连接时,监听器会通知它们 。
  4. onServiceConnected()中得到一个配置文件代理对象的句柄。
  5. 一旦你拥有配置代理对象,你可以用它来监听连接的状态,并执行该配置文件相关的操作。

例如,下面的代码片段展示了如何连接到一个BluetoothHeadset代理对象,这样就可以控制耳机配置文件:

BluetoothHeadset mBluetoothHeadset; // Get the default adapterBluetoothAdapter 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,BluetoothHealthCallbackBluetoothHealthAppConfiguration ,这在基础中有描述 。

为了更好使用蓝牙健康API,理解下面这些关键HDP概念很有必要:

概念描述资源在HDP中定义的角色。 资源是一种健康设备,传输医疗数据(计重秤,血糖仪,温度计等)给智能设备如Android手机或平板电脑。接收器在HDP中定义的角色。 在HDP中,接收器是接收医疗数据的智能设备。在一个Android HDP应用中,接收器由一个BluetoothHealthAppConfiguration对象表示注册是指注册接收器到特定健康设备。连接指的是打开一个健康设备和智能设备之间的信道,例如Android手机或平板电脑。


创建HDP应用

以下是参与创建一个Android HDP应用程序的基本步骤:

  1. 获得一个BluetoothHealth代理对象的引用。

    类似普通耳机和A2DP功能的设备,你必须使用BluetoothProfile.ServiceListenerHEALTH配置类型来调用getProfileProxy(),建立与配置代理对象的连接。

  2. 创建BluetoothHealthCallback,注册一个应用程序配置(BluetoothHealthAppConfiguration充当健康接收器
  3. 建立到健康设备的连接。 有些设备将启动连接。有些设备不需要进行此步骤。
  4. 当成功地连接到一个健康设备,使用文件描述符来读/写健康设备。

    所接收的数据需要使用实现了IEEE 11073-XXXXX规格的健康管理器来解释。

  5. 完成后,关闭健康通道并取消注册应用程序。有扩展活动的通道也关闭。

对于说明了这些步骤的完整代码示例,请参阅蓝牙HDP (健康设备配置文件)


2 0