Android Bluetooth

目前低功耗短距离传输设备蓝牙已属于智能手机标配,这里就介绍一下Android设备上Bluetooth的简单连接使用、蓝牙的自组网/蓝牙的一对多连接。

蓝牙的通信和连接,在维基百科关于蓝牙的说明:https://en.wikipedia.org/wiki/Bluetooth#Communication_and_connection

**A master Bluetooth device can communicate with a maximum of seven devices in a piconet (an ad-hoc computer network using Bluetooth technology), though not all devices reach this maximum. The devices can switch roles, by agreement, and the slave can become the master (for example, a headset initiating a connection to a phone necessarily begins as master—as initiator of the connection—but may subsequently operate as slave).
The Bluetooth Core Specification provides for the connection of two or more piconets to form a scatternet, in which certain devices simultaneously play the master role in one piconet and the slave role in another.
At any given time, data can be transferred between the master and one other device (except for the little-used broadcast mode.[citation needed]) The master chooses which slave device to address; typically, it switches rapidly from one device to another in a round-robin fashion. Since it is the master that chooses which slave to address, whereas a slave is (in theory) supposed to listen in each receive slot, being a master is a lighter burden than being a slave. Being a master of seven slaves is possible; being a slave of more than one master is difficult.[citation needed] The specification is vague as to required behavior in scatternets.**

若英文理解得不是很好,相应的度娘百科有对应的翻译:http://baike.baidu.com/view/1028.htm#3

主要提及蓝牙核心规范是支持一个蓝牙设备作为主设备(Server)能够同时与最多7个从设备(Client)建立连接,这是对蓝牙支持一对多建立基础的“星形网络”简单介绍。

Bluetooth自组网( Ad Hoc Networking)

由于博主在写实例测试过程发现,蓝牙间的连接并不像上述介绍的仅仅只是一个主设备连接7个从设备那么简单,而是蓝牙在此基础上依然可以与其它蓝牙设备建立连接,多个小型”星形网”互联形成一个”散射网络”。
故而google一些更详细的资料来了解了下蓝牙的自组网:
http://www.netlab.tkk.fi/opetus/s38030/k02/Papers/16-Jari.pdf 这篇文章是英文的但是介绍的比较详细和全面。

文章内的一幅图比较好的展示了蓝牙技术支持的自组建网络:

比较详细的技术支持限制以及相关应用等,可以静下心来好好看看这篇英文论文。

Android Bluetooth的连接使用

Android官方Bluetooth API Guides:
http://developer.android.com/guide/topics/connectivity/bluetooth.html#ManagingAConnection

  • Bluetooth Permissions
    <uses-permission android:name="android.permission.BLUETOOTH" /><!-- 启动蓝牙设备发现,更改蓝牙设备设置需要BLUETOOTH_ADMIN --><uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
  • BluetoothAdapter
    BluetoothAdapter代表了本机的蓝牙适配器设备,基本上是使用蓝牙功能的入口。

  • BluetoothDevice
    代表了远程蓝牙设备,搜索到的蓝牙设备,已连接的对端蓝牙。

  • BluetoothSocket
    类似TCP Socket,建立连接后用于传输数据的socket

  • BluetoothServerSocket
    主蓝牙设备(Server)的监听Socket,用于监听处理从设备Client发起的连接。

    PS:蓝牙设备具有一个可见性设置,出于安全考虑默认都是不可见的,即你启动搜索周围的蓝牙设备也不会发现不可见的的蓝牙设备。

    //enable蓝牙设备的可见性Intent discoverableIntent = newIntent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);//DISCOVERABLE_DURATION取值为0-3600秒 default=120discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);startActivity(discoverableIntent);
  1. 获取Remote BluetoothDevice
        //获取本地蓝牙适配器mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();if( mBluetoothAdapter == null ){Toast.makeText(this,"未找到蓝牙设备", Toast.LENGTH_SHORT).show();finish();} if( !mBluetoothAdapter.isEnabled() ) {//申请打开蓝牙设备Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);startActivity(intent);}//获取本机已配对的蓝牙设备Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();//If there are paired devicesif (pairedDevices.size() > 0) {// Loop through paired devicesfor (BluetoothDevice device : pairedDevices) {// Add the name and address to an array adapter to show in a ListViewmArrayAdapter.add(device.getName() + "\n" + device.getAddress());}}mBluetoothAdapter.startDiscovery();//注册广播接收,搜索查找周围的设备// 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 deviceif (BluetoothDevice.ACTION_FOUND.equals(action)) {// Get the BluetoothDevice object from the IntentBluetoothDevice device =     intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);// Add the name and address to an array adapter to show in a ListViewmArrayAdapter.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
  1. 作为主设备Server
    建立蓝牙连接需要有一方为主设备Server,另一方为从设备Client,而无论Server接受连接或者Client发起连接这个过程都是一个阻塞的调用,所以需要在子线程内进行接受或者发起连接。
    主设备需要通过本地的蓝牙适配器mBluetoothAdapter的listenUsingRfcommWithServiceRecord函数获得server socket 然后调用socket的accept函数来持续监听client的连接请求。
    PS:listenUsingRfcommWithServiceRecord(String, UUID)函数的第一个参数String代表这个蓝牙service的名称可以自己定义;第二个UUID则是一个128-bits通用唯一标示码,是蓝牙服务的唯一标识码,当client发起连接请求时也会包含一个uuid用于区分要连接哪一个蓝牙服务,即要保证client和server连接成功需要有同样的UUID。 UUID网上有很多生成方法,随意挑一个生成使用就行。
public class BltServerSocketThread extends Thread{private final BluetoothServerSocket mmServerSocket;private final BluetoothAdapter mBluetoothAdapter;private final  UUID MY_UUID;public BltServerSocketThread(BluetoothAdapter bluetoothAdapter) {mBluetoothAdapter = bluetoothAdapter;MY_UUID = UUID.fromString("2da12563-e314-1211-7789-" + mBluetoothAdapter.getAddress().replace(":", ""));BluetoothServerSocket tmp = null;try {// MY_UUID is the app's UUID string, also used by the client code//get the server socket listenning the client's connection requests.tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord("MyBLTServer", MY_UUID);} catch (IOException e) { }mmServerSocket = tmp;}public void run() {BluetoothSocket socket = null;// Keep listening until exception occurs or a socket is returnedwhile (true) {try {/*Start listening for connection requests by calling accept().*This is a blocking call. A connection is accepted only when a remote device has sent * a connection request with a UUID matching the one registered with this listening server socket. * When successful, accept() will return a connected BluetoothSocket.*/socket = mmServerSocket.accept();} catch (IOException e) {System.out.println("Unable to accept; close the socket and get out");cancel();break;}// If a connection was acceptedif (socket != null) {// Do work to manage the connection (in a separate thread)BltConnectionThread bltConnectionThread = new BltConnectionThread(socket);bltConnectionThread.start();EventBus.getDefault().post(bltConnectionThread);//if you want to connect only one bluetooth device,//should break here, close the server socket.//cancle(); break;}}}/** Will cancel the listening socket, and cause the thread to finish */public void cancel() {try {mmServerSocket.close();} catch (IOException e) { }}
}
  1. 作为从设备Client
public class BltClientConnectionThread extends Thread {private final BluetoothSocket mmSocket;private final BluetoothDevice mmDevice;private final  UUID MY_UUID;public BltClientConnectionThread(BluetoothDevice device) {// Use a temporary object that is later assigned to mmSocket,// because mmSocket is finalBluetoothSocket tmp = null;mmDevice = device;//The same as the server's uuid.MY_UUID = UUID.fromString("2da12563-e314-1211-7789-" + device.getAddress().replace(":", ""));// Get a BluetoothSocket to connect with the given BluetoothDevicetry {// MY_UUID is the app's UUID string, also used by the server codetmp = device.createRfcommSocketToServiceRecord(MY_UUID);} catch (IOException e) { }mmSocket = tmp;}public void run() {try {// Connect the device through the socket. This will block// until it succeeds or throws an exceptionmmSocket.connect();} catch (IOException connectException) {// Unable to connect; close the socket and get outcancel();return;}// Do work to manage the connection (in a separate thread)BltConnectionThread bltConnectionThread = new BltConnectionThread(mmSocket);bltConnectionThread.start();EventBus.getDefault().post(bltConnectionThread);}/** Will cancel an in-progress connection, and close the socket */public void cancel() {try {mmSocket.close();} catch (IOException e) { }finally {}}
}
  1. 管理蓝牙链接
    连接成功后就可以获取到一个用于蓝牙通信的BluetoothSocket,每两个蓝牙设备直接成功建立连接都会获得一个BluetoothSocket。
public class BltConnectionThread extends Thread {private final BluetoothSocket mmSocket;private final InputStream mmInStream;private final OutputStream mmOutStream;public BltConnectionThread(BluetoothSocket socket) {mmSocket = socket;InputStream tmpIn = null;OutputStream tmpOut = null;// Get the input and output streams, using temp objects because// member streams are finaltry {tmpIn = socket.getInputStream();tmpOut = socket.getOutputStream();} catch (IOException e) { }mmInStream = tmpIn;mmOutStream = tmpOut;}public void run() {int bufferSize = 1024;int bytesRead = -1;byte[] buffer = new byte[bufferSize];// Keep listening to the InputStream until an exception occurswhile (true) {try {final StringBuilder sb = new StringBuilder();// Read from the InputStreambytesRead = mmInStream.read(buffer);// Send the obtained bytes to the UI activityif (bytesRead != -1) {String result = "";while ((bytesRead == bufferSize) && (buffer[bufferSize] != 0)) {result = result + new String(buffer, 0, bytesRead);bytesRead = mmInStream.read(buffer);}result = result + new String(buffer, 0, bytesRead);sb.append(result);}EventBus.getDefault().post(new BluetoothCommunicator(sb.toString()));} 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) { }}}

蓝牙一对多连接

基本的原理就是上述的连接和管理,蓝牙服务端Server启动一个持续的socket listening,多个client向该server发起连接请求,即可建立多个连接。
这是博主写的一个简单的蓝牙多连接示例,分为server和client,server可以启动server socket监听,然后各个client可以点击搜索设备并且与server进行连接;连接成功后server端会显示已经成功连接的client列表,点击对应设备可向client发送消息。
AndroidMultiBluetoothSample:https://github.com/lishushu/AndroidMultiBluetoothSample.git

关于Android蓝牙设备的连接使用相关推荐

  1. Android中发现蓝牙设备的广播是,Android 蓝牙设备的查找和连接

    1.权限 使用蓝牙设备需要先在Manifest中开放权限,位置如下. [html] view plaincopy ... // 使用蓝牙设备的权限 // 管理蓝牙设备的权限 2.打开蓝牙 获得蓝牙适配 ...

  2. Android 蓝牙设备的查找与连接

    Android 蓝牙设备的查找与连接 1,添加蓝牙设备的权限,6.0以上动态权限 管理蓝牙设备的权限<uses-permissionandroid:name="android.perm ...

  3. android 连接蓝牙音响,Android 扫描附近的蓝牙设备并连接蓝牙音响的示例

    Android 扫描附近的蓝牙设备并连接蓝牙音响的示例 发布时间:2020-09-10 04:30:39 来源:脚本之家 阅读:111 作者:叶应是叶 写了一个可以扫描附近蓝牙设备的小Demo,可以查 ...

  4. 【Android】锁屏/熄屏之后,与蓝牙设备的连接就会自动断开

    今天客户给反馈一个比较奇怪的问题,在OPPO Android6.0手机上,锁屏之后,与蓝牙设备的连接就会断开,但是其它手机却没有出现该问题.拿到这个问题一开始也是百思不得其解,但是一个无意中的操作,让 ...

  5. android 蓝牙耳机 判断,Android实现蓝牙耳机连接

    前言 最近看了下蓝牙耳机连接的问题,查阅了相关资料,再此做一个总结. 本文参考以下链接: Android实现主动连接蓝牙耳机 再次对作者表示感谢. 今天涉及的内容有: 流程讲解 新建广播Bluetoo ...

  6. Android蓝牙A2DP连接实现

    代码地址如下: http://www.demodashi.com/demo/14624.html 开发环境: 开发工具:Androidstudio 适配机型:honor8(Android6.0), 坚 ...

  7. android 如何实现连接蓝牙打印机来实现打印功能

    ============问题描述============ 目前,android 如何实现连接蓝牙打印机来实现打印功能,请大侠来指点, 是否要遵循什么协议标准,还是有设备提供商会提供打印的sdk, 我们 ...

  8. Android实现蓝牙耳机连接

    代码地址如下: http://www.demodashi.com/demo/13259.html 前言 讲讲android对于蓝牙耳机连接技术的实现 今天涉及的内容有: 1. 流程讲解 2. 新建广播 ...

  9. Android 设备蓝牙连接扫描枪获取扫描内容

    Android 设备蓝牙连接扫描枪获取扫描内容 标签(空格分隔): 未分类 条形扫描枪主要可以扫描条形码和二维码等,扫描速度比手机扫描设备快得多,本文简单介绍android 通过蓝牙监听蓝牙连接,当扫 ...

最新文章

  1. 端口号被占用怎么解决
  2. python发送邮件带附件_Python发送邮件(带附件)
  3. 输入法图标(语言栏)不见了怎么办
  4. 写得蛮好的linux学习笔记(二)
  5. Shadow of Survival
  6. C++ 函数的引用返回值
  7. Python-深拷贝-浅拷贝-时间消耗
  8. 神经信息学整理(1)-神经细胞,MP模型
  9. Matlb中break 和continue 语句
  10. redis 持久化详解 RDB和AOF 优缺点
  11. 牧马人机械鼠标g3_性价比好的有线鼠标都有哪些?2020年12款热选游戏鼠标推荐...
  12. 加密和解密算法的兩個實現
  13. pyqt5-控件是否可用
  14. 截取字符串,计算字符串字节大小,选择文件夹,上传文件
  15. 软件需求规格说明书 模板
  16. 简单聊聊为什么说外包不好?
  17. 破解双中台困局:万家数科 x StarRocks 数字化技术实践
  18. Visual Paradigm下载并设置中文
  19. 算法竞赛入门经典 习题3-2 分子量 Molar Mass
  20. 如何治疗水龟脖子长的大包

热门文章

  1. java面试换背景颜色_正在修生养息,突然收到阿里(蚂蚁)面试电话,四面阿里面经总结...
  2. 系统方法定位 IOS
  3. Java程序员如何月薪达到两万,需要技术水平达到什么程度?
  4. 平安电工冲刺深交所:年营收8.8亿 为潘协保家族企业
  5. python 获取硬盘信息失败请谨慎操作_老毛桃pe装机工具出现获取硬盘信息失败,请谨慎操作...
  6. vmware-vmx.exe无法结束进程
  7. 使用Python在图片上增加文字
  8. 用Python分析了7w+《悬崖之上》影评,看看观众都是怎么说?
  9. Matlab plotyy画双纵坐标图实例
  10. 在移动开发快捷推广方式