Weather

The app creates a second thread with AsyncTask. The thread sends an HTTP GET command to the Open Weathermap server. (Compare the download without the GET in exercise 7 of Offer.) See OpenWeatherMap’s documentation for the zip, units, and mode parameters of the URL.

The response is a String containing a string in JSON format representing a JSON object. We call the constructor for class JSONObject to create a JSONObject that holds the information in this JSON object, and call getJSONObject, getDouble, and getLong to get some of the fields of the JSON object.

Source code in Weather.zip

  1. MainActivity.java
  2. activity_main.xml consists of a RelativeLayout containing a ScrollView containing a TextView. The ScrollView lets the TextView scroll.
  3. strings.xml
  4. AndroidManifest.xml has uses-permission INTERNET.
  5. build.gradle (Module: app).

Output into the TextView

See Parameters, Weather Condition Codes, and Weather icons.

JSON string downloaded from server =
{"coord":{"lon":-74.01,"lat":40.71},"weather":[{"id":701,"main":"Mist","description":"mist","icon":"50n"},{"id":500,"main":"Rain","description":"light rain","icon":"10n"}],"base":"cmc stations","main":{"temp":76.69,"pressure":1015,"humidity":65,"temp_min":70,"temp_max":84.2},"wind":{"speed":7.78,"deg":220},"clouds":{"all":40},"dt":1436324173,"sys":{"type":1,"id":1975,"message":0.006,"country":"US","sunrise":1436347955,"sunset":1436401761},"id":5128581,"name":"New York","cod":200}

JSON object =
{
    "id": 5128581,
    "dt": 1436324173,
    "clouds": {
        "all": 40
    },
    "coord": {
        "lat": 40.71,
        "lon": -74.01
    },
    "wind": {
        "speed": 7.78,
        "deg": 220
    },
    "cod": 200,
    "sys": {
        "message": 0.006,
        "id": 1975,
        "sunrise": 1436347955,
        "type": 1,
        "sunset": 1436401761,
        "country": "US"
    },
    "name": "New York",
    "base": "cmc stations",
    "weather": [
        {
            "id": 701,
            "icon": "50n",
            "description": "mist",
            "main": "Mist"
        },
        {
            "id": 500,
            "icon": "10n",
            "description": "light rain",
            "main": "Rain"
        }
    ],
    "main": {
        "temp_min": 70,
        "temp": 76.69,
        "humidity": 65,
        "pressure": 1015,
        "temp_max": 84.2
    }
}

dt = 1436324173
dt = Tuesday, July 7, 2015 10:56:13 PM EDT

main =
{
    "temp_min": 70,
    "temp": 76.69,
    "humidity": 65,
    "pressure": 1015,
    "temp_max": 84.2
}

Temperature in 10003 is 76.69° Fahrenheit.

Things to try

  1. The urlString is pasted together with question marks, ampersands, and equal signs. Instead of pasting it yourself, create it with a Uri.Builder. It’s like the AlertDialog.Builder we saw in Text.
                Uri uri = Uri.parse("http://api.openweathermap.org/data/2.5/weather");
                Uri.Builder builder = uri.buildUpon();
                builder.appendQueryParameter("zip", zip[0]);
                builder.appendQueryParameter("units", "imperial");
                builder.appendQueryParameter("mode", "json");
                uri = builder.build();
                String urlString = uri.toString();
    

    You can even do it in a single statement:

                String urlString =
                    Uri.parse("http://api.openweathermap.org/data/2.5/weather")
                    .buildUpon()
                    .appendQueryParameter("zip", zip[0])
                    .appendQueryParameter("units", "imperial")
                    .appendQueryParameter("mode", "json")
                    .build()
                    .toString();
    

  2. Read an array of values from the server, for example, the maximum temperature for each of the next seven days. Store the values in a Java array, plug the Java array into an ArrayAdapter<String>, and plug the ArrayAdapter<String> into a ListView.

    In activity_main.xml, replace the TextView with the following.

        <ListView
            android:id="@+id/listView"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>
    

    In doInBackground in MainActivity.java,

            String urlString =
                    "http://api.openweathermap.org/data/2.5/forecast/daily"
                    + "?zip=" + zip[0]  //7 East 12th Street, New York NY  10003
                    + "&cnt=5"          //number of days
                    + "&units=imperial" //fahrenheit, not celsius
                    + "&mode=json";     //vs. xml or html
    

    Change useTheResult to the following.

        private void useTheResult(String json) {
            if (json == null) {
                return;
            }
    
            String[] a = new String[5];
            try {
                JSONObject jSONObject = new JSONObject(json);
                JSONArray list = jSONObject.getJSONArray("list");
                DateFormat dateFormat =
                        DateFormat.getDateInstance(DateFormat.FULL, Locale.getDefault());
    
                for (int i = 0; i < list.length(); ++i) {
                    JSONObject day = (JSONObject)list.get(i);
                    long seconds = day.getLong("dt");
                    JSONObject temp = (JSONObject)day.getJSONObject("temp");
                    double max = temp.getDouble("max");
                    a[i] = Math.round(max) + "\u00B0 F   " + dateFormat.format(1000L * seconds);
                }
            } catch (JSONException exception) {
                Toast toast = Toast.makeText(this, exception.toString(), Toast.LENGTH_LONG);
                toast.show();
            }
    
            ArrayAdapter<String> adapter = new ArrayAdapter<String> (
                    this,
                    android.R.layout.simple_list_item_1,
                    a
            );
    
            ListView listView = (ListView)findViewById(R.id.listView);
            listView.setAdapter(adapter);
        }
    

    The JSON object contains an array named list. The array contains five days in its [square brackets].

    {
        "message": 0.0156,
        "list": [
            {
                "clouds": 12,
                "dt": 1436288400,
                "humidity": 84,
                "pressure": 1010.12,
                "speed": 4.8,
                "deg": 221,
                "weather": [
                    {
                        "id": 801,
                        "icon": "02n",
                        "description": "few clouds",
                        "main": "Clouds"
                    }
                ],
                "temp": {
                    "morn": 75.31,
                    "min": 72.88,
                    "night": 72.88,
                    "eve": 75.31,
                    "max": 75.31,
                    "day": 75.31
                }
            },
            {
                "clouds": 80,
                "dt": 1436374800,
                "humidity": 80,
                "pressure": 1007.54,
                "speed": 5.96,
                "deg": 245,
                "weather": [
                    {
                        "id": 500,
                        "icon": "10d",
                        "description": "light rain",
                        "main": "Rain"
                    }
                ],
                "temp": {
                    "morn": 75.7,
                    "min": 70,
                    "night": 70,
                    "eve": 76.89,
                    "max": 80.15,
                    "day": 80.15
                },
                "rain": 1.08
            },
            {
                "clouds": 56,
                "dt": 1436461200,
                "humidity": 87,
                "pressure": 1009.84,
                "speed": 3.05,
                "deg": 162,
                "weather": [
                    {
                        "id": 502,
                        "icon": "10d",
                        "description": "heavy intensity rain",
                        "main": "Rain"
                    }
                ],
                "temp": {
                    "morn": 67.14,
                    "min": 63.55,
                    "night": 63.55,
                    "eve": 73.22,
                    "max": 74.82,
                    "day": 73.35
                },
                "rain": 16.8
            },
            {
                "clouds": 0,
                "dt": 1436547600,
                "humidity": 63,
                "pressure": 1013.03,
                "speed": 4.56,
                "deg": 347,
                "weather": [
                    {
                        "id": 800,
                        "icon": "01d",
                        "description": "sky is clear",
                        "main": "Clear"
                    }
                ],
                "temp": {
                    "morn": 65.93,
                    "min": 64.27,
                    "night": 64.27,
                    "eve": 72.82,
                    "max": 78.15,
                    "day": 76.89
                }
            },
            {
                "clouds": 5,
                "dt": 1436634000,
                "humidity": 0,
                "pressure": 1016.29,
                "speed": 2.31,
                "deg": 298,
                "weather": [
                    {
                        "id": 500,
                        "icon": "10d",
                        "description": "light rain",
                        "main": "Rain"
                    }
                ],
                "temp": {
                    "morn": 70.93,
                    "min": 68.29,
                    "night": 68.29,
                    "eve": 76.46,
                    "max": 78.33,
                    "day": 78.33
                },
                "rain": 0.37
            }
        ],
        "cnt": 5,
        "cod": "200",
        "city": {
            "coord": {
                "lat": 40.714272,
                "lon": -74.005966
            },
            "id": 5128581,
            "population": 0,
            "country": "US",
            "name": "New York"
        }
    }