Android中使用HTTP Client发送JSON格式POST请求异常问题
问题描述
我在HTML中设置了一个按钮,点击时会调用MainActivity.java中的postData函数,相关代码及问题如下:
HTML中的JavaScript代码
<script> document.getElementById("login-button").addEventListener("click", function(event) { event.preventDefault(); var username = document.getElementById("username").value; var password = document.getElementById("password").value; var role = document.getElementById("role").value; var company = document.getElementById("company").value; Android.postData(username, password, role, company); }); </script>
MainActivity.java代码
public class MainActivity extends AppCompatActivity { private String username; private String password; private String role; private String company; private Retrofit retrofit; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); WebView webView = findViewById(R.id.webview); webView.getSettings().setJavaScriptEnabled(true); webView.addJavascriptInterface(new WebAppInterface(), "Android"); webView.loadUrl("file:///android_asset/index.html"); } public class WebAppInterface { @JavascriptInterface public void postData(String username, String password, String role, String company) { try { // 测试HTML输入数据是否正常传递 System.out.println("Username: " + username); System.out.println("Password: " + password); System.out.println("Role: " + role); System.out.println("Company: " + company); JSONObject jsonObject = new JSONObject(); jsonObject.put("username", username); jsonObject.put("password", password); jsonObject.put("role", role); jsonObject.put("company", company); String jsonString = jsonObject.toString(); if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.P) { new post().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, jsonString); } else { new post().execute(jsonString); } } catch (Exception e) { e.printStackTrace(); } } } class post extends AsyncTask<String, Void, String> { @Override protected String doInBackground(String... strings) { try { // 创建请求URL URL url = new URL("http://10.0.2.2:3000/login"); // 打开连接 HttpURLConnection client = (HttpURLConnection) url.openConnection(); // 设置请求方法为POST client.setRequestMethod("POST"); // 设置请求头 client.setRequestProperty("Content-Type", "application/json"); client.setRequestProperty("Accept", "application/json"); // 允许输出数据 client.setDoOutput(true); // 写入JSON数据 try (OutputStream os = client.getOutputStream()) { byte[] input = strings[0].getBytes("utf-8"); os.write(input, 0, input.length); } // 读取响应 try (BufferedReader br = new BufferedReader( new InputStreamReader(client.getInputStream(), "utf-8"))) { StringBuilder response = new StringBuilder(); String responseLine = null; while ((responseLine = br.readLine()) != null) { response.append(responseLine.trim()); } } } catch (Exception e) { e.printStackTrace(); } return null; } }
点击按钮后Logcat输出
2023-06-15 05:21:08.684 505-505 AutofillManager com.example.myapplication V requestHideFillUi(null): anchor = null 2023-06-15 05:21:08.763 505-2113 System.out com.example.myapplication I Username: 1 2023-06-15 05:21:08.763 505-2113 System.out com.example.myapplication I Password: 1 2023-06-15 05:21:08.763 505-2113 System.out com.example.myapplication I Role: Company 2023-06-15 05:21:08.763 505-2113 System.out com.example.myapplication I Company: Company 1
Server.js代码
app.post('/login', (req, res) => { const { username, password, role, company } = req.body; // 登录逻辑 console.log(username, password, role, company); if (role === 'Company' && company === 'Company 2' && username === 'admin2' && password === 'password') { res.json({ success: true, message: 'org2CreateUser.html' }); } if (role === 'Company' && company === 'Company 1' && username === 'admin1' && password === 'password') { res.json({ success: true, message: 'org1CreateUser.html' }); } if (role === 'Employer') { credentials.forEach(element => { if(element.username === username && element.password == password) { res.json({ success: true, message: 'upload.html' }); return; } }); res.status(401).json({ success: false, message: 'Invalid username or password' }); } }); app.listen(3000, () => { console.log('Server is running on port 3000'); });
核心问题
点击按钮后,Android端Logcat能正常打印输入参数,但服务器端的console.log(username, password, role, company)无任何输出。用CURL测试服务器接口完全正常:
curl -X POST -H "Content-Type: application/json" -d '{ "username": "admin", "password": "password", "role": "Company", "company": "Company 1" }' http://localhost:3000/login
环境:Ubuntu虚拟机中使用Android Studio开发,通过USB调试连接真实手机。
解决思路及方案
1. 修正网络连接地址
10.0.2.2是Android模拟器访问宿主机的专属回环地址,但你用的是真实手机,这个地址无法访问到Ubuntu虚拟机的服务器。解决方法:
- 确保手机和虚拟机处于同一局域网(比如手机连接电脑共享的WiFi,或同一路由器)
- 用
ifconfig或ip addr命令查看Ubuntu虚拟机的局域网IP(一般为192.168.x.x段) - 将代码中的
http://10.0.2.2:3000/login替换为虚拟机的局域网IP,例如http://192.168.1.100:3000/login
2. 确保服务器能解析JSON请求体
Express默认不会自动解析JSON格式的请求体,若未配置相关中间件,req.body会是undefined,导致服务器console.log输出空值。在server.js的app.post之前添加:
app.use(express.json());
3. 添加网络权限
检查AndroidManifest.xml是否添加了必要的网络权限:
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
4. 排查请求状态
在Android的post AsyncTask中,添加响应码打印,确认请求是否到达服务器:
// 在获取输入流之前添加 int responseCode = client.getResponseCode(); System.out.println("Response Code: " + responseCode);
- 若返回
200:请求到达服务器,需排查服务器解析逻辑 - 若返回
400/500:请求格式或服务器处理异常 - 若返回
0:网络连接失败,需检查地址、防火墙或局域网配置
5. 解决跨域问题(可选)
真实手机访问虚拟机服务器可能存在跨域限制,可在Express中添加cors中间件:
npm install cors
然后在server.js中配置:
const cors = require('cors'); app.use(cors());
内容的提问来源于stack exchange,提问作者abcd1211231
相关产品推荐
相关产品推荐

