You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求基于Java的Android Studio ESP32多连接通信APP资源与源码

Android Java 与 ESP32 三种连接方式数据收发实现方案

一、经典蓝牙(Bluetooth Classic)连接与数据收发

核心代码片段

设备配对与连接

// 获取蓝牙适配器
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (bluetoothAdapter == null) {
    // 设备不支持蓝牙,直接返回
    return;
}

// 开启蓝牙(未开启时请求权限)
if (!bluetoothAdapter.isEnabled()) {
    Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
    startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}

// 遍历已配对设备,匹配ESP32
Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices();
for (BluetoothDevice device : pairedDevices) {
    if (device.getName().contains("ESP32")) {
        // 建立RFCOMM连接(使用通用串口UUID)
        BluetoothSocket socket = device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
        
        // 子线程执行连接与读写,避免阻塞主线程
        new Thread(() -> {
            try {
                socket.connect();
                InputStream in = socket.getInputStream();
                OutputStream out = socket.getOutputStream();
                
                // 发送数据
                out.write("Hello ESP32".getBytes());
                out.flush();
                
                // 接收数据
                byte[] buffer = new byte[1024];
                int bytesRead = in.read(buffer);
                String receivedData = new String(buffer, 0, bytesRead);
                
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();
        break;
    }
}

卡顿规避要点

  • 所有蓝牙操作(连接、读写)必须放在子线程执行,禁止在主线程操作,否则会触发ANR。
  • 扫描新设备时设置超时时间,扫描完成后立即停止,避免持续占用系统资源。

二、低功耗蓝牙(BLE)连接与数据收发

核心代码片段

扫描与GATT连接

BluetoothLeScanner scanner = bluetoothAdapter.getBluetoothLeScanner();
ScanCallback scanCallback = new ScanCallback() {
    @Override
    public void onScanResult(int callbackType, ScanResult result) {
        super.onScanResult(callbackType, result);
        BluetoothDevice device = result.getDevice();
        if (device.getName() != null && device.getName().contains("ESP32-BLE")) {
            scanner.stopScan(this);
            // 连接BLE设备,异步回调处理状态
            device.connectGatt(MainActivity.this, false, gattCallback);
        }
    }
};
// 启动扫描(可添加过滤规则,只扫描指定服务UUID的设备)
scanner.startScan(scanCallback);

// GATT回调处理连接、服务发现与数据收发
BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
    @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
        super.onConnectionStateChange(gatt, status, newState);
        if (newState == BluetoothProfile.STATE_CONNECTED) {
            // 连接成功后发现服务
            gatt.discoverServices();
        }
    }

    @Override
    public void onServicesDiscovered(BluetoothGatt gatt, int status) {
        super.onServicesDiscovered(gatt, status);
        // 匹配ESP32端定义的服务与特征UUID
        BluetoothGattService service = gatt.getService(UUID.fromString("YOUR_ESP32_SERVICE_UUID"));
        BluetoothGattCharacteristic characteristic = service.getCharacteristic(UUID.fromString("YOUR_ESP32_CHAR_UUID"));
        
        // 开启通知,接收ESP32主动推送的数据
        gatt.setCharacteristicNotification(characteristic, true);
        
        // 发送数据到ESP32
        characteristic.setValue("BLE Test Data".getBytes());
        gatt.writeCharacteristic(characteristic);
    }

    @Override
    public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
        super.onCharacteristicChanged(gatt, characteristic);
        // 接收ESP32数据
        String receivedData = new String(characteristic.getValue());
        // 更新UI需切换到主线程
        runOnUiThread(() -> {
            tvReceived.setText(receivedData);
        });
    }
};

卡顿规避要点

  • 扫描BLE设备时添加服务UUID过滤,减少无效扫描结果,降低资源消耗。
  • GATT的写/读操作回调中,避免执行耗时逻辑,更新UI必须通过runOnUiThread。

三、WIFI 连接与数据收发(TCP)

核心代码片段(TCP客户端)

// 子线程建立TCP连接,避免阻塞主线程
new Thread(() -> {
    Socket socket = null;
    try {
        // 替换为ESP32的WIFI IP和监听端口
        socket = new Socket("192.168.1.100", 8080);
        OutputStream out = socket.getOutputStream();
        InputStream in = socket.getInputStream();
        
        // 发送数据
        out.write("WIFI TCP Test".getBytes());
        out.flush();
        
        // 接收数据
        byte[] buffer = new byte[1024];
        int bytesRead = in.read(buffer);
        String receivedData = new String(buffer, 0, bytesRead);
        
        // 更新UI
        runOnUiThread(() -> {
            tvReceived.setText(receivedData);
        });
        
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if (socket != null) socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}).start();

卡顿规避要点

  • 所有网络操作必须放在子线程,可使用AsyncTask或RxJava简化线程管理。
  • 若需持续通信,使用长连接并设置超时时间,避免无响应时阻塞线程;闲置时及时关闭Socket释放资源。

通用优化与卡顿排查

  • 主线程检查:用Android Studio Profiler工具排查主线程耗时操作,确保所有IO、网络、蓝牙逻辑都在子线程执行。
  • 资源释放:蓝牙连接断开后关闭BluetoothSocket/BluetoothGatt;WIFI连接关闭后释放Socket和流,避免资源泄漏。
  • 权限配置:确保AndroidManifest.xml添加必要权限(Android 12+需动态申请蓝牙相关权限):
<!-- 经典蓝牙 -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<!-- BLE -->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<!-- WIFI -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />

内容的提问来源于stack exchange,提问作者Mohamed Amal A

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 01:01:20