BlueTooth
根据官方DOC翻译
(本人英语4级没过,看不懂请自行脑补)
Bluetooth API操作流程:
- 搜索其他蓝牙设备
- 查询本地匹配器已经匹配的蓝牙设备
- 建立RFCOMM通道
- 通过Service发现并连接其他设备
- 与其他蓝牙设备进行数据交互
- 管理多个连接
Permission:
- android.permission.BLUETOOTH:Allows applications to connect to paired bluetooth devices
- android.permission.BLUETOOTH_ADMIN:Allows applications to discover and pair bluetooth devices
Setting Up Bluetooth:
确保设备支持蓝牙模块,并已开启
- 获取BluetoothAdapter。整个系统只有一个BluetoothAdapter。如果返回null表示设备不支持蓝牙。
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
// 设备是否支持蓝牙
if (mBluetoothAdapter == null) {
Toast.makeText(this, R.string.not_support, Toast.LENGTH_SHORT).show();
}
- 开启蓝牙:如果没用开启蓝牙,会弹出系统对话框,请求用户开启蓝牙功能。如果开启成功,则返回:Activity.RESULT_OK,否则返回:Activity.RESULT_CANCELED。
- 监听状态:你可以通过监听BluetoothAdapter. ACTION_STATE_CHANGED广播获得蓝牙状态变化信息。广播包含以下额外字段: EXTRA_STATE和EXTRA_PREVIOUS_STATE。常见值包括:STATE_TURNING_ON,STATE_ON,STATE_TURNING_OFF和STATE_OFF。
Finding Devices:
使用BluetoothAdapter,你可以找到远程蓝牙设备。通过查找设备,或查询配对(绑定)的设备列表。查找设备会搜索区域内的蓝牙设备,如果该设备设定为可被发现,则会返回一些信息,通过该信息则可连接设备。当首次建立连接,该设备信息会被保存并可通过API获得,使用MAC地址不需要重新搜索设备(假设设备在可连接范围内)。
- 配对(Pair): 意味着两个设备都知道彼此的存在,有一个共同的链路密钥,可用于进行认证,并且能够建立与彼此的加密连接的。
- 连接(Connect):该装置当前共享一个RFCOMM信道,并能够相互传送数据。Android Bluetooth API's要求设备配对前需要先建立RFCOMM连接(当你通过API建立加密连接配对会自动执行)。
Querying paired devices:
通过getBondedDevices()可返回一组蓝牙配对清单(BluetoothDevice)。
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices(); if (pairedDevices.size() > 0) { mDeviceInfoList = new ArrayList<HashMap<String, Object>>(); for (BluetoothDevice device : pairedDevices) { mDeviceInfoList.add(device.getName() + "\n" + device.getAddress()); } }
Discovering devices:
通过startDiscovery()可搜索设备,此方法会立即返回Boolean提示是否成功开始搜索。这是一个异步操作,搜索时间大约12秒然后会返回发现的蓝牙设备信息。对于每个搜索到的设备,系统会广播一个ACTION_FOUND Intent,装载的信息包括:EXTRA_DEVICE和EXTRA_CLASS(包含BluetoothDevice和BluetoothClass)。所以你需要注册BroadcastReceiver接收ACTION_FOUND Intent。
// 搜索到蓝牙设备时接收广播提示信息 IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); registerReceiver(mReceiver, filter); // 搜索完成时接收广播提示信息 filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); registerReceiver(mReceiver, filter); private BroadcastReceiver mReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // TODO Auto-generated method stub String action = intent.getAction(); if (BluetoothDevice.ACTION_FOUND.equals(action)) { // 如果查找到设备 BluetoothDevice device = intent .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED .equals(action)) { // 查找完成 } } }; protected void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); if (mBluetoothAdapter != null) { // 停止搜索设备 mBluetoothAdapter.cancelDiscovery(); } // 注销广播监听 this.unregisterReceiver(mReceiver); }
需要注意的是,搜索蓝牙设备非常消耗资源,所以一旦找到对应设备,应该使用cancelDiscovery()停止搜索。如果你已有该设备的连接再执行搜索会节约带宽。
如果你想使本地设备能被其他设备检测到,调用startActivityForResult(Intent,INT)和ACTION_REQUEST_DISCOVERABLE action Intent.。这将发出一个请求,以使通过系统设置发现模式(无需停止应用程序)。默认可见时间为120秒,也可以能过EXTRA_DISCOVERABLE_DURATION Intent extra来修改可见时间(最大值为3600秒,0表示设备始终可见)。系统会弹出对话框提示用户设置可见,并调用onActivityResult()返回结果,如果用户选择确定,则返回时间,如果用户选择否或者出现错误,则返回RESULT_CANCELED。如果未开启蓝牙,使设备可见会自动开启。如果你希望监听到设备可见状态的改变,可以注册BroadcastReceiver ACTION_SCAN_MODE_CHANGED Intent,包含:EXTRA_SCAN_MODE和EXTRA_PREVIOUS_SCAN_MODE。
// 设置设备对外可见,持续30秒 Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE); intent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300); startActivityForResult(intent, REQUEST_DISCOVERABLE);
Connectting Devices:
服务器端创建Server Socket,客户端使用服务器端的MAC地址创建连接,当服务器端与与客户端连接时,双方的BluetoothSocket会在同一RFCOMM通道中。此时双方都各自拥有input和output stream,并能实现数据传输。服务器端和客户端分别以不同的方式获得BluetoothSocket。服务器端:当传入连接Accepted时,接收到BluetoothSocket;
客户端:当客户端打开RFCOMM通道时,接收到BluetoothSocket。
有一种实现方法是每台设备均准备作为服务器,均打开Server Socket并监听连接。然后其它设备则以客户端的形式创建连接。
注意:如果两个设备先前未配对,Android框架将发送配对请求通知对话框给用户,应用程序不需要关注的设备是否被配对。您的RFCOMM连接尝试将阻塞,直到用户成功配对,或者如果用户拒绝配对,或者如果配对失败或者超时就会失败。
Connecting as a server:
当你尝试连接两台设备,其中一台需要充当服务器端打开并持有BluetoothServerSocket。Server Socket目的是监听来自客户端的连接请求,当客户端的连接请求被通过,服务器端将提供BluetoothSocket。一旦取得BluetoothSocket,BluetoothServerSocket应该被移除,除非你打算接受更多连接。
设置Server Socket和接收连接请求的基本流程:
- 使用listenUsingRfcommWithServiceRecord(String, UUID)获得BluetoothServerSocket。String是服务器端的名称。UUID它是用来唯一标识应用程序的蓝牙服务。如果与蓝牙串口(Bluetooth serial board)连接可以尝试使用标准的SPP UUID:00001101-0000-1000-8000-00805F9B34FB。但是如果连接的是Android Peer,你需要生成自己的UUID。
- 通过accept()开始监听连接请求。这是一个阻塞调用,当任意连接被同意或者发生异常时则会退出。只有当客户端发送连接请求,并且请求数据中的UUID与Server Socket的UUID才能被同意。如果连接成功,则返回BluetoothSocket。
- 除非你打算接受其他的连接,否则连接成功后,调用close()。这将释放Server Socket及其所有资源,但不会关闭accept()返回的BluetoothSocket。RFCOMM只允许每个通道一个连接的客户端的时间,因此,在大多数情况下,在BluetoothServerSocket通过连接请求后立即调用close()。
- Accept()不能运行于主线程,应该创建子线程执行些方法,另外BluetoothServerSocket和BluetoothSocket所有方法都是线程安全的。
private class AcceptThread extends Thread { private final BluetoothServerSocket mmServerSocket; private String mSocketType; public AcceptThread(boolean secure) { BluetoothServerSocket tmp = null; mSocketType = secure ? "Secure" : "Insecure"; // 创建一个新的server socket监听,secure表示是否使用加密方式 try { if (secure) { tmp = mAdapter.listenUsingRfcommWithServiceRecord( NAME_SECURE, MY_UUID_SECURE); } else { tmp = mAdapter.listenUsingInsecureRfcommWithServiceRecord( NAME_INSECURE, MY_UUID_INSECURE); } } catch (IOException e) { } mmServerSocket = tmp; } public void run() { BluetoothSocket socket = null; // 保持监听,直到Socket返回,或者中止 while (true) { try { // 这是一个阻塞方法,只会返回成功,否则抛出异常 socket = mmServerSocket.accept(); } catch (IOException e) { break; } // 如果连接成功 if (socket != null) { // 新创建一个线程使用Socket manageConnectedSocket (socket); mmServerSocket.close(); break; } } } public void cancel() { try { mmServerSocket.close(); } catch (IOException e) { } } }
请注意,当accept()返回的BluetoothSocket,socket已经连接,所以客户端不需要调用connect()。manageConnectedSocket()用于启动线程传输数据。你可能还需要在线程里提供public方法用于关闭BluetoothSocket。
Connecting as a client:
客户端连接服务器端首先要从服务器端获得BluetoothDevice(参考Finding Devices),然后从BluetoothDevice中获得BluetoothSocket并创建连接。基本流程如下:
- 通过createRfcommSocketToServiceRecord(UUID)从BluetoothDevice中获得BluetoothSocket。UUID必须与服务器端的UUID一致。
- 通过connect()启动连接。connect()连接服务器时,服务器端会匹配UUID,如果匹配成功,服务器会同意连接请求并提供RFCOMM能道,此时connect()会返回。Connect()是阻塞方法,所以需要创建子线程执行,如果连接出现任何问题或者超时(12秒),将会抛出错误。需要注意的是,调用connect()时,确保已经停止搜索(cancelDiscovery()),否则性能会明显降低。也可以使用isDiscovering()检查是否正在搜索中。
private class ConnectThread extends Thread { private final BluetoothSocket mmSocket; private final BluetoothDevice mmDevice; private String mSocketType; public ConnectThread(BluetoothDevice device, boolean secure) { mmDevice = device; BluetoothSocket tmp = null; mSocketType = secure ? "Secure" : "Insecure"; // 通过BluetoothDevel和UUID获得BluetoothSocket try { if (secure) { // 使用加密方式 tmp = device .createRfcommSocketToServiceRecord(MY_UUID_SECURE); } else { // 不使用加密方式,需要API Level 10支持 tmp = device .createInsecureRfcommSocketToServiceRecord(MY_UUID_INSECURE); } } catch (IOException e) { } mmSocket = tmp; } public void run() { // 停止搜索,搜索设备会占用大量资源 mAdapter.cancelDiscovery(); // 创建Bluetooth连接 try { // connect阻塞方法,只会返回成功, 否则抛出异常 mmSocket.connect(); } catch (IOException e) { try { mmSocket.close(); } catch (IOException e2) { } return; } // 完成后重置线程 synchronized (BluetoothChatService.this) { mConnectThread = null; } // 创建一个独立的线程使用Sokcet manageConnectedSocket(mmSocket); } public void cancel() { try { mmSocket.close(); } catch (IOException e) { } } }
当使用完BluetoothSocket,调用close()关闭连接释放资源。
Managing a Connection:
当两(多)台设备连接成功后,两台设备都持有BluetoothSocket,这时可以进行数据交互了。使用BluetoothSocket传输数据流程:
- 通过Socket使用InputStream和OutputStream数据。
- 通过read(byte[])和write(byte[])读写数据流。需要注意的是,你要为读写流创建线程,因为read(byte[])和write(byte[])是阻塞方法,read(byte[])会一直阻塞直到所有数据被读出;write(byte[])通常不会阻塞,但如果远和设备没有迅速调用read(byte[])又或者缓冲区已经满,则会造成阻塞。所以你的线程run主要用于读取InputStream。另外提供public方法,以启动写入输出流。
private class ConnectedThread extends Thread { private final BluetoothSocket mmSocket; private final InputStream mmInStream; private final OutputStream mmOutStream; public ConnectedThread(BluetoothSocket socket, String socketType) { mmSocket = socket; InputStream tmpIn = null; OutputStream tmpOut = null; // 获取输入和输出流,使用临时对象,因为成员流是final的 try { tmpIn = socket.getInputStream(); tmpOut = socket.getOutputStream(); } catch (IOException e) { } mmInStream = tmpIn; mmOutStream = tmpOut; } public void run() { Log.i(TAG, "BEGIN mConnectedThread"); byte[] buffer = new byte[1024]; int bytes; // 当连接成功后,一直监听InputStream while (true) { try { // 从InputStream读取数据 bytes = mmInStream.read(buffer); // 发送获得的数据至UI Activity mHandler.obtainMessage(BluetoothChat.MESSAGE_READ, bytes, -1, buffer).sendToTarget(); } catch (IOException e) { break; } } } // 写入数据并发送 public void write(byte[] buffer) { try { mmOutStream.write(buffer); } catch (IOException e) { } } // 关闭连接 public void cancel() { try { mmSocket.close(); } catch (IOException e) { } } }
Working with Profiles:
从Android 3.0开始,Bluetooth API包括了对Bluetooth Profiles的支持。Bluetooth Profile是一种基于设备间的蓝牙通信无线协议规范。其中一个例子是Hands-Free profile(免提模式),手机连接无线耳机,两个设备都必须要支持Hands-Free profile。你可以通过实现BluetoothProfile接口编写自己的类来支持特定的Bluetooth profiles。
- Headset:Headset profile提供对手机使用蓝牙耳机的支持。Android提供BluetoothHeadset类,通过进程通讯(IPC)代理控制蓝牙耳机服务。这里包括蓝牙耳机和免提(v1.5)模式。BluetoothHeadset包括支持AT命令。
- A2DP:The Advanced Audio Distribution Profile (A2DP高级音频传输模式)定义了多高质量的音频可以通过蓝牙传输。Android提供BluetoothA2dp类,通过进程通讯(IPC)代理控制蓝牙A2DP服务。
- Health Device:Android 4.0 (API level 14) 支持Bluetooth Health Device Profile (HDP)。它使你能够创建应用,通过蓝牙与Health Device通讯。例如:heart-rate monitors(心脏速率监视器),blood meters(血压计),thermometers(体温计),scales(身体均衡器),等等。
基本步骤如下:
- 获得Adapter(参考Setting Up Bluetooth)
- 通过方法getProfileProxy()建立与模式关联的理对象的连接。在下面的例子中,配置文件代理对象是BluetoothHeadset的一个实例。
- 设置BluetoothProfile.ServiceListener用于监听服务器端连接或断开连接的事件,并通知BluetoothProfile IPC。
- 在方法onServiceConnected()中获得profile proxy的handle对象。
- 一旦获得profile prox对象,你可以用它来监测连接状态,并进行其它相关的操作。
例如,以下代码显示了如何连接到一个BluetoothHeadset代理对象,这样就可以控制Headset profile:
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);
Vendor-specific AT commands:
从Android 3.0开始应用程序可以通过注册来接收来自耳机的pre-defined vendor-specific AT commands系统广播(例如:Plantronics +XEVENT command),例如应用程序可以通过广播接收所连接设备的电量水平,并通知用户。创建广播接收器并通过ACTION_VENDOR_SPECIFIC_HEADSET_EVENT intent处理来自耳机的vendor-specific AT commands。
Health Device Profile:
相关推荐
Bluetooth Core v5.4 Bluetooth Core v5.4是Bluetooth SIG(Bluetooth Special Interest Group)发布的一份专有的核心规范,用于定义创建可互操作的蓝牙设备所需的技术。该规范的版本号为v5.4,发布日期为2023年1月...
Bluetooth? Framework is a VCL and ActiveX components library, which allows you to add Bluetooth?, IrDA?, Serial and ActiveSync? support into your applications. The Bluetooth? Framework is not an end...
Java Bluetooth API.pdf文档可能包含了这些概念的详细解释、示例代码以及API参考,是学习和开发蓝牙应用的重要资源。建议仔细阅读该文档,结合实践来提升蓝牙编程能力。通过熟练掌握Java蓝牙API,你可以开发出各种...
在"ros_gps2bluetooth"项目中,其核心功能是实现从智能手机获取GPS数据并通过蓝牙将其传输到计算机上。这在机器人系统中非常有用,因为手机GPS模块通常比嵌入式计算机或机器人平台上的GPS接收器更便宜且易于获取。 ...
蓝牙低功耗(Bluetooth Low Energy, 简称BLE或Bluetooth LE)是一种现代通信技术,广泛应用于移动设备,如iOS和Android智能手机和平板电脑。在本文中,我们将深入探讨BLE在Unity3D环境中的应用,以及如何在iOS和...
该文档是一份关于Unity Bluetooth LE Plugin for Android的技术文档,主要针对的是在Unity中开发Android低功耗蓝牙功能。文档中介绍和解释了如何使用这个插件,提供了一些版本更新的详细信息,以及设置和安装插件的...
A radical new departure from conventional Bluetooth technology, Bluetooth Low Energy (BLE) will enable a whole new generation of wireless applications in industries ranging from healthcare to ...
- **Android Bluetooth框架层**:位于Java层,包含`android.bluetooth`包中的各种类,如`BluetoothAdapter`, `BluetoothDevice`, `BluetoothGatt`等,提供了开发者友好的API。 - **蓝牙应用程序**:使用Android蓝牙...
在Linux系统中,Bluetooth编程是一项重要的技能,尤其对于开发物联网(IoT)设备或需要无线通信的项目至关重要。本文将深入探讨"实战Linux Bluetooth编程"的主题,主要关注blueZ库的使用,它是一个官方支持的Linux ...
标题中的"Bluetooth_javascript_bluetooth_yearg9h_"暗示了我们将在JavaScript环境下探讨如何利用蓝牙技术进行设备交互。描述进一步证实了这个主题,说明我们将学习如何通过JavaScript来搜索、连接蓝牙设备,以及...
### Linux Bluetooth 编程介绍 #### 一、安装软件及环境配置 在开始Linux下的蓝牙编程之前,首先需要确保系统中已经安装了必要的软件。主要包括: 1. **GCC**: GCC (GNU Compiler Collection) 是用于编译C语言...
在Android系统中,Bluetooth OPP(Object Push Profile)是一种用于设备间传输小文件的协议,它允许用户方便地发送图片、联系人、日历事件等数据。这篇博客文章的附件是针对一个特定的Android设备(可能是Xiaomi设备...
Android Bluetooth 框架知识 Android Bluetooth 框架知识是指在 Android 系统中,关于 Bluetooth 技术的架构和实现细节。Android 4.2 和 4.3 中的 Bluetooth 框架知识是特别重要的,因为在这个版本中,Android 引入...
Toshiba Bluetooth Stack v8.00.03(T) 补丁,Toshiba Bluetooth Stack v8.00.04(T)也可以用。 日发现东芝的蓝牙驱动软件升级到 v8.00.03(T) 版本了,新版本除了修复了一些BUG,更是增加了对蓝牙3.0的支持,建议使用...
【VC2010 蓝牙(Bluetooth)设备查找】是关于利用Windows API进行蓝牙设备搜索和串口通信的编程实例。这个项目是专为Visual Studio 2010设计的,允许开发者通过C++语言来实现蓝牙设备的识别和通信功能。下面将详细介绍...
《C# Windows Bluetooth LE 应用开发详解——以BluetoothLEExplorer为例》 在现代物联网(IoT)领域,蓝牙低功耗(BLE, Bluetooth Low Energy)技术因其高效、低耗的特点,广泛应用于各种智能设备之间的小数据量通信。...
通过`navigator.bluetooth.requestDevice()`方法,开发者可以获取到用户选择的蓝牙设备。 2. **Service Workers**:为了在没有页面活动时仍能与蓝牙设备保持连接,可能使用了Service Workers。Service Workers允许...
"Bluetooth Library for Android 1.6.rar" 是一个针对Android平台的蓝牙库资源包,适用于版本1.6的Android系统。这个压缩包包含了帮助开发者集成蓝牙功能到他们的应用程序的各种资源。 API.TXT 文件很可能是该蓝牙...
在Windows操作系统中,蓝牙通信是通过一套名为Bluetooth API的接口实现的。这些API提供了与蓝牙设备交互的各种功能,包括搜索设备、建立连接、传输数据、管理服务等。本资源包含了一个文档和一个封装好的蓝牙通信...
【Ellisys Bluetooth Analyzer】是专业级的蓝牙协议分析工具,专为开发者、测试工程师以及技术爱好者设计,用于深入理解、调试和优化蓝牙设备的性能。这款软件的强大之处在于其全面的功能,它不仅可以捕获蓝牙通信...