Android API Guides---Bluetooth

来源:互联网 发布:云计算加密发展方向 编辑:程序博客网 时间:2024/04/30 17:22

Bluetooth

Android平台包括蓝牙网络协议栈,它允许设备以无线方式与其他蓝牙设备进行数据交换的支持。应用程序框架提供了访问通过Android蓝牙API的蓝牙功能。这些API使应用程序无线方式连接到其它蓝牙设备,实现点对点和多点无线功能。


使用蓝牙的API,Android应用程序可以执行以下操作:


扫描其他蓝牙设备
查询本地蓝牙适配器配对的蓝牙设备
建立RFCOMM通道
连接到通过服务发现其他设备
传送数据和从其他设备
管理多个连接
本文介绍如何使用传统蓝牙。经典蓝牙是有关电池密集型操作,如流媒体和Android设备之间的通信是正确的选择。对于低功耗的要求蓝牙设备的Andr​​oid 4.3(API等级18)引入了低功耗蓝牙API支持。要了解更多信息,请参阅蓝牙低功耗。


基础


本文介绍了如何使用Android的蓝牙API来完成必要的四大任务,使用蓝牙通信:建立蓝牙,发现要么在当地配对或可用,连接设备的设备和设备之间的数据传输。


所有蓝牙API都是在android.bluetooth封装。这里有您需要创建蓝牙连接的类和接口的摘要:


BluetoothAdapter
代表本地蓝牙适配器(蓝牙无线电)。该BluetoothAdapter是入口点所有蓝牙互动。利用这一点,你会发现其他蓝牙设备,查询保税(配对)的设备列表,使用已知的MAC地址实例化一个BluetoothDevice类,并创建一个BluetoothServerSocket监听来自其他设备的通信。
BluetoothDevice类
表示远程蓝牙设备。使用这个请求通过绕装置的BluetoothSocket或查询的信息与远程设备的连接,如它的名称,地址,类别,和结合状态。
的BluetoothSocket
表示为蓝牙套接字接口(类似于TCP插座)。这是连接点,它允许应用程序通过InputStream和OutputStream其它蓝牙设备交换数据。
BluetoothServerSocket
表示侦听传入请求(类似于TCP ServerSocket的)一个开放的服务器套接字。为了连接两个Android设备,一台设备必须打开这个类的服务器套接字。当一个远程蓝牙设备建立连接请求到该装置中,当连接被接受的BluetoothServerSocket将返回一个连接的BluetoothSocket。
BluetoothClass
描述的一般特征和蓝牙设备的能力。这是一个只读设置定义设备的主要和次要设备类和它的服务性质。但是,这并不能可靠地描述了设备支持的所有蓝牙配置文件和服务,而且是作为一个提示设备类型非常有用。
BluetoothProfile
表示蓝牙配置文件的接口。蓝牙配置文件是设备间基于蓝牙的通信的无线接口规范。一个例子是免提模式。对于配置文件的详细讨论,请参阅使用配置文件
蓝牙耳机
蓝牙耳机提供了支持,与手机一起使用。这包括蓝牙耳机和免提(V1.5)型材。
BluetoothA2dp
如何定义高品质音频,可从流一个设备到另一个通过蓝牙连接。 “A2DP”代表高级音频传输模式。
BluetoothHealth
表示控制蓝牙服务医疗设备规范代理。
BluetoothHealthCallback
您用来实现BluetoothHealth回调的一个抽象类。您必须扩展这个类,并实现回调方法来接收有关在应用程序的注册状态和蓝牙信道状态的变化更新。
BluetoothHealthAppConfiguration
表示蓝牙医疗第三方应用注册与远程蓝牙设备的健康通信的应用程序配置。
BluetoothProfile.ServiceListener
该通知时,他们已经被连接到或从服务断开BluetoothProfile的IPC客户端的接口(即,运行一个特定的轮廓内部服务)。
蓝牙权限


为了使用应用程序中的蓝牙功能,您必须声明蓝牙权限蓝牙。你需要这个权限才能执行任何蓝牙通信,比如请求连接,接受连接,传输数据。


如果你希望你的应用程序来启动设备发现或操纵蓝牙设置,您还必须声明BLUETOOTH_ADMIN许可。大多数应用程序需要这个权限仅用于发现本地的蓝牙设备的能力。通过此权限授予其他的能力不应该被使用,除非应用程序是一个“电源管理”,将根据用户的请求修改蓝牙设置。注:如果您使用BLUETOOTH_ADMIN许可,则还必须具备蓝牙权限。


声明在您的应用程序清单文件的蓝牙权限(S)。例如:

 <manifest ... >  <uses-permission android:name="android.permission.BLUETOOTH" />  ...</manifest>
请参阅有关声明应用程序权限的详细信息<使用许可权>引用。
设置蓝牙
图1:启用蓝牙对话框。
在应用程序能够通过蓝牙通信,您需要验证支持蓝牙设备上,如果是这样,请确保它已启用。
如果不支持蓝牙,那么你应该优雅地禁用任何蓝牙功能。如果支持蓝牙,但被禁用,则可以要求用户启用蓝牙无需离开应用程序。这种设置两个步骤来完成,使用BluetoothAdapter。
获取BluetoothAdapter
该BluetoothAdapter需要的任何和所有蓝牙活动。要获得BluetoothAdapter,调用静态getDefaultAdapter()方法。返回表示设备自身的蓝牙适配器(蓝牙无线电)一BluetoothAdapter。还有一个蓝牙适配器为整个系统和应用程序可以使用这个对象与它进行交互。如果getDefaultAdapter()返回null,则该设备不支持蓝牙和你的故事在这里结束。例如:

BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();if (mBluetoothAdapter == null) {    // Device does not support Bluetooth}
启用蓝牙
接下来,您需要确保蓝牙已启用。调用isEnabled()检查蓝牙当前是否启用。如果此方法返回false,那么蓝牙被禁用。要请求蓝牙启用,调用startActivityForResult()与ACTION_REQUEST_ENABLE行动意图。这将发出一个请求通过系统设置来启用蓝牙(无需停止应用程序)。 例如:

 if (!mBluetoothAdapter.isEnabled()) {    Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);    startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);}
将出现一个对话框,要求用户权限才能启用蓝牙功能,如图1。如果用户回答“是”,系统将开始启用蓝牙,一旦该过程完成后(或失败),焦点将返回到应用程序。
)传递给startActivityForResult(该REQUEST_ENABLE_BT常量是一个本地定义整数(必须大于0更大),系统传回在你的onActivityResult()实现为requestCode参数。
如果启用蓝牙成功,你的活动收到了的onActivityResult()回调RESULT_OK结果代码。如果蓝牙没有由于启用错误(或用户回答“否”),那么结果代码RESULT_CANCELED。
或者,您的应用程序还可以侦听广播ACTION_STATE_CHANGED意图,这每当蓝牙状态发生变化,系统将播出。此广播包含了额外的字段EXTRA_STATE和EXTRA以前的状态,包含新老蓝牙状态,分别为。这些额外的字段可能的值是STATE_TURNING_ON,STATE_ON,STATE_TURNING_OFF和STATE_OFF。侦听此广播可以检测到您的应用程序正在运行,而蓝牙状态所做的更改非常有用。
提示:启用可发现会自动启用蓝牙。如果您计划执行蓝牙活动前始终使设备可发现,你可以跳过上面的步骤2。阅读关于启用可发现,下文。
查找设备
使用BluetoothAdapter,可以发现无论是通过设备发现,或通过查询配对(保税)的设备列表远程蓝牙设备。
设备发现的是,搜索蓝牙设备的局部区域​​,然后请求关于每一个的一些信息(这有时被称为“发现”,“查询”或“扫描”)的扫描过程。然而,只有当它当前已启用可被发现局部区域内的蓝牙设备会以发现请求作出响应。如果一个设备是可发现,它会通过共享一些信息,例如设备名称,类和其特有的MAC地址的发现请求作出响应。使用该信息,该设备执行发现随后可以选择发起对所发现的设备的连接。
一旦连接与用于第一次的远程设备制成,配对请求被自动呈现给用户。当一个设备被配对,关于该设备的基本信息(例如设备名称,类和MAC地址)被保存,并且可以使用蓝牙API来读取。使用公知的MAC地址为远程设备中,连接可以用它在任何时间发起而不执行发现(假设设备在范围内)。
记得有被配对并连接之间的差。进行配对意味着两个设备都知道彼此的存在,具有可以用于认证的共享链接密钥,并且能够建立与彼此的加密连接的。要连接意味着设备目前共享一个RFCOMM信道,并且能够彼此传输数据。目前Android蓝牙API的要求,可以建立一个RFCOMM连接之前配对的设备。 (当你开始使用蓝牙API的一个加密的连接会自动进行配对。)
以下部分描述了如何找到已配对的设备,或使用设备发现发现新的设备。
注:Android系统的设备默认情况下不被发现。用户可以使设备可发现在有限的时间通过系统设置,或者应用程序可以要求用户能够发现能力,而无需离开应用程序。如何启用可发现在下面讨论。
查询配对设备
执行设备发现之前,看到了它的价值查询组配对的设备,如果需要的设备是已知的。要做到这一点,调用getBondedDevices()。这将返回一组表示配对设备BluetoothDevices的。例如,您可以查询所有配对设备,然后显示每个设备的用户名,使用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秒的查询扫描,随后每发现设备检索其蓝牙名称的页面扫描。
您的应用程序必须注册为ACTION_FOUND意图一个BroadcastReceiver接收关于发现的每个设备的信息。对于每个设备,该系统将播出ACTION_FOUND意图。此意向进行额外的领域和EXTRA_DEVICE额外的类,分别包含蓝牙设备和BluetoothClass。例如,下面是当设备被发现,你如何注册处理广播:

// 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(意向,INT)与ACTION_REQUEST_DISCOVERABLE行动意图。这将发出一个请求,以使通过系统设置发现模式(无需停止应用程序)。默认情况下,该设备将成为可发现120秒。您可以通过添加EXTRA_DISCOVERABLE_DURATION意向额外的定义不同的持续时间。一个应用程序可以设置的最长持续时间为3600秒,值为0意味着设备总是发现。低于0或高于3600的任何值会自动设置为120秒)。例如,该片段设置期限为300:

Intent discoverableIntent = newIntent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);startActivity(discoverableIntent);
将显示一个对话框,要求用户权限,使设备可发现,如图2。如果用户回答“是”,则该设备将成为发现了指定的时间量。那么你的活动将接收呼叫到的onActivityResult())回调,结果代码等于该设备是可发现的持续时间。如果用户回答“否”,或者如果发生错误,结果代码将被RESULT_CANCELED。
注意:如果蓝牙尚未在设备上启用,则使设备可发现会自动启用蓝牙。
该装置会悄悄地留在发现模式指定的时间。如果您希望得到通知时,发现模式发生了变化,你可以注册为ACTION_SCAN_MODE_CHANGED意图广播接收器。这将包含额外的领域EXTRA SCAN_MODE和EXTRA_PREVIOUS_SCAN_MODE,它告诉你新老扫描模式,分别为。对于每一个可能的值有SCAN_MODE连接发现,SCAN_MODE_CONNECTABLE或SCAN_MODE_NONE,这表明该设备是可发现模式,而不是在发现模式,但仍然能够接收发现模式连接,或者没有,无法分别接收连接。
不需要启用设备可发现如果将发起到远程设备的连接。启用可发现,当你想你的应用程序托管的服务器套接字将接受传入的连接仅仅是必要的,因为远程设备必须能够发现设备才可以发起连接。

连接设备


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


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


图3:蓝牙配对对话框。
一种实现方法是自动准备每个设备作为服务器,让每个人都有一台服务器套接字打开并侦听连接。然后或者可以发起与其他的连接,并成为客户端。另外,一台设备可以明确的“主机”的连接,并打开需求的服务器插座和其他设备可以简单地启动连接。


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


连接作为服务器


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


关于UUID


通用唯一标识符(UUID)是用来唯一标识信息的字符串ID标准化的128位格式。一个UUID的一点是,它足够大,你可以选择任何随机的,也不会发生冲突。在这种情况下,它是用来唯一标识应用程序的蓝牙服务。要获得UUID与你的应用程序中使用,则可以使用Web上的许多随机UUID生成器之一,则初始化fromString(String)将UUID。
这里是基本的程序建立一个服务器套接字并接受连接:


通过调用listenUsingRfcommWithServiceRecord(字符串,UUID)获取BluetoothServerSocket。
该字符串是你的服务,系统会自动写入到一个新的服务发现协议在设备上(SDP)数据库条目的识别名称(名称是任意的,可以简单地将您的应用程序名称)。的UUID也包含在SDP条目和将用于与所述客户端设备的连接协定的基础。也就是说,当客户端试图与此设备连接,其将携带唯一标识与它要连接的服务一个UUID。这些的UUID必须以使连接被接受(在下一步骤)相匹配。
开始通过调用accept()方法监听连接请求。
这是一个阻塞调用。当任一连接被接受或者已经发生异常它将返回。一个连接被接受,只有当远程设备已派出匹配与此监听套接字服务器中注册的一个UUID的连接请求。如果成功,accept()方法将返回一个连接的BluetoothSocket。
除非你想接受更多的连接,调用close()。
这将释放服务器插槽及其所有资源,但不会关闭一个已经被接受返回的连接的BluetoothSocket()。不像TCP / IP,RFCOMM只允许每个通道的一个连接的客户端的时间,因此,在大多数情况下,它是有道理的接受连接套接字后立即关闭()的调用BluetoothServerSocket。
的接受()调用不应该在主活动UI线程,因为它是一个阻塞调用,并防止与应用程序的任何其它交互来执行。它通常情理之中的事了BluetoothServerSocket或全部的BluetoothSocket工作,你的应用程序管理的一个新的线程。要中止阻塞调用,如接受(),从另一个线程调用close()在BluetoothServerSocket(或的BluetoothSocket)和阻塞调用将立即返回。需要注意的是在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()(当你从客户端做的)。
管理器连接插座()是在将启动该线程用于传送数据,这是在大约管理一个连接部分中所讨论的应用的一个虚构的方法。
通常你应该尽快关闭BluetoothServerSocket为你做侦听传入连接。在这个例子中,接近()被尽快的BluetoothSocket获取调用。您可能还需要提供你的线程公开的方法,可以在你需要停止监听服务器套接字上的事件关闭的BluetoothSocket私人。
连接作为客户端
为了与远程设备(设备保持一个开放的服务器套接字)的连接,您必须首先获取表示远程设备BluetoothDevice类的对象。 (获取一个BluetoothDevice类是覆盖在关于查找设备上面的部分。)然后,您必须使用BluetoothDevice类收购的BluetoothSocket,并启动连接。
这里的基本步骤:
使用BluetoothDevice类,通过调用createRfcommSocketToServiceRecord(UUID)获得的BluetoothSocket。
这一个初始化的BluetoothSocket将连接到BluetoothDevice类。这里传递的UUID必须开业时其BluetoothServerSocket(带listenUsingRfcommWithServiceRecord(字符串,UUID))由服务器设备使用的UUID相匹配。使用相同的UUID是一个简单的硬编码的UUID字符串到您的应用程序,然后从服务器端和客户端的代码都引用它的问题。
启动通过调用连接的连接()。
在此呼叫时,系统会以匹配的UUID远程设备上执行的SDP查找。如果查找成功与远程设备接受连接,它会共享连接过程中使用和connect()将返回RFCOMM通道。这种方法是一个阻塞调用。如果因任何原因,连接失败或者connect()方法超时(约12秒后),那么它会抛出异常。
由于连接()是一个阻塞调用,这个连接过程应始终在一个线程执行从主线程的活动分开。
注意:您应始终确保设备未进行设备发现,当你调用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,一般方法来传输任意数据是简单的:


获得通过套接字句柄传输的InputStream和OutputStream,通过的getInputStream()和的getOutputStream(),分别为。
具有读取读取和写入数据流(字节[])和写(字节[])。
而已。


有,当然,实现的细节要考虑。首先,你应该使用一个专用的线程所有流读取和写入。这是重要的,因为这两种读取(字节[])和写(字节[])方法阻塞调用。阅读(字节[])将阻塞,直到有东西从流中读取。写(字节[])通常不阻塞,但如果远程设备没有调用read(字节[])的速度不够快,并在中间缓冲区已满可以阻止流量控制。所以,你在线程主循环应专门用于从InputStream读取。在线程一个单独的公共方法可以用于启动写入到输出流。





这里有一个如何这可能外观的示例:

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的。当读取(字节[])与从流的字节返回时,数据是使用从父类中的成员处理程序发送到主活性。然后它返回,并等待从流更多的字节。


发送传出数据是从调用的主要活动线程的write()方法,并在字节传递给发送一样简单。然后,此方法简单地调用写(字节[])的数据发送到远程设备。


线程的取消()方法是重要的,这样的连接可以在任何时候,通过关闭所述的BluetoothSocket被终止。当你使用蓝牙连接来完成这应始终被调用。


对于使用蓝牙API的演示,请参见蓝牙聊天示例应用程序。


使用配置文件


在Android 3.0的开始,蓝牙API包括与蓝牙配置文件的工作的支持。蓝牙配置文件是设备间基于蓝牙的通信的无线接口规范。一个例子是免提模式。对于手机连接到一个无线耳机,两个设备必须支持免提模式。


您可以实现接口BluetoothProfile编写自己的类来支持特定的Bluetooth配置文件。 Android的蓝牙API提供实现以下蓝牙规范:


耳机。耳机配置文件提供与手机使用蓝牙耳机的支持。机器人提供BluetoothHeadset类,它是对经由进程间通信(IPC)控制所述蓝牙耳机服务的代理。这包括蓝牙耳机和免提(V1.5)型材。该BluetoothHeadset类包括AT命令的支持。有关此主题的更多讨论,请参阅供应商特定的AT命令
A2DP。高级音频传输模式(A2DP)配置文件定义了如何高品质的音频文件可以被串流从一个设备到另一个通过蓝牙连接。机器人提供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。此侦听通知BluetoothProfile IPC客户端时,他们已经连接或从服务断开。
在onServiceConnected(),得到一个处理配置文件代理对象。
一旦你的轮廓代理对象,你可以用它来监视连接的状态,并执行相关的该配置文件等操作。
例如,下面的代码片段展示了如何连接到一个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,BluetoothHealthCallback和BluetoothHealthAppConfiguration,这在基础知识介绍。


在使用蓝牙API健康,它有助于理解这些关键概念HDP:


概念说明
源HDP定义的角色。源是一种健康的设备,传输医疗数据(计重秤,血糖仪,温度计等),智能设备如Android手机或平板电脑。
下沉HDP定义的角色。在HDP,水槽是接收医疗数据智能设备。在一个Android应用程序HDP,水槽由BluetoothHealthAppConfiguration对象表示。
注册是指注册水槽特定保健设备。
连接是指打开保健设备与智能设备之间的信道,例如Android手机或平板电脑。
创建HDP应用


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


获取到BluetoothHealth代理对象的引用。
类似普通耳机和A2DP功能的设备,你必须调用getProfileProxy()与BluetoothProfile.ServiceListener和健康状况的类型,建立与轮廓的代理对象的连接。
创建BluetoothHealthCallback并注册充当健康水槽应用程序配置(BluetoothHealthAppConfiguration)。
建立到卫生设备的连接。有些设备将启动连接。它是不需要进行此步骤的那些设备。
当成功地连接到一个医疗设备,读/写使用文件描述符卫生设备。
所接收的数据需要使用它实现了IEEE 11073-XXXXX规格健康管理器来解释。
完成后,关闭健康频道和注销应用程序。当有扩展活动的通道也关闭。
对于说明了这些步骤的完整代码示例,请参阅蓝牙HDP(健康设备配置文件)。

0 0