代码之家  ›  专栏  ›  技术社区  ›  Niels Vanwingh

REST API OpenWeatherMap不使用变量输入,可正确使用固定输入。。

  •  0
  • Niels Vanwingh  · 技术社区  · 6 年前

    应用程序从OpenWeatherMap API获取数据,并在我指示城市时正常工作,例如“伦敦”。用变量“place”替换“London”时出错。。在下面可以找到代码。 有人能帮我吗?

        **MAIN ACTIVITY** 
    
        public class MainActivity extends AppCompatActivity {
    
        //create the fields on the Activity
        private TextView cityName;
        private TextView temp;
        private TextView description;
        private TextView humidity;
        private TextView pressure;
        private TextView wind;
        private TextView sunrise;
        private TextView sunset;
        private TextView updated;
    
        private Exception error;
    
        Weather weather = new Weather();
    
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            //set up all the resources for the Views here
            cityName = (TextView)findViewById(R.id.cityText);
            temp = (TextView)findViewById(R.id.tempText);
            description = (TextView)findViewById(R.id.CloudText);
            humidity = (TextView)findViewById(R.id.HumidText);
            pressure = (TextView)findViewById(R.id.PressureText);
            wind = (TextView)findViewById(R.id.WindText);
            sunrise = (TextView)findViewById(R.id.RiseText);
            sunset = (TextView)findViewById(R.id.SetText);
            updated = (TextView)findViewById(R.id.UpdateText);
    
            //instantiate a CityPreference object from the MainActivity that 
           carries the city with it..
            //render the data based on the city you get through the parsing
            CityPreference cityPreference = new CityPreference(MainActivity.this);
            renderWeatherData(cityPreference.getCity());
        }
    
        public void renderWeatherData (String city){
        // we want to do all of our tasks in the background, use AsyncTask for this
    
            WeatherTask weatherTask = new WeatherTask();
            weatherTask.execute(new String[]{city} + "&units=metric");
            }
    
            //last parameter is Weather, this is what we will be populating
            private class WeatherTask extends AsyncTask<String, Void, Weather>{
    
            //AsyncTask <PARAMETERS, TASK, RESULT>
                @Override
                protected Weather doInBackground(String... params) {
                    //background computation
                    //data variable holds all the data that we have got..
                    //instantiate the weather client and get the weather data..
    
                    //getWeatherData gets all necessary data from HTTPClient
                    //getWeather parses all the data from the JSONParser
    
    
                        try {
                            String data = ((new WeatherHTTPClient().getWeatherData(params[0])));
                            weather = JSONWeatherParser.getWeather(data);
    
                            //create a log to test if everything is working
    
                            Log.v("Data:",weather.currentCondition.getDescription());
    
                            return weather;
    
                    } catch (Exception e) {
                        error = e;
                    }
                    return null;
                }
    
                //here you will populate the data so you can show it to the user
                @Override
                protected void onPostExecute(Weather weather) {
                    super.onPostExecute(weather);
    
                    try {
                        //gets time and decimal formats and applies it to the data underneath
                        DateFormat df = DateFormat.getTimeInstance();
                        String sunriseDate = df.format(new Date(Weather.place.getSunrise()));
                        String sunsetDate = df.format(new Date(Weather.place.getSunset()));
                        String updateDate = df.format(new Date(Weather.place.getLastupdate()));
    
                        DecimalFormat decimalFormat = new DecimalFormat("#.#");
                        String tempFormat = decimalFormat.format(weather.currentCondition.getTemperature());
    
                        //gets the value from the JSON and parses it in the view of the activity
                        cityName.setText(weather.place.getCity() + "," + weather.place.getCountry());
                        temp.setText("" + tempFormat + "C");
                        humidity.setText("Humidity" + weather.currentCondition.getHumidity() + "%");
                        pressure.setText("Pressure" + weather.currentCondition.getPressure() + "hPa");
                        wind.setText("Wind" + weather.wind.getSpeed() + "mps");
                        sunrise.setText("Sunrise" + sunriseDate);
                        sunset.setText("Sunset" + sunsetDate);
                        updated.setText("Updated" + updateDate);
                        description.setText("Condition" + weather.currentCondition.getCondition() + "(" + weather.currentCondition.getDescription() + ")");
    
                    } catch(Exception e) {
                        error = e;
                    }
                    }
            }
    
    
            //create an alert dialog to put in the city you want to parse the data for - A subclass of Dialog that can display one, two or three buttons.
    
            private void showInputDialog () {
    
                AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
                builder.setTitle("Change City");
                final EditText cityInput = new EditText(MainActivity.this);
                cityInput.setInputType(InputType.TYPE_CLASS_TEXT);
                cityInput.setHint("put down city name");
                builder.setView(cityInput);
                builder.setPositiveButton("Submit", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which){
    
                        CityPreference cityPreference = new CityPreference(MainActivity.this);
                        cityPreference.setCity(cityInput.getText().toString());
    
                        String newCity = cityPreference.getCity();
                        renderWeatherData(newCity);
    
                    }
                });
                        builder.show();
            }
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            //inflate the menu, this adds items to the action bar if it is present
            getMenuInflater().inflate(R.menu.main_menu, menu);
            return true;
        }
    
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
    
            int id = item.getItemId();
    
            if (id == R.id.change_cityId){
                showInputDialog();
            }
            return super.onOptionsItemSelected(item);
        }
    }
    
    
        **HTTP CLIENT**
    
        public class WeatherHTTPClient {
    
        public String getWeatherData (String place) throws IOException {
    
            // setting things up.., create connection between application and the web, everything we get from the web comes as an inputstream
            HttpURLConnection connection = null;
            InputStream inputStream = null;
    
            // api.openweathermap.org/data/2.5/weather?q=London
            // errors may occur when you connect to the internet, build this in the model with try...catch
    

    在下一个语句中,当我将“place”替换为“London”时,应用程序就可以运行了。这部分一定有错误,但我找不到。。我需要帮助。。

            try {
                connection = (HttpURLConnection) (new URL(Utils.BASE_URL + place +"&APPID=f77c39703fb6be71e2c5a96e58edc077")).openConnection();
                connection.setRequestMethod("GET");
                connection.setDoInput(true);
                connection.setDoOutput(true);
                connection.connect();
    
                //read the response, buffer "bucket" where you are going to put your data
                StringBuffer stringBuffer = new StringBuffer();
                //you get a stream of bits and data to your device - everything comes in as an inputstream
                inputStream = connection.getInputStream();
                //BufferedReader is the only thing that can read the stream of data - hold it and start reading
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
    
                String line = null;
    
                //line is set as the data read by the BufferedReader, Stringbuffer reads the Buffer and goes to the next one
                while ((line = bufferedReader.readLine()) != null){
                    stringBuffer.append(line + "\r\n");
                }
    
                inputStream.close();
                connection.disconnect();
    
                return stringBuffer.toString();
    
    
            } catch (IOException e) {e.printStackTrace();}
    
            return null;
        }
    }
    
    
        **WEATHER DATA MODEL JSON** 
    
    public class Weather {
        public static Place place;
        public String IconData;
        public CurrentCondition currentCondition = new CurrentCondition();
        public Temperature temperature = new Temperature();
        public Wind wind = new Wind();
        public Snow snow = new Snow();
        public Clouds clouds = new Clouds();
    }
    
        **PLACE DATA MODEL, left out getters and setters**
        **LEFT OUT THE FULL DATA MODEL**  
    
    public class Place {
        private float lon ;
        private float lat ;
        private long sunset;
        private long sunrise;
        private String country;
        private String city;
        private long lastupdate;
    
    **THE WEATHER PARSER**
    
    public class JSONWeatherParser {
    
        public static Weather getWeather(String data){
    
            //we call the top JSON object weather
            Weather weather = new Weather();
    
            //create JSONObject that holds all of the data you get from the web
            //place is the parameter you use to get all the data for
            //the rest of the variables you have to "calculate" from your data model
            //tagName needs to be EXACTLY as it is in the JSON
    
            try {
                JSONObject jsonObject = new JSONObject(data);
                Place place = new Place();
    
                //for each "header" in JSON you create a JSONObject or a JSONArray
                JSONObject coorObj = Utils.getObject("coord", jsonObject);
                //you set the latitude by getting the "lat" variable from the coorObj from the top JSON Object weather
                place.setLat(Utils.getFloat("lat",coorObj));
                place.setLon(Utils.getFloat("lon",coorObj));
    
                //get the sys object
                JSONObject sysObj = Utils.getObject("sys", jsonObject);
                place.setCountry(Utils.getString("country", sysObj));
                //dt Lastupdate is found directly under the jsonObject, hence ...
                place.setLastupdate(Utils.getInt("dt", jsonObject));
                place.setSunrise(Utils.getInt("sunrise",sysObj));
                place.setSunset(Utils.getInt("sunset",sysObj));
                place.setCity(Utils.getString("name",jsonObject));
                weather.place = place;
    
                //get the weather info, it is a JSONArray of the main jsonObject (the whole thing) - starts with square brackets
                JSONArray jsonArray = jsonObject.getJSONArray("weather");
                //get the underlying Jsonobject from the jsonarray
                JSONObject jsonWeather = jsonArray.getJSONObject(0);
                weather.currentCondition.setWeatherId(Utils.getInt("id",jsonWeather));
                weather.currentCondition.setDescription(Utils.getString("description", jsonWeather));
                weather.currentCondition.setCondition(Utils.getString("main",jsonWeather));
                weather.currentCondition.setIcon(Utils.getString("icon",jsonWeather));
    
                JSONObject mainObj = Utils.getObject("main", jsonObject);
                weather.currentCondition.setHumidity(Utils.getInt("humidity",mainObj));
                weather.currentCondition.setPressure(Utils.getInt("pressure",mainObj));
                weather.currentCondition.setMin_temp(Utils.getFloat("temp_min",mainObj));
                weather.currentCondition.setMax_temp(Utils.getFloat("temp_max", mainObj));
                weather.currentCondition.setTemperature(Utils.getDouble("temp",mainObj));
    
                JSONObject windObj = Utils.getObject("wind", jsonObject);
                weather.wind.setSpeed(Utils.getFloat("speed", windObj));
                weather.wind.setDeg(Utils.getFloat("deg",windObj));
    
                JSONObject cloudObj = Utils.getObject("clouds", jsonObject);
                weather.clouds.setPrecipitation(Utils.getInt("all", cloudObj));
    
                return weather;
    
    
            } catch (JSONException e) {
                e.printStackTrace();
            }
    
            return null;
        }
    }
    
    1 回复  |  直到 6 年前
        1
  •  0
  •   Soumya    6 年前

    如果您查看URL

    https://api.openweathermap.org/data/2.5/weather?q=[Ljava.lang.String;@34e4306&units=metric&APPID=f77c39703fb6be71e2c5a96e58edc077
    

    查询字段(q)的值为 [Ljava.lang.String;@34e4306 ,无效。确保在此位置发送正确的字符串值。

    是否可以修改此行:

    weatherTask.execute(new String[]{city} + "&units=metric");
    

    以下代码:

    weatherTask.execute(city + "&units=metric");
    

    希望这会有所帮助。