REST API OpenWeatherMap 无法使用可变输入,但可以正确使用固定输入..

REST API OpenWeatherMap not working with Variable Input, works correctly with fixed input..

应用程序从 OpenWeatherMap API 获取数据并在我指示城市时正常工作,例如"London"。当我用变量 "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

当我在下一条语句中用 "London" 替换 "place" 时,应用程序可以正常工作。这部分一定有错误,但我找不到它..我需要帮助..

        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;
    }
}

如果你看 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");

希望这会有所帮助。