Android应用向ESP32通过WiFi发送数据失败求助
问题排查与修复方案
核心问题分析
目前代码编译正常但功能失效,主要可能出在Android网络权限/明文限制、Java代码异常未暴露、ESP32数据读取逻辑不完善这三个方向,以下是针对性修复:
1. 修复Android端权限与明文网络限制
Android 9(API 28)及以上默认禁止明文网络连接(包括Socket),同时需要申请必要的网络权限:
修改AndroidManifest.xml
在<manifest>标签内添加权限声明:
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
在<application>标签内添加明文连接允许(测试阶段可用,正式版建议配置更严谨的网络安全策略):
<application ... android:usesCleartextTraffic="true" ...>
2. 改进Android Java代码的异常反馈与可靠性
原代码仅在后台静默打印异常,无法直观定位问题,同时优化Socket资源管理:
package com.benledmatrix.esp32controloverwifi; import android.os.Bundle; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.Toast; import androidx.appcompat.app.AppCompatActivity; import java.io.IOException; import java.io.PrintWriter; import java.net.Socket; public class MainActivity extends AppCompatActivity { private static final String TAG = "ESP32_CONTROL"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Button sendButton = findViewById(R.id.send_button); sendButton.setOnClickListener(v -> sendData()); } private void sendData() { new Thread(() -> { Socket socket = null; PrintWriter out = null; try { socket = new Socket("192.168.4.1", 80); // 启用自动flush,避免手动调用遗漏 out = new PrintWriter(socket.getOutputStream(), true); out.println("Hello, ESP32!"); // 在UI线程显示成功提示 runOnUiThread(() -> Toast.makeText(MainActivity.this, "数据发送成功", Toast.LENGTH_SHORT).show()); } catch (IOException e) { Log.e(TAG, "发送失败: " + e.getMessage()); // 在UI线程显示错误详情 runOnUiThread(() -> Toast.makeText(MainActivity.this, "发送失败: " + e.getMessage(), Toast.LENGTH_LONG).show()); } finally { // 确保资源安全关闭 if (out != null) out.close(); if (socket != null) { try { socket.close(); } catch (IOException e) { Log.e(TAG, "关闭Socket失败: " + e.getMessage()); } } } }).start(); } }
- 新增
Log日志和Toast提示,直观反馈连接/发送状态 - 优化资源关闭逻辑,避免内存泄漏
- 使用自动flush的
PrintWriter构造方法,确保数据及时发送
3. 修复ESP32 Arduino代码的数据读取逻辑
原代码存在两个关键问题:
client.available()仅检测客户端连接,未等待数据发送完成- Java的
println会发送\r\n,原代码读取的字符串会包含多余的\r,导致字符串比较失败
修改后的ESP32代码:
#include <WiFi.h> const char* ssid = "ESP32 HotSpot"; const char* password = "password"; WiFiServer server(80); void setup() { Serial.begin(115200); WiFi.mode(WIFI_AP); WiFi.softAP(ssid, password); Serial.print("IP address: "); Serial.println(WiFi.softAPIP()); server.begin(); pinMode(2, OUTPUT); } void loop() { WiFiClient client = server.available(); if (client) { Serial.println("新客户端连接"); // 等待客户端发送数据 while (client.connected() && !client.available()) { delay(10); } // 读取数据并去除首尾的换行/回车/空格 String data = client.readStringUntil('\n'); data.trim(); Serial.print("收到数据: "); Serial.println(data); if (data.equals("Hello, ESP32!")) { for (int i = 0; i < 2; i++) { digitalWrite(2, HIGH); delay(200); digitalWrite(2, LOW); delay(200); } } else { digitalWrite(2, HIGH); delay(200); digitalWrite(2, LOW); delay(200); } client.stop(); Serial.println("客户端断开连接"); } }
- 新增等待数据的逻辑,确保读取到完整的客户端数据
- 用
trim()去除字符串首尾的无效字符,避免比较失败 - 增加串口日志,方便跟踪连接和数据接收状态
测试步骤
- 重新编译ESP32代码并上传,打开串口监视器确认AP启动正常
- 重新编译Android代码生成APK安装,连接ESP32热点
- 点击按钮,观察Android端Toast提示和ESP32串口日志,验证LED闪烁逻辑
内容的提问来源于stack exchange,提问作者Benjam2k4
相关产品推荐
相关产品推荐

