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

Android应用访问XAMPP本地数据库时JSONObject为空致崩溃原因排查

排查Android应用访问本地XAMPP数据库时JSONObject为空的问题

我来帮你一步步分析这个导致崩溃的空指针问题,咱们从最常见的原因开始排查:

一、先确认网络与服务器基础连通性

这是最容易忽略的前提:

  • 检查设备与服务器的局域网一致性:确保你的Android设备和运行XAMPP的电脑在同一个WiFi网络下,并且BASE_URL里的192.168.0.169是电脑的正确局域网IP(可以在电脑的命令行用ipconfig(Windows)或ifconfig(Linux/Mac)查看)。
  • 直接用手机浏览器测试接口:打开手机浏览器,访问http://192.168.0.169/movies/fetch_all_movies.php。如果浏览器打不开或者返回错误页面,那问题出在XAMPP配置或PHP脚本,和App代码无关:
    • 确认XAMPP的Apache服务已经启动;
    • 确认fetch_all_movies.php文件放在XAMPP的htdocs/movies/目录下;
    • 检查PHP脚本是否有语法错误或数据库连接失败,可以在PHP开头添加错误输出:
      error_reporting(E_ALL);
      ini_set('display_errors', 1);
      
    • 确保PHP脚本返回的是合法JSON格式,比如正确的结构应该是:
      {"success":1,"data":[{"movie_id":"1","movie_name":"Test Movie"}]}
      

二、检查Android应用的网络权限与明文访问限制

  • 添加网络权限:在AndroidManifest.xml中必须声明网络权限:
    <uses-permission android:name="android.permission.INTERNET" />
    
  • Android 9+明文HTTP访问限制:如果你的App目标SDK是28及以上,默认禁止明文HTTP请求,需要在AndroidManifest.xml的application标签中添加:
    android:usesCleartextTraffic="true"
    

三、修复HttpJsonParser类的错误处理缺陷

你的HttpJsonParser类在出现网络错误、服务器错误或JSON解析失败时,只是打印日志但依然返回null,导致后续代码崩溃。我们需要增强错误处理,明确问题原因:

public JSONObject makeHttpRequest(String url, String method, Map<String, String> params) {
    try {
        Uri.Builder builder = new Uri.Builder();
        URL urlObj;
        String encodedParams = "";
        if (params != null) {
            for (Map.Entry<String, String> entry : params.entrySet()) {
                builder.appendQueryParameter(entry.getKey(), entry.getValue());
            }
        }
        if (builder.build().getEncodedQuery() != null) {
            encodedParams = builder.build().getEncodedQuery();
        }
        if ("GET".equals(method)) {
            url = url + "?" + encodedParams;
            urlObj = new URL(url);
            urlConnection = (HttpURLConnection) urlObj.openConnection();
            urlConnection.setRequestMethod(method);
        } else {
            urlObj = new URL(url);
            urlConnection = (HttpURLConnection) urlObj.openConnection();
            urlConnection.setRequestMethod(method);
            urlConnection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
            urlConnection.setRequestProperty("Content-Length", String.valueOf(encodedParams.getBytes().length));
            urlConnection.getOutputStream().write(encodedParams.getBytes());
        }
        urlConnection.connect();

        // 新增:检查服务器响应码
        int responseCode = urlConnection.getResponseCode();
        if (responseCode != HttpURLConnection.HTTP_OK) {
            // 读取错误流,打印错误信息
            is = urlConnection.getErrorStream();
            BufferedReader errorReader = new BufferedReader(new InputStreamReader(is));
            StringBuilder errorSb = new StringBuilder();
            String errorLine;
            while ((errorLine = errorReader.readLine()) != null) {
                errorSb.append(errorLine + "\n");
            }
            Log.e("HttpError", "Response Code: " + responseCode + ", Error Message: " + errorSb.toString());
            is.close();
            return null;
        }

        is = urlConnection.getInputStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        StringBuilder sb = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {
            sb.append(line + "\n");
        }
        is.close();
        json = sb.toString();
        Log.d("ReceivedJson", json); // 新增:打印收到的原始JSON,方便排查格式问题
        jObj = new JSONObject(json);
    } catch (UnsupportedEncodingException e) {
        Log.e("EncodingError", e.toString());
    } catch (ProtocolException e) {
        Log.e("ProtocolError", e.toString());
    } catch (IOException e) {
        Log.e("IOException", e.toString());
    } catch (JSONException e) {
        Log.e("JSONParserError", "Failed to parse JSON: " + e.toString() + ", Raw JSON: " + json);
    } catch (Exception e) {
        Log.e("GeneralError", e.toString());
    } finally {
        if (urlConnection != null) {
            urlConnection.disconnect(); // 新增:关闭连接,避免资源泄漏
        }
    }
    return jObj;
}

四、在MovieListingActivity中添加空指针判断

在doInBackground中,必须先判断jsonObject是否为null,再进行后续操作,避免崩溃:

@Override
protected String doInBackground(String... params) {
    HttpJsonParser httpJsonParser = new HttpJsonParser();
    JSONObject jsonObject = httpJsonParser.makeHttpRequest(
            BASE_URL + "fetch_all_movies.php", "GET", null);
    
    if (jsonObject != null) {
        try {
            int success = jsonObject.getInt(KEY_SUCCESS);
            // 这里可以继续处理成功后的逻辑,比如解析data数组
            Log.d("Success", "Success code: " + success);
        } catch (JSONException e) {
            Log.e("JSONError", "Failed to get success key: " + e.getMessage());
            e.printStackTrace();
        }
    } else {
        Log.e("NullError", "JSONObject is null - check network, server or PHP script");
    }
    return null;
}

按照这个顺序排查,你应该能快速定位到问题所在——大概率是网络连通性、PHP脚本错误或者Android的明文访问限制导致的。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 06:52:51