Flutter通过Android模拟器发起本地请求时后端打印乱码符号问题排查
问题分析与解决方案
嘿,这个问题我之前也踩过坑!根源其实很明确:你的Flutter代码发的是HTTPS加密请求,但后端用的是普通ServerSocket,根本没法解密SSL加密的数据,所以打印出来全是乱码。而Postman发的是HTTP明文请求,后端能直接解析,这就对应上了。
为什么会出现乱码?
- Flutter代码里用的是
https://10.0.2.2:8000/,HTTPS会把请求内容通过SSL/TLS加密后再发送; - 你的Java后端是基于
ServerSocket的普通TCP服务,只能处理明文数据,收到加密后的二进制流直接打印,自然是一堆看不懂的乱码符号; - Postman用
http://localhost:8000/发的是明文HTTP请求,后端能直接读取解析,所以显示正常。
两种解决方案
方案1:改用HTTP请求(开发阶段推荐)
这是最快解决问题的办法,适合本地开发调试:
- 修改Flutter的请求URL:把
https改成http
http.Response response =await http.post("http://10.0.2.2:8000/", headers: headers, body: jsonEncode(body));
- 允许Android明文HTTP请求:Android 9(API 28)及以上默认禁止明文HTTP流量,需要在
android/app/src/main/AndroidManifest.xml的<application>标签中添加属性:
<application ... android:usesCleartextTraffic="true"> ... </application>
改完之后再测试,后端应该能正常打印请求内容了。
方案2:让后端支持HTTPS(生产环境推荐)
如果需要模拟生产环境的HTTPS场景,就得把后端改成支持SSL/TLS的服务,用SSLServerSocket代替ServerSocket。这里给个简单的示例:
首先你需要生成一个自签名证书(开发用),然后用以下代码创建HTTPS服务器:
import javax.net.ssl.*; import java.io.*; import java.security.KeyStore; public class HttpsServerClass extends Thread { private int port; private SSLServerSocket serverSocket; private boolean running = true; public HttpsServerClass(int port) { this.port = port; } public void startServer() { try { // 加载密钥库(自签名证书,密钥库密码和密钥密码需一致) char[] password = "your-keystore-password".toCharArray(); KeyStore keyStore = KeyStore.getInstance("JKS"); keyStore.load(new FileInputStream("your-keystore.jks"), password); // 创建SSL上下文 KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); keyManagerFactory.init(keyStore, password); SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(keyManagerFactory.getKeyManagers(), null, null); // 创建SSLServerSocket serverSocket = (SSLServerSocket) sslContext.getServerSocketFactory().createServerSocket(port); this.start(); System.out.println("HTTPS Server started on port " + port); } catch (Exception e) { e.printStackTrace(); } } @Override public void run() { while (running) { try { SSLSocket socket = (SSLSocket) serverSocket.accept(); System.out.println("Client connected: " + socket.getInetAddress()); // 读取解密后的请求内容 BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); String line; while ((line = reader.readLine()) != null && line.length() != 0) { System.out.println(line); } socket.close(); } catch (IOException e) { e.printStackTrace(); } } } public static void main(String[] args) { HttpsServerClass server = new HttpsServerClass(8000); server.startServer(); } }
生成自签名证书可以用Java的keytool命令,比如:
keytool -genkey -alias myserver -keyalg RSA -keystore your-keystore.jks -keysize 2048
配置完成后,Flutter端的HTTPS请求就能正常被后端解密解析了。
内容的提问来源于stack exchange,提问作者Madhukar Choudhary
相关产品推荐
相关产品推荐

