Android蓝牙数据传输开发求助:Java新手需实现跨设备数字文本传输
嘿,作为刚入门时被Android蓝牙官方指南绕晕过的过来人,我太懂你的感受了!官方文档全是大段概念,新手根本抓不住重点。咱们直接针对你的需求——传输4-5个数字和2-3段文本——一步一步来,都是接地气的Java代码,看完就能上手~
一、先把权限补全(你可能漏了关键部分)
你已经加了基础蓝牙权限,但Android不同版本的权限要求不一样,尤其是12+的新权限,补全你的Manifest代码:
<!-- 基础蓝牙权限 --> <uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <!-- Android 12+ 新增的细分权限,必须加 --> <uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" /> <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" /> <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" /> <!-- Android 11及以下版本,需要位置权限才能扫描蓝牙设备 --> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <!-- 声明App依赖蓝牙硬件 --> <uses-feature android:name="android.hardware.bluetooth" android:required="true" />
另外,Android 6+还要动态申请权限(比如BLUETOOTH_CONNECT、位置权限),不然会直接报错。
二、核心逻辑:蓝牙传输本质是Socket通信
Android蓝牙传输用的是RFCOMM协议,和普通网络Socket逻辑一样——分「服务端(等待连接的设备)」和「客户端(主动连的设备)」。你要传的数字、文本,本质就是把数据转成字节流发送,再解析回来。
1. 服务端:等待客户端连接并发送数据
先开个线程(绝对不能在主线程做!会卡死App)监听连接:
import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothServerSocket; import android.bluetooth.BluetoothSocket; import java.io.IOException; import java.io.OutputStream; import java.util.UUID; // 重点!服务端和客户端必须用同一个UUID,我用的是标准SPP服务UUID private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); private BluetoothAdapter bluetoothAdapter; // 启动服务端的方法,在你需要的地方调用(比如点击按钮) private void startBluetoothServer() { bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); // 先检查蓝牙是否开启 if (bluetoothAdapter == null || !bluetoothAdapter.isEnabled()) { // 这里可以弹出提示让用户开蓝牙,比如调用Intent开启蓝牙设置 return; } // 用线程处理阻塞操作 new Thread(() -> { BluetoothServerSocket serverSocket = null; try { // 创建服务器Socket,参数是服务名称和UUID serverSocket = bluetoothAdapter.listenUsingRfcommWithServiceRecord("MyTextNumberService", MY_UUID); // 等待客户端连接(这是阻塞方法,会一直等直到有设备连进来) BluetoothSocket socket = serverSocket.accept(); // 连接成功!现在发送你的数据 // 推荐把数字和文本打包成字符串,比如用逗号分隔数字,换行分隔文本 sendData(socket, "123,456,789,101,202"); // 4-5个数字 sendData(socket, "第一段文本内容"); sendData(socket, "第二段文本内容"); } catch (IOException e) { e.printStackTrace(); } finally { // 用完记得关闭Socket try { if (serverSocket != null) serverSocket.close(); } catch (IOException e) { e.printStackTrace(); } } }).start(); } // 通用发送数据方法 private void sendData(BluetoothSocket socket, String data) throws IOException { OutputStream outputStream = socket.getOutputStream(); outputStream.write(data.getBytes()); // 把字符串转成字节发送 outputStream.flush(); }
2. 客户端:扫描并连接服务端,接收数据
客户端要先找到服务端设备,然后发起连接:
import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothSocket; import java.io.IOException; import java.io.InputStream; // 连接指定蓝牙设备的方法,参数是你扫描到的服务端设备 private void connectToServerDevice(BluetoothDevice serverDevice) { new Thread(() -> { BluetoothSocket socket = null; try { // 创建客户端Socket,必须用和服务端一样的UUID socket = serverDevice.createRfcommSocketToServiceRecord(MY_UUID); // 发起连接(阻塞方法) socket.connect(); // 连接成功!接收数据 String numbersStr = receiveData(socket); String text1 = receiveData(socket); String text2 = receiveData(socket); // 解析数字:把逗号分隔的字符串转成int数组 String[] numArray = numbersStr.split(","); int[] numbers = new int[numArray.length]; for (int i = 0; i < numArray.length; i++) { numbers[i] = Integer.parseInt(numArray[i]); } // 现在你就拿到了数字数组和两段文本,随便处理啦 // 比如更新UI的话,要切回主线程:runOnUiThread(() -> { ... }); } catch (IOException e) { e.printStackTrace(); } finally { try { if (socket != null) socket.close(); } catch (IOException e) { e.printStackTrace(); } } }).start(); } // 通用接收数据方法 private String receiveData(BluetoothSocket socket) throws IOException { InputStream inputStream = socket.getInputStream(); byte[] buffer = new byte[1024]; // 缓冲区大小足够装你的文本和数字 int bytesRead = inputStream.read(buffer); return new String(buffer, 0, bytesRead); }
三、进阶小技巧:用JSON打包数据更清晰
如果觉得用逗号、换行分隔数据太麻烦,推荐用JSON格式打包,解析起来更不容易出错。比如:
{ "numbers": [123, 456, 789, 101], "texts": ["第一段文本", "第二段文本"] }
你可以用Gson库把Java对象转成JSON字符串发送,接收后再转成对象。Gson的依赖在build.gradle里加:
implementation 'com.google.code.gson:gson:2.10.1'
示例代码:
// 定义一个数据类 public class BluetoothData { public int[] numbers; public String[] texts; } // 服务端发送: BluetoothData dataToSend = new BluetoothData(); dataToSend.numbers = new int[]{123,456,789}; dataToSend.texts = new String[]{"文本1", "文本2"}; String json = new Gson().toJson(dataToSend); sendData(socket, json); // 客户端接收: String jsonReceived = receiveData(socket); BluetoothData receivedData = new Gson().fromJson(jsonReceived, BluetoothData.class); // 直接用receivedData.numbers和receivedData.texts就行
四、新手必避的坑
- 绝对不能在主线程操作蓝牙Socket:所有连接、收发数据的操作都要放在子线程,不然会触发ANR(应用无响应)。
- UUID必须完全一致:服务端和客户端的UUID差一个字符都连不上,我给的是标准SPP服务UUID,直接用就行。
- 动态申请权限:除了Manifest里的权限,Android 6+必须在代码里动态申请BLUETOOTH_CONNECT、位置权限(旧版本),不然会被系统拒绝操作。
- 蓝牙状态检查:操作前一定要检查蓝牙是否开启,没开启的话引导用户去设置开启。
内容的提问来源于stack exchange,提问作者Manos Rasidakis
相关产品推荐
相关产品推荐

