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

Android 9 Pie(API28)空对象引用问题排查求助

解决Android 9 Pie下JSONObject空指针异常问题

这个问题我太熟悉了——在Android 8上跑的好好的,到Android 9就炸了,核心原因是Android 9(API 28)开始默认禁用了明文HTTP请求。你的代码里用HttpURLConnection访问HTTP接口的话,请求会直接失败,导致doInBackground返回null,后续把null传给JSONArray构造器,就触发了String.length()的空指针异常。

第一步:确认问题根源

API 28及以上系统中,Google为了提升安全性,默认阻止App发起明文(非HTTPS)的网络请求。你的doInBackground方法里,请求失败时会返回null,然后在onPostExecute里直接把这个null传给loadIntoListView,new JSONArray(json)这一步就会因为json是null,内部调用String.length()时抛出异常。

第二步:修复方案

这里有两种常用解决方式,优先推荐第一种:

方案1:升级接口为HTTPS(强烈推荐)

这是最安全、符合Google规范的做法,把你的urlWebService换成HTTPS地址,直接绕过明文请求限制,问题就能解决。

方案2:允许明文HTTP请求(临时过渡方案)

如果暂时无法升级HTTPS,可以通过配置让App允许明文请求:

  • 快速方式:在AndroidManifest.xml的<application>标签里添加属性:
    <application
        ...
        android:usesCleartextTraffic="true">
    
  • 更安全的方式(针对特定域名开放):
    1. 在res/xml目录下创建network_security_config.xml,内容如下:
      <?xml version="1.0" encoding="utf-8"?>
      <network-security-config>
          <domain-config cleartextTrafficPermitted="true">
              <!-- 替换成你的接口域名 -->
              <domain includeSubdomains="true">your-api-domain.com</domain>
          </domain-config>
      </network-security-config>
      
    2. 在AndroidManifest.xml的<application>标签里引用这个配置:
      <application
          ...
          android:networkSecurityConfig="@xml/network_security_config">
      

第三步:优化代码,避免后续崩溃

除了网络配置问题,你的代码缺少空值判断,就算网络请求成功,也可能因为JSON格式不正确崩溃。建议修改这几处:

  1. 修改doInBackground,异常时返回空字符串而非null:

    @Override
    protected String doInBackground(Void... voids) {
        try {
            URL url = new URL(urlWebService);
            HttpURLConnection con = (HttpURLConnection) url.openConnection();
            StringBuilder sb = new StringBuilder();
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(con.getInputStream()));
            String json;
            while ((json = bufferedReader.readLine()) != null) {
                sb.append(json + "\n");
            }
            return sb.toString().trim();
        } catch (Exception e) {
            e.printStackTrace(); // 打印异常方便调试
            return ""; // 返回空字符串代替null
        }
    }
    
  2. 在onPostExecute里先判断返回值是否有效:

    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);
        if (s == null || s.isEmpty()) {
            Toast.makeText(getApplicationContext(), "请求失败或无数据", Toast.LENGTH_SHORT).show();
            return;
        }
        try {
            loadIntoListView(s);
        } catch (JSONException e) {
            e.printStackTrace();
            Toast.makeText(getApplicationContext(), "JSON解析失败", Toast.LENGTH_SHORT).show();
        }
    }
    
  3. 在loadIntoListView里增加空值判断,并用optString避免key不存在崩溃:

    private void loadIntoListView(String json) throws JSONException {
        if (json.isEmpty()) {
            // 处理空数据情况,比如显示空提示
            listView.setAdapter(null);
            Toast.makeText(this, "暂无数据", Toast.LENGTH_SHORT).show();
            return;
        }
        JSONArray jsonArray = new JSONArray(json);
        String[] stocks = new String[jsonArray.length()];
        for (int i = 0; i < jsonArray.length(); i++) {
            JSONObject obj = jsonArray.getJSONObject(i);
            // 用optString设置默认值,避免key不存在时崩溃
            String sentDate = obj.optString("sent_date", "未知时间");
            String username = obj.optString("username", "匿名用户");
            String message = obj.optString("message", "无内容");
            stocks[i] = sentDate + "| " + username + ": " + message;
        }
        ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, stocks);
        listView.setAdapter(arrayAdapter);
    }
    

这样修改后,不仅解决了Android 9的明文请求问题,还增强了代码的健壮性,能应对网络异常、JSON格式错误等多种情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:35:53