在做安卓蓝牙相关的需求时 有一个需要 在app侧开启蓝牙共享网络之后把手机的网络共享给硬件设备,

但是竞品在app侧开启这个开关之后 硬件确实就有网络了 我们又查看到了手机侧的网络共享开关状态

不管是在对应的蓝牙设置详情中 还是系统的网络连接与共享中 蓝牙共享网络的开关均开关 百思不得其解 既然开关都关闭了 那么竞品是如何能做到通过蓝牙协议共享网络的呢?

于是我们就开始对竞品app进行日志的logcat分析 最终找到如下的一段日志

这段日志瞬间给了我们启发 有没有可能 他们走的是socket呢 在我们查找到了相关资料后 就可以确定这个事实了,就是以下要讲到的BluetoothSocket

在 Android 中,BluetoothSocket 主要用来建立 点对点 的 RFCOMM(类似串口)或者 L2CAP 连接,通常是配合 BluetoothDevice 来使用的。

我们先看方法如何调用

客户端调用

1.	获取蓝牙适配器
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

2.	找到目标设备
可以通过扫描 (BluetoothLeScanner 或经典蓝牙 startDiscovery) 获取设备。
如果已经配对,可以通过 getBondedDevices() 获取。

BluetoothDevice device = bluetoothAdapter.getRemoteDevice("XX:XX:XX:XX:XX:XX"); // 设备MAC地址

3.	建立连接 (客户端)
// 通常使用 UUID(与服务端约定好的 UUID)
UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

// 创建 socket
BluetoothSocket socket = device.createRfcommSocketToServiceRecord(MY_UUID);

// 取消扫描(否则会影响连接速度)
bluetoothAdapter.cancelDiscovery();

// 连接
socket.connect();

4.	数据传输
InputStream inputStream = socket.getInputStream();
OutputStream outputStream = socket.getOutputStream();

// 写数据
outputStream.write("Hello Device".getBytes());

// 读数据
byte[] buffer = new byte[1024];
int bytes = inputStream.read(buffer);
String message = new String(buffer, 0, bytes);

5.	关闭连接
socket.close();

服务端调用

BluetoothServerSocket serverSocket = bluetoothAdapter.listenUsingRfcommWithServiceRecord("MyApp", MY_UUID);
BluetoothSocket socket = serverSocket.accept(); // 阻塞等待客户端连接

常见注意点

UUID 必须和客户端/服务端一致,否则无法建立连接。

Android 12+ 需要在 AndroidManifest.xml 里声明权限:

<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />

以上的方法就跟常规的socket连接基本就一直了 没有什么技术难点 重点了这个技术栈确实在之前的认知里面是缺失的 今天看来 安卓的各种连接协议链确实要更加的开放些!