Search code examples
androidjsongoogle-mapsandroid-asynctaskgoogle-maps-api-2

Getting location by address on Google Maps APIv2 using AsyncTask and JSON


I'm trying to implement a functionality in my app which allows you to find a place by address using Google Maps Api.
I'm trying to use AsyncTask and JSON to do it, but it always throws org.json.JSONException index 0 out of range (even if the location exists). I used to have the below code without async task, but it throwed exceptions when downloaded from playstore.

private class FindByAddress extends AsyncTask<String, Void, LatLng> {
@Override
public LatLng doInBackground(String... placesName) {
    HttpGet httpGet = new HttpGet("http://maps.google.com/maps/api/geocode/json?address=" +placesName+"&ka&sensor=false");
    HttpClient client = new DefaultHttpClient();
    HttpResponse response;
    StringBuilder stringBuilder = new StringBuilder();

    // Building/getting the JSON object...
    try {
        response = client.execute(httpGet);
        HttpEntity entity = response.getEntity();
        InputStream stream = entity.getContent();
        int b;
        while ((b = stream.read()) != -1) {
            stringBuilder.append((char) b);
        }
    } catch (ClientProtocolException e) {  } catch (IOException e) {  }

    JSONObject jsonObject = new JSONObject();

    try {
        jsonObject = new JSONObject(stringBuilder.toString());
    } catch (JSONException e) {
        e.printStackTrace();
    }

    // Collect results
    Double lon = new Double(0);
    Double lat = new Double(0);

    // IT MESSES UP HERE, index out of range [0..0) on getJSONObject
    try {
        lon = ((JSONArray)jsonObject.get("results")).getJSONObject(0)
                .getJSONObject("geometry").getJSONObject("location")
                .getDouble("lng");

        lat = ((JSONArray)jsonObject.get("results")).getJSONObject(0)
                .getJSONObject("geometry").getJSONObject("location")
                .getDouble("lat");

        } catch (JSONException e) {
            e.printStackTrace();
        }

        return new LatLng(lat, lon);

}

@Override
protected void onPostExecute(LatLng latilen) {
    // Show results
    if(latilen.latitude!=0 && latilen.longitude!=0){
        if(idioma.equals("english"))
            Toast.makeText(MainActivity.this, "Location found", Toast.LENGTH_SHORT).show();
        else if(idioma.equals("spanish"))
            Toast.makeText(MainActivity.this, "Dirección encontrada", Toast.LENGTH_SHORT).show();
        googleMap.animateCamera(CameraUpdateFactory.newLatLng(new LatLng(latilen.latitude, latilen.longitude)));
    }
    else if(idioma.equals("english"))
        Toast.makeText(MainActivity.this, "Location not found", Toast.LENGTH_SHORT).show();
    else if(idioma.equals("spanish"))
        Toast.makeText(MainActivity.this, "Dirección no encontrada", Toast.LENGTH_SHORT).show();
    }
}

I read somewhere that this needs to be in an asynctask, otherwise it throws an android.os.networkonmainthreadexception (which was my problem earlier). When I didnt have it in an asynctask at least it worked in my device (but not when downloaded from PlayStore).
With this AsyncTask thing doesn't work in any way.

I used to have this problem, so I had to change all the code for the one shown in the answer from @Ani in that same question.

Thankyou


Solution

  • If I understand what you are trying to do correctly, why don't you just use a GeoCoder...

    double lat, lng;
    Geocoder coder = new Geocoder(this, Locale.US);
    List<Address> results;
    try{
        results =  = coder.getLocationFromName(placeName, 5);    // 5 is max number of results
        if(results != null){
            Address location = results.get(0);
            lat = location.getLatitude();
            lng = location.getLongtitude();
        }
    }
    

    EDIT

    Since you were having a weird bug with the GeoCoding I understand wanting/needing to do an alternate method. You are basically just making and parsing the code yourself (probably how GeoCoding handles it though I haven't looked at the source). Thanks to your link, I was able to notice the culprit.

    AsyncTasks doInBackground method parameter takes the form of an array. Because of this you need to change your url call from ... + placesName + ... to ... + placesName[0] + .... Glad I was able to help. Best of luck with your project!