Android Location API in developing Weather App – Search city

This post describes how to use Android location API and  how to search a city using openweathermap to get weather conditions. There are two way we can use to find a city:

  • Using name pattern
  • Using geographic coordinates (Android Location API)

We will introduce, moreover, some concepts about Android location API and Location-based service.

Searching city by name

In this kind of search, an user inserts a part of city name and the app will show all the possible result matching the pattern. From the UI perspective, we want to obtain something like the image shown below:

android weather app search city
As first step, we can use EditText so that the user can insert the city name:

[xml]<RelativeLayout xmlns:android=”http://schemas.android.com/apk/res/android”
android:layout_width=”match_parent”
android:layout_height=”match_parent”>

….
<EditText
android:id=”@+id/cityEdtText”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:layout_alignParentLeft=”true”
android:layout_below=”@+id/textView1″
android:layout_marginTop=”5dp”
android:imeOptions=”actionSearch”
android:inputType=”text” >
<requestFocus />
</EditText>

<ListView android:id=”@+id/cityList”
android:layout_width=”wrap_content”
android:layout_height=”wrap_content”
android:layout_below=”@id/txt1″
android:layout_marginTop=”3dp”/>

</RelativeLayout>[/xml]

Notice that at line 13, we used imeOptions with “actionSearch” value to specify search action when an user completes inserting the city name pattern.

Now in the Activity that holds this layout we have:

[java]final EditText edt = (EditText) findViewById(R.id.cityEdtText);

edt.setOnEditorActionListener(new TextView.OnEditorActionListener() {

@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
bar.setVisibility(View.VISIBLE);
JSONSearchTask task = new JSONSearchTask();
String pattern = edt.getEditableText().toString();
task.execute(new String[]{pattern});
return true;
}

return false;
}
});[/java]

So when an user clicks on the search icon, we start searching for matching city names and at the end, we will populate a ListView (line 18) . As you can notice, we start an AsyncTask, because the search operation can require quite long time and we don’t want to have ANR problems.

Now it is time to implement the logic that calls the remote openweathermap service and retrieve the cities. We know from API that the URL to call is:

http://api.openweathermap.org/data/2.5/find?mode=json&type=like&q=...&cnt=10

where after q we will add our pattern name and cnt represents the number of items we want to get (in our case we want 10 results at maximum).

Once we have the data, we parse it. We look for list tag that holds the result and for each item in the result we look for name tag that holds the name, the id and the country. The parser is very simple:

[java]public static List&lt;City&gt; getCityList(String data) throws JSONException {
JSONObject jObj = new JSONObject(data);
JSONArray jArr = jObj.getJSONArray(“list”);

List<City> cityList = new ArrayList<City>();

for (int i=0; i < jArr.length(); i++) {
JSONObject obj = jArr.getJSONObject(i);

String name = obj.getString(“name”);
String id = obj.getString(“id”);

JSONObject sys = obj.getJSONObject(“sys”);
String country = sys.getString(“country”);

City c = new City(id,name,country);

cityList.add(c);
}

return cityList;
}[/java]

..and finally, we populate the ListView to show the results to the user. This happens in  onPostExecute method of the AsyncTask. Notice that you can create a custom Adapter to show this information or you can use a standard Adapter.

Search city using geographic coordinates: Android Location API

Another way to look for the city is using the current user position. We can use Location based service to find the current device position using GPS or WI-FI or cell network. There are two main elements when implementing Location based service:

  • Location Manager that is the entry point to the Location based service
  • Location Provider representing the location technology used to find the device position

The first step is getting the LocationManager reference. This is a system service, then we can use:

LocationManager locManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

once we have our Location Manager reference we can find the provider. In our case, we don’t want to specify a specific provider (like GPS for example) but let the system find the best matching the search criteria we set:

[java]private static Criteria searchProviderCriteria = new Criteria();

// Location Criteria
static {
searchProviderCriteria.setPowerRequirement(Criteria.POWER_LOW);
searchProviderCriteria.setAccuracy(Criteria.ACCURACY_COARSE);
searchProviderCriteria.setCostAllowed(false);
}[/java]

and then we are ready to get the provider:

String provider = locManager.getBestProvider(searchProviderCriteria, true);

and:

[java]Location loc = locManager.getLastKnownLocation(provider);[/java]

Now we have to check if the location is null or is too old, in this case we get a new position:

[java]if (loc == null || (SystemClock.elapsedRealtime() – loc.getTime()) &amp;gt; timeOut) {
// We request another update Location
Log.d(“SwA”, “Request location”);
locManager.requestSingleUpdate(provider, locListener, null);
}
else {
JSONSearchTask task = new JSONSearchTask();
task.execute(new Location[]{loc});
}[/java]

otherwise, we simply call the service to get the city. Notice at line 4, that we need a listener that implements some callback methods, that will be called when the current position is available:

[java]private LocationListener locListener = new LocationListener() {

@Override
public void onStatusChanged(String provider, int status,
Bundle extras) {
}

@Override
public void onProviderEnabled(String provider) {
}

@Override
public void onProviderDisabled(String provider) {
}

@Override
public void onLocationChanged(Location location) {
Log.d(“SwA”, “Location changed!”);
String sLat = “” + location.getLatitude();
String sLon = “” + location.getLongitude();
Log.d(“SwA”, “Lat [“+sLat+”] – sLong [“+sLon+”]”);

LocationManager locManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locManager.removeUpdates(locListener);
JSONSearchTask task = new JSONSearchTask();
task.execute(new Location[]{location});
}
};[/java]

The last step is creating the URL that will be called to retrieve the city from the geographic coordinates. In this case the url to call is:

http://api.openweathermap.org/data/2.5/find?lat=%lat%&lon=%lon%

where the %lat% and &lon% will be substituted by the real value extracted from the current position.

Using emulator to test the app

The last step is testing the app passing the coordinates. We can use DDMS and pass the coordinates:
android ddms location

Please notice that you should separate the decimal part according to your language and number format.

Another way is using

[plain]telnet iphost port[/plain]

and when connected send

[plain]geo fix <longitude value> <latitude value>[/plain]

At the end of this post, you gained the knowledge about how to use android location api.

    1. Felix August 24, 2014
    2. Felix August 24, 2014
    3. survivingwithandroid August 26, 2014
    4. myria September 4, 2014
    5. Francesco Azzola September 4, 2014
    6. myria September 5, 2014
    7. abinaya September 28, 2014
    8. boshra May 20, 2015
    9. boshra May 20, 2015
    10. Mike December 10, 2019
      • Francesco Azzola December 10, 2019

    Add Your Comment