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

向HTTP提交XML失败:Android NetworkOnMainThreadException问题求助

问题分析与解决方案

首先看你日志里的核心错误:android.os.NetworkOnMainThreadException,这是Android开发里非常常见的问题——你直接在Activity的onCreate方法里调用了postXML(),也就是把网络请求放在了**主线程(UI线程)**里执行。

从Android 3.0(API 11)开始,系统严格禁止在主线程中进行网络操作,因为网络请求是耗时操作,会阻塞UI线程,导致界面卡顿甚至出现ANR(应用无响应)弹窗。

解决步骤:

1. 把网络请求移到子线程执行

你可以用AsyncTask(适合简单场景)或者直接创建新线程处理网络操作。这里给你修改后的实现,用AsyncTask封装更贴合你当前的代码结构:

private class PostXmlTask extends AsyncTask<Void, Void, Boolean> {

    @Override
    protected Boolean doInBackground(Void... voids) {
        HttpURLConnection conn = null;
        try {
            URL url = new URL(URLchanges);
            conn = (HttpURLConnection) url.openConnection();
            conn.setReadTimeout(10000);
            conn.setConnectTimeout(15000);
            conn.setRequestMethod("POST");
            // 关键:设置请求头,告诉服务器我们发送的是XML格式
            conn.setRequestProperty("Content-Type", "application/xml; charset=UTF-8");
            conn.setDoInput(true);
            conn.setDoOutput(true);

            // 修正XML字符串:Java字符串里不需要转义&lt;和&gt;,直接写正常标签即可
            String xmlContent = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
                    "<Devices>" +
                    "<Device>" +
                    "<ID>EZR010A49</ID>" +
                    "<DATETIME>2014-01-20T11:40:00</DATETIME>" +
                    "</Device>" +
                    "</Devices>";

            OutputStream output = new BufferedOutputStream(conn.getOutputStream());
            output.write(xmlContent.getBytes(StandardCharsets.UTF_8)); // 指定编码避免乱码
            output.flush();
            output.close();

            // 检查响应码,确认请求是否真的成功
            int responseCode = conn.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) {
                Log.d("posted", "请求成功,响应码:" + responseCode);
                return true;
            } else {
                Log.d("posted", "请求失败,响应码:" + responseCode);
                return false;
            }
        } catch (Exception e) {
            e.printStackTrace();
            Log.d("ERROR", "网络请求出错:" + e.getMessage());
            return false;
        } finally {
            if (conn != null) {
                conn.disconnect(); // 确保conn不为null再关闭,避免空指针异常
            }
        }
    }

    @Override
    protected void onPostExecute(Boolean success) {
        super.onPostExecute(success);
        // 这里可以更新UI,比如用Toast提示请求结果
        if (success) {
            Toast.makeText(MainActivity.this, "XML发送成功", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(MainActivity.this, "XML发送失败", Toast.LENGTH_SHORT).show();
        }
    }
}

然后在onCreate里替换原来的postXML()调用:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    URLchanges = "http://192.168.178.37/data/changes.xml";
    URLstats = "http://192.168.178.37/data/static.xml";
    // 启动异步任务执行网络请求
    new PostXmlTask().execute();
}

2. 补充必要的网络权限

在你的AndroidManifest.xml里必须添加网络权限,否则所有网络请求都会失败:

<uses-permission android:name="android.permission.INTERNET" />

3. 其他细节优化

  • 你原来的XML字符串用了&lt;和&gt;,这是HTML/XML文档里的转义字符,但在Java字符串中直接写<和>就可以,转义后服务器收到的XML会是错误格式,可能导致解析失败。
  • 发送数据时指定UTF-8编码,避免出现乱码问题。
  • 不要只靠日志判断请求成功,一定要检查服务器返回的响应码,比如HTTP_OK(200)才代表请求正常完成。

额外建议(针对新版本Android)

如果你的项目基于API 26+,更推荐使用**Coroutines(协程)**处理网络请求,代码更简洁且能避免AsyncTask的潜在内存泄漏问题:

// 在onCreate里调用
lifecycleScope.launch {
    val success = postXmlCoroutine()
    Toast.makeText(MainActivity.this, success ? "发送成功" : "发送失败", Toast.LENGTH_SHORT).show();
}

// 协程版网络请求方法
private suspend fun postXmlCoroutine(): Boolean {
    return withContext(Dispatchers.IO) {
        // 这里写和AsyncTask中doInBackground一致的网络请求逻辑即可
        // ...
    }
}

内容的提问来源于stack exchange,提问作者user9216568

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:38:26