<uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <!-Android 12+需要定位权限 --> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
// 检查并请求权限 if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_CODE_LOCATION); }
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); if (bluetoothAdapter == null) { // 设备不支持蓝牙 Toast.makeText(context, "设备不支持蓝牙", Toast.LENGTH_SHORT).show(); return; } // 注册蓝牙状态广播接收器 IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED); registerReceiver(bluetoothStateReceiver, filter); // 状态监听回调 private final BroadcastReceiver bluetoothStateReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { final String action = intent.getAction(); if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)) { final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR); switch (state) { case BluetoothAdapter.STATE_ON: // 蓝牙已开启 break; case BluetoothAdapter.STATE_OFF: // 蓝牙已关闭 break; } } } };
Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices(); for (BluetoothDevice device : pairedDevices) { // 过滤目标设备(通过MAC地址或名称) if (device.getName().equals("目标设备名称")) { // 建立连接 connectToDevice(device); } }
private void connectToDevice(BluetoothDevice device) { new Thread(() -> { try { // 创建RFCOMM协议Socket(经典蓝牙) BluetoothSocket socket = device.createRfcommSocketToServiceRecord(MY_UUID); socket.connect(); // 阻塞式连接 // 连接成功后处理输入输出流 manageConnectedSocket(socket); } catch (IOException e) { e.printStackTrace(); // 处理连接失败(重试或提示) } }).start(); } // UUID需与对方设备一致(自定义服务) private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
private BluetoothSocket socket; private OutputStream outputStream; private void sendData(byte[] data) { if (socket != null && socket.isConnected()) { try { outputStream.write(data); // 发送字节流 outputStream.flush(); } catch (IOException e) { e.printStackTrace(); // 处理发送失败(如断线重连) } } }
private InputStream inputStream; private void manageConnectedSocket(BluetoothSocket socket) { this.socket = socket; try { inputStream = socket.getInputStream(); outputStream = socket.getOutputStream(); // 持续监听数据 byte[] buffer = new byte[1024]; int len; while ((len = inputStream.read(buffer)) != -1) { // 处理接收到的数据(注意粘包问题) String received = new String(buffer, 0, len); handleReceivedData(received); } } catch (IOException e) { e.printStackTrace(); // 处理断线逻辑 } finally { closeConnection(); } }
private void closeConnection() { try { if (socket != null) { socket.close(); // 关闭Socket socket = null; } } catch (IOException e) { e.printStackTrace(); } }
经典蓝牙 | BLE(Android 5.0+) |
---|---|
使用BluetoothSocket |
使用BluetoothGatt |
适合持续数据传输 | 适合间歇性小数据通信 |
需配对(可选) | 无需配对,直接扫描连接 |
高功耗 | 低功耗 |
// 扫描BLE设备并连接 bluetoothLeScanner.startScan(scanCallback); private final ScanCallback scanCallback = new ScanCallback() { @Override public void onScanResult(ScanResult result) { // 匹配目标设备并连接 if (result.getDevice().getName().equals("BLE设备")) { bluetoothLeScanner.stopScan(scanCallback); // 停止扫描 connectGatt(result.getDevice(), false, gattCallback); // 自动连接 } } }; // GATT回调处理特征值读写 private final BluetoothGattCallback gattCallback = new BluetoothGattCallback() { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { if (newState == BluetoothProfile.STATE_CONNECTED) { gatt.discoverServices(); // 发现服务 } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { // 处理断线 } } @Override public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { // 处理读取结果 } @Override public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { // 处理异步通知(监听数据) String data = new String(characteristic.getValue()); handleReceivedData(data); // 自定义数据处理方法 } };
解答:
setNotification
启用特征值变化监听,减少轮询开销。 解答:
Map<String, BluetoothSocket>
存储设备MAC地址与Socket的映射。