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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 02:27:06