0

im getting this error, trying to build a JSON parser with a ListView. I tried this code with another JSON source and it works but with this link crashes: http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_day.geojson

I´d love some help :D

Error:

05-21 20:53:32.871 2509-2606/com.ikeres.app.professorearthquake     W/System.err: org.json.JSONException: End of input at character 0 of 
05-21 20:53:32.872 2509-2606/com.ikeres.app.professorearthquake    W/System.err:     at org.json.JSONTokener.syntaxError(JSONTokener.java:449)
05-21 20:53:32.872 2509-2606/com.ikeres.app.professorearthquake W/System.err:     at org.json.JSONTokener.nextValue(JSONTokener.java:97)
05-21 20:53:32.872 2509-2606/com.ikeres.app.professorearthquake W/System.err:     at org.json.JSONObject.<init>(JSONObject.java:156)
05-21 20:53:32.872 2509-2606/com.ikeres.app.professorearthquake W/System.err:     at org.json.JSONObject.<init>(JSONObject.java:173)
05-21 20:53:32.872 2509-2606/com.ikeres.app.professorearthquake W/System.err:     at    com.ikeres.app.professorearthquake.MainActivity.ParseJSON(MainActivity.java:102)
05-21 20:53:32.872 2509-2606/com.ikeres.app.professorearthquake  W/System.err:     at   com.ikeres.app.professorearthquake.MainActivity.access$200(MainActivity.java:19)
05-21 20:53:32.872 2509-2606/com.ikeres.app.professorearthquake  W/System.err:     at  com.ikeres.app.professorearthquake.MainActivity$GetTerremotos.doInBackground(Mai nActivity.java:70)
05-21 20:53:32.872 2509-2606/com.ikeres.app.professorearthquake  W/System.err:     at  com.ikeres.app.professorearthquake.MainActivity$GetTerremotos.doInBackground(Mai nActivity.java:44)
05-21 20:53:32.872 2509-2606/com.ikeres.app.professorearthquake  W/System.err:     at android.os.AsyncTask$2.call(AsyncTask.java:295)
05-21 20:53:32.872 2509-2606/com.ikeres.app.professorearthquake W/System.err:     at java.util.concurrent.FutureTask.run(FutureTask.java:237)
05-21 20:53:32.872 2509-2606/com.ikeres.app.professorearthquake W/System.err:     at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:234)
05-21 20:53:32.872 2509-2606/com.ikeres.app.professorearthquake W/System.err:     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1113)
05-21 20:53:32.872 2509-2606/com.ikeres.app.professorearthquake  W/System.err:     at  java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:588)
05-21 20:53:32.872 2509-2606/com.ikeres.app.professorearthquake W/System.err:         at java.lang.Thread.run(Thread.java:818)

Here is the MainActivity:

public class MainActivity extends ListActivity {

// URL to get contacts JSON
private static String url = "http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_day.geojson";

// JSON Node names
private static final String TAG_FEATURES = "features";
private static final String TAG_PROPERTIES = "properties";
private static final String TAG_LUGAR = "lugar";
private static final String TAG_MAGNITUD = "magnitud";
private static final String TAG_HORA = "hora";


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // Calling async task to get json
    new GetTerremotos().execute();
}

/**
 * Async task class to get json by making HTTP call
 */
private class GetTerremotos extends AsyncTask<Void, Void, Void> {

    // Hashmap for ListView
    ArrayList<HashMap<String, String>> terremotostList;
    ProgressDialog pDialog;

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        // Showing progress dialog
        pDialog = new ProgressDialog(MainActivity.this);
        pDialog.setMessage("Please wait...");
        pDialog.setCancelable(false);
        pDialog.show();
    }

    @Override
    protected Void doInBackground(Void... arg0) {
        // Creating service handler class instance
        WebRequest webreq = new WebRequest();

        // Making a request to url and getting response
        String jsonStr = webreq.makeWebServiceCall(url, WebRequest.GET);

        Log.d("Response: ", "> " + jsonStr);

        terremotostList = ParseJSON(jsonStr);

        return null;
    }

    @Override
    protected void onPostExecute(Void result) {
        super.onPostExecute(result);
        // Dismiss the progress dialog
        if (pDialog.isShowing())
            pDialog.dismiss();
        /**
         * Updating parsed JSON data into ListView
         * */
        ListAdapter adapter = new SimpleAdapter(
                MainActivity.this, terremotostList,
                R.layout.list_item, new String[]{TAG_LUGAR, TAG_MAGNITUD,
                TAG_HORA}, new int[]{R.id.name,
                R.id.email, R.id.mobile});

        setListAdapter(adapter);
    }

}

private ArrayList<HashMap<String, String>> ParseJSON(String json) {
    if (json != null) {
        try {
            // Hashmap for ListView
            ArrayList<HashMap<String, String>> studentList = new ArrayList<HashMap<String, String>>();

            JSONObject jsonObj = new JSONObject(json);

            // Getting JSON Array node
            JSONArray terremotos = jsonObj.getJSONArray(TAG_FEATURES);

            // looping through All HeartQuakes
            for (int i = 0; i < terremotos.length(); i++) {
                JSONObject c = terremotos.getJSONObject(i);




                // Properties node is JSON Object
                JSONObject properties = c.getJSONObject(TAG_PROPERTIES);
                String lugar = properties.getString(TAG_LUGAR);
                String magnitud = properties.getString(TAG_MAGNITUD);
                String hora = properties.getString(TAG_HORA);

                // tmp hashmap for single hq
                HashMap<String, String> oterremoto = new HashMap<String, String>();

                // adding each child node to HashMap key => value
                oterremoto.put(TAG_LUGAR, lugar);
                oterremoto.put(TAG_MAGNITUD, magnitud);
                oterremoto.put(TAG_HORA, hora);


                // adding student to hq list
                studentList.add(oterremoto);
            }
            return studentList;
        } catch (JSONException e) {
            e.printStackTrace();
            return null;
        }
    } else {
        Log.e("ServiceHandler", "Couldn't get any data from the url");
        return null;
    }
}

}

WebRequest class:

public class WebRequest {

static String response = null;
public final static int GET = 1;
public final static int POST = 2;

//Constructor with no parameter
public WebRequest() {

}

/**
 * Making web service call
 *
 * @url - url to make request
 * @requestmethod - http request method
 */
public String makeWebServiceCall(String url, int requestmethod) {
    return this.makeWebServiceCall(url, requestmethod, null);
}

/**
 * Making service call
 *
 * @url - url to make request
 * @requestmethod - http request method
 * @params - http request params
 */
public String makeWebServiceCall(String urladdress, int requestmethod,
                                 HashMap<String, String> params) {
    URL url;
    String response = "";
    try {
        url = new URL(urladdress);

        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setReadTimeout(15000);
        conn.setConnectTimeout(15000);
        conn.setDoInput(true);
        conn.setDoOutput(true);

        if (requestmethod == POST) {
            conn.setRequestMethod("POST");
        } else if (requestmethod == GET) {
            conn.setRequestMethod("GET");
        }

        if (params != null) {
            OutputStream os = conn.getOutputStream();
            BufferedWriter writer = new BufferedWriter(
                    new OutputStreamWriter(os, "UTF-8"));

            StringBuilder result = new StringBuilder();
            boolean first = true;
            for (Map.Entry<String, String> entry : params.entrySet()) {
                if (first)
                    first = false;
                else
                    result.append("&");

                result.append(URLEncoder.encode(entry.getKey(), "UTF-8"));
                result.append("=");
                result.append(URLEncoder.encode(entry.getValue(), "UTF-8"));
            }

            writer.write(result.toString());

            writer.flush();
            writer.close();
            os.close();
        }

        int responseCode = conn.getResponseCode();

        if (responseCode == HttpsURLConnection.HTTP_OK) {
            String line;
            BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            while ((line = br.readLine()) != null) {
                response += line;
            }
        } else {
            response = "";
        }
    } catch (Exception e) {
        e.printStackTrace();
    }

    return response;
}

}

17
  • ParseJSON(jsonStr) in terremotostList = ParseJSON(jsonStr) may be returning null. Can you log your JSON string at the start of ParseJSON(jsonStr) to ensure the JSON was downloaded correctly? Commented May 21, 2016 at 20:26
  • I think the problem is what you said, but im a newbie and i dont know how to check if the JSON string was downloaded. Commented May 21, 2016 at 20:46
  • Well @R. Kirill did a great job pinpointing the issue but you could benefit from learning how to debug server responses so do this: Before if (json != null) try Log.v("JSON Response", json), then check the logcat to see if you get response the link you provided gives. Commented May 21, 2016 at 20:49
  • At the logcat i can check that i hace an error here: JSONObject jsonObj = new JSONObject(json); Commented May 21, 2016 at 21:04
  • Actually I took a second look and you're already logging your JSON response. It's this statement Log.d("Response: ", "> " + jsonStr); So search for it on your logcat. If you're not getting a response, you should be getting an exception in the ParseJSON method & it should be producing a stacktrace. Post the result from that stacktrace. Commented May 21, 2016 at 21:08

2 Answers 2

1

Finally got it. Remove the following lines from the WebRequest class:

    conn.setDoInput(true);
    conn.setDoOutput(true);

add the following after conn.setRequestMethod("GET");:

conn.connect();

Now you get JSON out of the API. After that your app would not display anything. That's because your tags are all in spanish and the API is in english so change:

private static final String TAG_LUGAR = "lugar";
private static final String TAG_MAGNITUD = "magnitud";
private static final String TAG_HORA = "hora";

to:

private static final String TAG_LUGAR = "place";
private static final String TAG_MAGNITUD = "mag";
private static final String TAG_HORA = "time";

It works after these changes.

Sign up to request clarification or add additional context in comments.

2 Comments

You are right man, I really love you, thanks very much for ur help!!
No problem at all, glad I could help, sorry it took a while. Just mark it as answered.
0

You need to check for fields existence when parsing your json. Your code fails at this line:

String lugar = properties.getString(TAG_LUGAR);

because there is no such field lugar in the returned json. So this line throws an exception, which is catched with this code:

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

and returns NULL. Then, you are creating an adapter and passing a null object:

ListAdapter adapter = new SimpleAdapter(
            MainActivity.this, terremotostList,
            R.layout.list_item, new String[]{TAG_LUGAR, TAG_MAGNITUD,
            TAG_HORA}, new int[]{R.id.name,
            R.id.email, R.id.mobile});

(terremotostList is null)

and finally your adapter fails trying to access getCount method of your list, which is null.

How to solve this problem? You should either check for field existence before getting its value:

String lugar = properties.has(TAG_LUGAR) ? properties.getString(TAG_LUGAR) : null;

or just use optString method, which doesn't throw an exception if field doesn't exist:

String lugar = properties.optString(TAG_LUGAR);

4 Comments

Thx, I tried this but it still crash, i tried to parse another url and it works, im so confused right now
did you try to replace with optString the other string fields as well (magnitud and hora) ?
Also Daniel mentioned above that you have to ensure that you receive the json from the server and it is not empty
Yes, i think the json in not being downloaded

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.