ESP8266与Android APP TCP通信问题:双向数据传输实现求助
实现Android与ESP8266 TCP服务器的双向通信
看起来你已经顺利搞定了ESP8266的TCP服务器配置(AT指令全返回OK就是最好的证明😉),接下来咱们把Android端的通信逻辑补全,实现ESP主动发0/1、APP接收后回传EditText内容的双向交互。
第一步:补全Android端基础配置
首先得给App加上必要的网络权限,在AndroidManifest.xml里添加:
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
然后是对应你提到控件的布局文件activity_main.xml:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="16dp"> <TextView android:id="@+id/tv" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="等待ESP数据..." android:textSize="18sp"/> <EditText android:id="@+id/txt" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="输入要发送的文本"/> <EditText android:id="@+id/txt2" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="备用输入框(按需使用)"/> <Button android:id="@+id/b" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="发送文本到ESP"/> </LinearLayout>
第二步:完整的MainActivity代码实现
注意:Android禁止在主线程执行网络操作,所以咱们用协程处理网络逻辑(比AsyncTask更简洁现代)。另外你的原代码里string response要改成String response,Java是大小写敏感的哦。
import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.TextView; import androidx.appcompat.app.AppCompatActivity; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.Socket; import kotlinx.coroutines.CoroutineScope; import kotlinx.coroutines.Dispatchers; import kotlinx.coroutines.launch; import kotlinx.coroutines.withContext; public class MainActivity extends AppCompatActivity { TextView tv; EditText txt, txt2; Button b; String espIp = "你的ESP8266局域网IP"; // 比如192.168.1.100,从ESP串口日志里找 int espPort = 80; Socket socket; BufferedReader inputReader; OutputStreamWriter outputWriter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tv = findViewById(R.id.tv); txt = findViewById(R.id.txt); txt2 = findViewById(R.id.txt2); b = findViewById(R.id.b); // 启动协程连接ESP并持续监听数据 CoroutineScope(Dispatchers.IO).launch(() -> { try { socket = new Socket(espIp, espPort); inputReader = new BufferedReader(new InputStreamReader(socket.getInputStream())); outputWriter = new OutputStreamWriter(socket.getOutputStream()); // 循环读取ESP发来的0/1 String espData; while ((espData = inputReader.readLine()) != null) { final String receivedData = espData; // 切回主线程更新UI withContext(Dispatchers.Main) { tv.setText("ESP发来数据:" + receivedData); } } } catch (IOException e) { e.printStackTrace(); withContext(Dispatchers.Main) { tv.setText("连接失败:" + e.getMessage()); } } }); // 按钮点击事件:发送EditText内容到ESP b.setOnClickListener(v -> { String sendText = txt.getText().toString().trim(); if (!sendText.isEmpty() && socket != null && socket.isConnected()) { CoroutineScope(Dispatchers.IO).launch(() -> { try { outputWriter.write(sendText + "\n"); // 加换行符让ESP识别数据结束 outputWriter.flush(); withContext(Dispatchers.Main) { txt.setText(""); // 发送后清空输入框 } } catch (IOException e) { e.printStackTrace(); withContext(Dispatchers.Main) { tv.setText("发送失败:" + e.getMessage()); } } }); } }); } @Override protected void onDestroy() { super.onDestroy(); // 销毁时关闭网络资源 try { if (inputReader != null) inputReader.close(); if (outputWriter != null) outputWriter.close(); if (socket != null) socket.close(); } catch (IOException e) { e.printStackTrace(); } } }
第三步:ESP8266端的补充逻辑
你已经完成了AT指令配置,现在需要在Arduino代码里实现客户端连接检测、定期发0/1、接收APP文本的逻辑:
#include <ESP8266WiFi.h> const char* ssid = "你的WiFi名称"; const char* password = "你的WiFi密码"; WiFiServer server(80); WiFiClient client; void setup() { Serial.begin(115200); // 连接WiFi WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); // 这里的IP就是Android端要填的espIp server.begin(); } void loop() { // 等待客户端连接 if (!client.connected()) { client = server.available(); if (client) { Serial.println("New client connected"); } } else { // 每2秒发送一次0或1(可按需调整间隔) static unsigned long lastSendTime = 0; if (millis() - lastSendTime > 2000) { int sendData = random(0,2); // 随机生成0或1 client.println(sendData); // 加换行符让Android端能读取 lastSendTime = millis(); Serial.println("Sent to APP: " + String(sendData)); } // 读取APP发来的文本 if (client.available() > 0) { String receivedText = client.readStringUntil('\n'); Serial.println("Received from APP: " + receivedText); // 这里可以添加逻辑,比如根据文本控制LED等外设 } } }
关键注意事项
- 确保Android设备和ESP8266在同一个局域网内
- 替换代码中的WiFi名称、密码以及ESP的局域网IP(从ESP串口日志里获取)
- 网络操作必须在子线程执行,否则会触发
NetworkOnMainThreadException - 发送数据时建议加换行符(
\n),方便两端识别数据结束位置
内容的提问来源于stack exchange,提问作者Malek
相关产品推荐
相关产品推荐

