Android 蓝牙SPP通信——服务端

本文详细介绍了蓝牙通信的基本流程,包括创建BluetoothServerSocket、等待客户端连接及数据读写操作。通过实例代码展示了如何利用BluetoothServerSocket建立安全的RFCOMM连接,并在子线程中处理数据读写,适用于Android平台的蓝牙开发。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

开始前先看一下大致的流程

 

1、创建BluetoothServerSocket

serverSocket = bluetoothAdapter.listenUsingRfcommWithServiceRecord(
                        bluetoothAdapter.getName(),java.util.UUID.fromString(SPP_UUID));

通过listenUsingRfcommWithServiceRecord返回一个BluetoothServerSocket,参数为本地的蓝牙名称和uuid,uuid可以定制,客户端和服务端要使用同一个uuid才能建立起连接。从方法名上看出,这一步和RFCOMM建立了联系,另外还有一个相似的方法为listenUsingInsecureRfcommWithServiceRecord,区别为后者为不安全的。

 

2、等待连接

socket = serverSocket.accept();

BluetoothServerSocket服务端要保持开启等待接收客户端的连接。这一步是阻塞的,所以需要另外开启一个线程处理,这里所有涉及的子线程都通过线程池管理。通过BluetoothServerSocket的accept方法就能获取得到BluetoothSocket,通过BluetoothSocket就能获取客户端的一些信息和通信了。

 

3、读写数据

 if(socket != null) {
       serverInputStream = socket.getInputStream();
       serverOutputStream = socket.getOutputStream();
       //读取
       readFromClient();
 }

拿到BluetoothSocket之后就可以获取输入输出流进行通信了,接下来就是流的操作了。流操作也开启子线程处理,readFromClient()方法我简单封装了一下从客户端读取数据:

   /**
     * 从客户端读取数据
     */
    private void readFormClient(){
        fixedThreadPool.execute(new ReadTask(serverInputStream));
    }


    /**
     * 读任务
     */
    private class ReadTask implements Runnable{

        InputStream inputStream;

        public ReadTask(InputStream inputStream) {
            this.inputStream = inputStream;
        }

        @Override
        public void run() {
            byte buffer[] = new byte[1024];
            int bytes;
            try {
                while (true){
                    if((bytes= inputStream.read(buffer))!=0){
                        byte[] buf_data = new byte[bytes];
                        for (int i = 0; i < bytes; i++){
                            buf_data[i]=buffer[i];
                        }
                        Log.i(TAG, "接受数据: " + ByteUtil.byteArrToHex(buf_data));
                        BluetoothMsg msg = new BluetoothMsg(buf_data);
                        EventBus.getDefault().post(msg);
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            } catch (IllegalThreadStateException ww){
                ww.printStackTrace();
            }
        }
    }

写的操作也类似:

    /**
     * 写任务
     */
    private class WriteTask implements Runnable {
        byte[] writeBytes;
        OutputStream outputStream;

        public WriteTask(OutputStream outputStream, byte[] writeBytes){
            this.outputStream = outputStream;
            this.writeBytes = writeBytes;
        }

        @Override
        public void run() {
            if(outputStream != null){
                try {
                    outputStream.write(writeBytes);
                    Log.i(TAG, "OutputStream: "+ByteUtil.byteArrToHex(writeBytes));
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }else{
                Log.i(TAG, "OutputStream null");
            }
        }
    }

 

### 单片机与蓝牙模块通信实现方法 #### ESP32通过MiPython实现蓝牙通信 对于ESP32而言,在MicroPython环境中可以借助`bluetooth`库来完成蓝牙功能开发。为了初始化并配置蓝牙设备,需先导入该库,并创建相应的对象实例[^1]。 ```python from bluetooth import Bluetooth bt = Bluetooth() ``` 设置蓝牙名称以便于识别连接: ```python bt.active(True) bt.config(name='ESP32_BT') ``` 针对串口服务(SPP),可通过如下方式建立服务器端等待客户端连接请求;或者作为客户端主动发起与其他设备间的配对尝试。 ```python # 创建 SPP 服务端 spp_server_sock= bt.spp.acceptor() # 或者创建 SPP 客户端去连接其他设备 remote_device_address = 'xx:xx:xx:xx:xx' # 对方 MAC 地址 spp_client_sock = bt.spp.connector(remote_device_address) ``` 一旦建立了有效的链接,则可以通过读写操作来进行数据交换处理逻辑编写。 ```python data_received = spp_server_sock.recv(1024) # 接收来自对方的数据包 print(data_received.decode()) message_to_send = b'This is a test message.' spp_client_sock.send(message_to_send) # 向目标发送消息字符串 ``` 关闭不再使用的套接字资源以节省电力消耗以及释放系统资源是非常重要的一步。 ```python spp_server_sock.close() # 关闭服务端监听通道 spp_client_sock.close() # 断开已有的客户会话链路 ``` #### Android Java应用程序控制单片机的蓝牙通信Android平台下编程时,通常需要定义一个专门用于管理蓝牙连接状态变化及数据传输过程的服务类——这里展示了一个简化版构造函数示例[^2]。 ```java public class BlueToothTool { private final BluetoothSocket mmSocket; private final OutputStream mmOutStream; private final InputStream mmInStream; public BlueToothTool(BluetoothDevice device, Handler handler){ try{ // 获取远程设备的安全 RFCOMM 通道 BluetoothSocket tmp = null; Method m = device.getClass().getMethod( "createRfcommSocket", new Class[] {int.class}); tmp = (BluetoothSocket)m.invoke(device, Integer.valueOf(1)); mmSocket = tmp; // 执行连接动作... mmSocket.connect(); // 初始化输入输出流 mmOutStream = mmSocket.getOutputStream(); mmInStream = mmSocket.getInputStream(); } catch(Exception e){ Log.e("BlueToothTool","Error during connection establishment.",e); } // ...后续代码省略 } } ``` 上述片段展示了如何基于反射机制获取指定编号的RFCOMM信道,并据此构建起一对可用于双向通讯的IO流管道结构体成员变量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值