Saturday, October 17, 2015

Get ISO country code for the given latitude/longitude, using GeoNames Web Service, using HttpURLConnection

The GeoNames geographical database covers all countries and contains over eight million placenames that are available for download free of charge. We can get the iso country code for any given latitude/longitude, using GeoNames webservices; api.geonames.org/countryCode?



CountryCode / reverse geocoding

The iso country code of any given point.
Webservice Type : REST 
Url : api.geonames.org/countryCode?
Parameters : lat,lng, type, lang, radius (buffer in km for closest country in coastal areas, a positive buffer expands the positiv area whereas a negative buffer reduces it);
Result : returns the iso country code for the given latitude/longitude
With the parameter type=xml this service returns an xml document with iso country code and country name. The optional parameter lang can be used to specify the language the country name should be in. JSON output is produced with type=JSON
Example http://api.geonames.org/countryCode?lat=47.03&lng=10.2&username=demo 

Important:

  • Do not use the 'demo' account for your app or your tests. It is only meant for the sample links on the documentation pages. Create your own account instead.
  • The parameter 'username' needs to be passed with each request. The username for your application can be registered here. You will then receive an email with a confirmation link and after you have confirmed the email you can enable your account for the webservice on your account page
  • Don't forget to url encode string parameters containing special characters or spaces. (Faq entry on url encoding)
  • ...


It's a example to get the ISO country code of user entered latitude/longitude.


MainActivity.java
package com.blogspot.android_er.androidgeonames;

import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

public class MainActivity extends AppCompatActivity {

    EditText latText;
    EditText lonText;
    Button btnFind;
    TextView textResult;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        latText = (EditText)findViewById(R.id.latText);
        lonText = (EditText)findViewById(R.id.lonText);
        btnFind = (Button)findViewById(R.id.find);
        textResult = (TextView)findViewById(R.id.result);

        btnFind.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                String strLat = latText.getText().toString();
                String strLon = lonText.getText().toString();

                new GeoNamesTask(textResult).execute(strLat, strLon);
            }
        });
    }

    private class GeoNamesTask extends AsyncTask<String, Void, String> {
        TextView tResult;

        public GeoNamesTask(TextView vResult){
            tResult = vResult;
            tResult.setText("");
        }

        @Override
        protected String doInBackground(String... params) {

            /*
            Do not use the 'demo' account for your app or your tests.
            It is only meant for the sample links on the documentation pages.
            Create your own account instead.
             */
            String queryString =
                    "http://api.geonames.org/countryCode?lat=" + params[0]
                    + "&lng=" + params[1] + "&username=demo";

            String s = "";
            try {
                s = sendQuery(queryString);
            } catch (IOException e) {
                e.printStackTrace();
                s = e.getMessage();
            }
            return s;
        }

        @Override
        protected void onPostExecute(String s) {
            tResult.setText(s);
        }


        private String sendQuery(String query) throws IOException {
            String result = "";

            URL searchURL = new URL(query);

            HttpURLConnection httpURLConnection = (HttpURLConnection)searchURL.openConnection();
            if(httpURLConnection.getResponseCode() == HttpURLConnection.HTTP_OK){
                InputStreamReader inputStreamReader = new InputStreamReader(httpURLConnection.getInputStream());
                BufferedReader bufferedReader = new BufferedReader(
                        inputStreamReader,
                        8192);

                String line = null;
                while((line = bufferedReader.readLine()) != null){
                    result += line;
                }

                bufferedReader.close();
            }

            return result;
        }
    }
}


layout/activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="16dp"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:autoLink="web"
        android:text="http://android-er.blogspot.com/"
        android:textStyle="bold" />

    <EditText
        android:id="@+id/latText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:inputType="numberSigned|numberDecimal"
        android:hint="Latitude"
        android:text="47.03"/>

    <EditText
        android:id="@+id/lonText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:inputType="numberSigned|numberDecimal"
        android:hint="Longitude"
        android:text="10.2"/>

    <Button
        android:id="@+id/find"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="find"/>

    <TextView
        android:id="@+id/result"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>


Permission of "android.permission.INTERNET" is needed in AndroidManifest.xml
    <uses-permission android:name="android.permission.INTERNET"/>

Next:
GeoNames also provide Java Client for GeoNames Webservices to help developers to easily access the geonames web services with java. Next post "Get ISO country code for the given latitude/longitude, using GeoNames Java Client" show how to use it in Android Studio project.

Related:
- Find addresses of given latitude and longitude using android.location.Geocoder

No comments: