【问题标题】:OpenWeatherMap API : Encounter NullPointerException [duplicate]OpenWeatherMap API:遇到 NullPointerException [重复]
【发布时间】:2020-03-25 18:35:36
【问题描述】:

借助 OpenWeatherMap 及其提供的 API,我正在 Android Studio 上构建一个实时检索天气信息的应用程序。

问题是,我正在使用具有不同 SDK 的两部手机。一个是 SDK 23 / Android 6.0,另一个是 SDK 28 / Android 9.0。

目前在带有 SDK 23 的手机上我没有问题。但是在带有 SDK 28 的手机上,我遇到了 NullPointerException 错误。我的第二个活动允许我显示 X 城市的信息及其天气信息。所以,最后我在使用 SDK 28 的手机上遇到的错误是这个:

java.lang.NullPointerException:尝试在空对象引用上调用虚拟方法“int java.lang.String.length()”

如果不是我的 AsyncTask 或其他什么,我已经研究了很多东西,看看它可能来自哪里,但我真的没有看到它。

知道在具有最旧版本 Android 的手机上,它可以很好地从我的 editText 中检索信息,在最新版本上它根本不会检索它,并且 nullpointerException 必须来自那里。

你知道这可能来自哪里吗?

这是我的异步任务:

public class ExecuteTask extends AsyncTask<String, Void, String> {


    @Override
    protected String doInBackground(String... strings) {
        HttpURLConnection con = null ;
        InputStream is = null;

        try {
            con = (HttpURLConnection) ( new URL(strings[0])).openConnection();
            con.setRequestMethod("GET");
            con.setDoInput(true);
            con.setDoOutput(true);
            con.connect();

            // Let's read the response
            StringBuffer buffer = new StringBuffer();
            is = con.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            String line = null;
            while (  (line = br.readLine()) != null )
                buffer.append(line + "\r\n");

            is.close();
            con.disconnect();
            return buffer.toString();
        }
        catch(Throwable t) {
            t.printStackTrace();
        }
        finally {
            try { is.close(); } catch(Throwable t) {}
            try { con.disconnect(); } catch(Throwable t) {}
        }

        return null;
    }

    @Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);
        try {
            String message = "";
            String degre="";
            String idMeteo="";

            JSONObject jsonObject = new JSONObject(s);


            String infoWeatherToday = jsonObject.getString("weather");


            JSONObject WeatherTemperature = jsonObject.getJSONObject("main");
            Integer deg = WeatherTemperature.getInt("temp");

            deg = deg - 273;


            JSONArray array = new JSONArray(infoWeatherToday);
            int tablongueur=array.length();


            for (int i = 0; i < tablongueur; i++) {
                JSONObject jsonSecondary = array.getJSONObject(i);


                String main = "";
                //Integer id;


                main = jsonSecondary.getString("main");
                //  id = jsonSecondary.getInt("id");

                switch (main) {
                    case "Clouds":
                        main = "Nuageux";
                        PhotoMeteo.setImageResource(R.drawable.cloud);

                        break;
                    case "Clear":
                        main = "Ensoleillé";
                        PhotoMeteo.setImageResource(R.drawable.sun);

                        break;
                    case "Rain":
                        main = "Pluie";
                        PhotoMeteo.setImageResource(R.drawable.rain);

                        break;
                    case "Snow":
                        main = "Neige";
                        PhotoMeteo.setImageResource(R.drawable.snow);

                        break;
                    case "Smoke":
                        main = "Brouillard";
                        PhotoMeteo.setImageResource(R.drawable.smoke);

                        break;
                    case "Drizzle":
                        main = "Brumeux";
                        PhotoMeteo.setImageResource(R.drawable.drizzle);
                        break;
                    default:
                        main = "Météo introuvable !";
                        PhotoMeteo.setImageResource(R.drawable.ic_warning);
                }


                if (main != "" /*&& id != null*/) {
                    message += main + "\r\n";
                    degre += deg +  "°C";
                    //idMeteo += "L'id de la météo est" +  id;
                }

            }


            if (message != "") {
                resultWeather.setText(message);
                resultDegre.setText(degre);
                //resultIdMeteo.setText(idMeteo);
            } else {
                Toast.makeText(AccueilActivity.this, "Une erreur a eu lieu ", Toast.LENGTH_SHORT).show();
            }


        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

这是我在第一个名为 RegisterActivity 的活动中保留的意图,将其作为城市“名称”的参数

Intent intent = new Intent(RegisterActivity.this, AccueilActivity.class);
                intent.putExtra(EXTRA_TEXT,cityField.getText().toString());
                startActivity(intent);

在我的第二个名为 “AccueilActivity”

的活动中
Intent intent = getIntent();
    if(intent!=null)
    {
        textViewVille.setText(intent.getStringExtra(EXTRA_TEXT));
        ville = intent.getStringExtra(EXTRA_TEXT);
        FindWeather();

    }

我的最后一个函数称为 FindWeather,它执行 AsyncTask

public void FindWeather() {
    cityToFind = ville;

    try {
        ExecuteTask tasky = new ExecuteTask();
        tasky.execute("http://api.openweathermap.org/data/2.5/weather?q=" + cityToFind + "&APPID={MYAPKKEY}&LANG=fr&UNITS=metric");
    } catch (Exception e) {
        e.printStackTrace();
    }

}

只是我没有给你我的 APK Key 的值,因为它不是什么有趣的东西,但值存在于初始代码中。

如果我要添加最后的内容,ville 是一个简单的 TextView,cityToFind 是我在第一个活动上的 editText 值。

如果你需要我的源代码,我可以给你更多。

谢谢。

【问题讨论】:

  • 首先,不要使用 AsyncTask 进行 HTTP 调用。我不确定你是从哪里学来的……但它不再在这里了developer.android.com/guide/topics/connectivity
  • 您对我可以在所有这些工具中使用什么进行连接有什么建议吗?谢谢你:)
  • Android 团队推荐 Volley 至少用于 Java。 Kotlin 可能会有所不同
  • 请随时 edit 您的帖子提供任何更新的代码和完整的堆栈跟踪。

标签: java android nullpointerexception openweathermap


【解决方案1】:

如果您的 HTTP 代码中有任何异常,doInBackground 将转到 return null

即作为参数传递给onPostExecute

然后你尝试构造一个JSONObject(null),这是一个无效的参数


总而言之,请选择更高级别的内置容错的HTTP库

Comparison of Android networking libraries: OkHTTP, Retrofit, and Volley


我还建议在该类之外编写单元测试并从 IDE 而不是设备运行它们,这样您就可以验证网络调用是否确实有效。

【讨论】:

  • 我只按照我在 Youtube 上找到的教程进行操作,这是我第一次尝试执行 AsyncTask,我知道这不正常。你有什么建议来解决它,因为我不知道如何继续
  • 嗯,你明白吗what a NullPointerException is, and how to read a stacktrace? 诚实地学习是你应该如何进行的。不要只关注您的代码,而是要真正了解错误的含义以及错误发生的位置。
  • 读取堆栈跟踪的问题是我理解 NullPointerException 发生,但为什么两个 SDK 之间会有所不同?以及为什么 NullPointerException 只发生在最近的 SDK 中。我要试试你的链接,看看我能用这个做什么。
  • API 可能并不重要,但 Android 权限已更改。您需要在代码中显式启用网络功能。这是围绕 SDK 26 developer.android.com/training/permissions/requesting 实现的,事实上,您让应用程序崩溃是因为我的回答中的原因。而且您正在跳过阅读您在 catch 块中打印的 真正的异常 ...
  • 嗨 cricket_007,我添加了互联网权限,我今天早上也尝试了 Volley,最后它不起作用。我没有任何解决方案来解决它。我试图记录我的结果(因为我认为他在 doInBackground() 的末尾为空)但没有解决它,我不明白我该如何解决这个问题。
猜你喜欢
  • 2017-02-08
  • 1970-01-01
  • 1970-01-01
  • 2020-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-04
  • 2016-01-31
相关资源
最近更新 更多