0

Original Question -

I was following a tutorial on json in android, but having problem to get json value using Async in android. First I created jsonparser class and added following to it -

    public JSONObject getJSONFromUrl(String url) {

    // Making HTTP request
    try {
        // defaultHttpClient
        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpPost httpPost = new HttpPost(url);

        HttpResponse httpResponse = httpClient.execute(httpPost);
        HttpEntity httpEntity = httpResponse.getEntity();
        is = httpEntity.getContent();           

    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    } catch (ClientProtocolException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }

    try {
        BufferedReader reader = new BufferedReader(new InputStreamReader(
                is, "iso-8859-1"), 8);
        StringBuilder sb = new StringBuilder();
        String line = null;
        while ((line = reader.readLine()) != null) {
            sb.append(line + "\n");
        }
        is.close();
        json = sb.toString();
    } catch (Exception e) {
//      Log.e("Buffer Error", "Error converting result " + e.toString());
    }

    // try parse the string to a JSON object
    try {
        jObj = new JSONObject(json);
    } catch (JSONException e) {
//      Log.e("JSON Parser", "Error parsing data " + e.toString());
    }

    // return JSON String
    return jObj;
}

Then to use this in fragment by async i tried -

    class getTopicId extends AsyncTask<String, String, JSONObject> {
    private ProgressDialog pDialog;
    @Override
      protected void onPreExecute() {
          super.onPreExecute();
          pDialog = new ProgressDialog(getActivity());
          pDialog.setMessage("Getting Topic of the Day ...");
          pDialog.setIndeterminate(false);
          pDialog.setCancelable(true);
          pDialog.show();
    }
    @Override
      protected JSONObject doInBackground(String... args) {
      JSONParser jParser = new JSONParser();
      // Getting JSON from URL
      JSONObject json = jParser.getJSONFromUrl("http://medicalguru.in/android/tod.php");
      return json;
    }
     @Override
       protected void onPostExecute(JSONObject json) {
       pDialog.dismiss();
       try {
           topic_id = json.getInt("value");    
      } 
       catch (JSONException e) {
        e.printStackTrace();
      }
       finally {
           Toast.makeText(getActivity(), "topic id -"+topic_id, Toast.LENGTH_LONG).show();
       }
     }
}

but the app is crashing when i execute this async. my logcat shows -

03-06 15:07:03.123: E/AndroidRuntime(2041): FATAL EXCEPTION: main
03-06 15:07:03.123: E/AndroidRuntime(2041): java.lang.NullPointerException
03-06 15:07:03.123: E/AndroidRuntime(2041):     at in.medicalguru.DailyTestFragment$getTopicId.onPostExecute(DailyTestFragment.java:786)
03-06 15:07:03.123: E/AndroidRuntime(2041):     at in.medicalguru.DailyTestFragment$getTopicId.onPostExecute(DailyTestFragment.java:1)
03-06 15:07:03.123: E/AndroidRuntime(2041):     at android.os.AsyncTask.finish(AsyncTask.java:631)
03-06 15:07:03.123: E/AndroidRuntime(2041):     at android.os.AsyncTask.access$600(AsyncTask.java:177)
03-06 15:07:03.123: E/AndroidRuntime(2041):     at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:644)
03-06 15:07:03.123: E/AndroidRuntime(2041):     at android.os.Handler.dispatchMessage(Handler.java:99)
03-06 15:07:03.123: E/AndroidRuntime(2041):     at android.os.Looper.loop(Looper.java:137)
03-06 15:07:03.123: E/AndroidRuntime(2041):     at android.app.ActivityThread.main(ActivityThread.java:5103)
03-06 15:07:03.123: E/AndroidRuntime(2041):     at java.lang.reflect.Method.invokeNative(Native Method)
03-06 15:07:03.123: E/AndroidRuntime(2041):     at java.lang.reflect.Method.invoke(Method.java:525)
03-06 15:07:03.123: E/AndroidRuntime(2041):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:737)
03-06 15:07:03.123: E/AndroidRuntime(2041):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
03-06 15:07:03.123: E/AndroidRuntime(2041):     at dalvik.system.NativeStart.main(Native Method)

The link mentioned above in the code outputs as -

{"value":1}

when opened normally, but when I run in async it says err related to nullpointer? Couldn't figure, where I am making mistake ?


Edit 1 : *tod.php* code (Since Matthew has pointed something which I dont understand, so it may be helpful)

<?php
$today = date("Ymd");
switch($today){
case 20140304 :
$tod["value"] = 24;
break;
case 20140305 :
$tod["value"] = 25;
break;
case 20140306 :
$tod["value"] = 1;
break;
default:
$tod["value"] = 1;
break;
}
echo json_encode($tod);
?>

Edit 2 : *Found the problem (fully for me) but Partly in Real* - A special thanks to Matthew for his idea, to uncomment the error logs of function getJSONFromUrl(String url). I got a new error line in logcat -

Error parsing data org.json.JSONException: Value  of type java.lang.String cannot be converted to JSONObject

After little bit of search on google and stacksoverflow I found one suggestion to change chrSet to UTF-8 instead of iso-8859-1. and it worked for my requested url in both situations (with or without WWW - suggestion to test, by nikis). But this answer is partial real, because, now 2 unanswered questions developed - 1. Why did chrSet change worked? In future, what chrSet to be used, to avoid this problem, and what's the use of other one chrSet? 2. Matthew has replicated my Json to his server mwesly.com/test/ . Trial on his server, logcat shows following error in all cases (with or without WWW, with or without using index.php in the end) -

Error parsing data org.json.JSONException: Value <!DOCTYPE of type java.lang.String cannot be converted to JSONObject

Now, why is this error appearing on his server? What should be done to prevent/treat this error. If I need to ask these updated questions separately, please let me know.

Dr. Atul Tiwari
  • 1,085
  • 5
  • 22
  • 46

3 Answers3

1

It looks like json is null on following line, which is giving you the NullPointerException.

topic_id = json.getInt("value");

I think this is because your parser is having issues parse the json. I wrote a quick python script and tried to parse the page and it failed as well. For some reason, the response I get from http://medicalguru.in/android/tod.php is:

\xef\xbb\xbf{"value":1}

I am not sure why the \xef\xbb\xbf bytes are there, but they are likely causing the problem.

edit: a quick google search says it is the UTF-8 BOM. If you remove it your android code should work.

edit2: I put an example json on http://mwesly.com/test. Try hitting that json to see if your android code is correct. If it works, it means there is a problem with your endpoint, not your android code.

edit3: example of using loopj:

AsyncHttpClient client = new AsyncHttpClient();
client.get("http://mwesly.com/test", null, new JsonHttpResponseHandler() {
    @Override
    public void onSuccess(JSONObject json) {
        // do something with the json
        int value = json.getInt("value");
    }
});

I'm going to head to bed, if you still haven't solved this problem when I wake up, I'll give it another look. Good luck and happy coding!

Matthew Wesly
  • 1,238
  • 1
  • 13
  • 14
  • Hi, I tried with your link.. but error in logcat is same :( – Dr. Atul Tiwari Mar 06 '14 at 11:18
  • Well then the good news is that you know the error is in your android code. I think it is probably in your `getJSONFromUrl` method. It is returning null, which means that it is having a problem loading the page. I would recommend uncommenting the error logs and trying to figure out where it is failing. That said, I generally use the loopj library for async http requests. http://loopj.com/android-async-http/ It is very nice and I have added an example of using it in my answer. – Matthew Wesly Mar 06 '14 at 11:27
  • I will try your new edit, and get back to you.. meanwhile I have edited my original question for you, so that you can have a look at php code too. you talked about UTF-8 BOM. after your mention, I read about it. But can you please tell me how to avoid/remove it. I use Notepad++ for php and don't know python so how can i know if my output is changed than expected. gn. – Dr. Atul Tiwari Mar 06 '14 at 11:49
  • please read my edit 2. Strange that, after changing chrSet, code is working on my-url while it's showing error in your json. Why is it so? – Dr. Atul Tiwari Mar 06 '14 at 20:07
0

Try to use the following getJSONFromUrl method:

public JSONObject getJSONFromUrl(String url) {

    // Making HTTP request
    try {
        // defaultHttpClient
        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpPost httpPost = new HttpPost(url);
        HttpResponse httpResponse = httpClient.execute(httpPost);
        return new JSONObject(EntityUtils.toString(httpResponse.getEntity()));
    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    } catch (ClientProtocolException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return null;
}
nikis
  • 11,166
  • 2
  • 35
  • 45
  • Sorry I didnt get you properly. Do you mean I should the line mentioned by you in JSONObject doInBackground? If yes, I tried, but says -"httpResponse cannot be resolved"... I dont know if it makes a difference I am using async in fragment. – Dr. Atul Tiwari Mar 06 '14 at 11:23
  • if i use your getJSONFromUrl I get this error (after pressing ctrl+shift+o) - The method JSONObject(String) is undefined for the type JSONParser. And if i correct it by creating method "private JSONObject JSONObject(String string)" I dont know how to use it? It seems operating on human patients is easier than android coding :( – Dr. Atul Tiwari Mar 06 '14 at 11:58
  • @Dr.AtulTiwari I've made a small typo (forgot `new`) – nikis Mar 06 '14 at 12:02
  • was unable to use your code as such, getting err - "unhandled" exception type jsonexception. so tried using try catch for the return... but my bad luck, stil same err. java.lang.NullPointerException at in.medicalguru.DailyTestFragment$getTopicId.onPostExecute(DailyTestFragment.java:786) at in.medicalguru.DailyTestFragment$getTopicId.onPostExecute(DailyTestFragment.java:1) at android.os.AsyncTask.access$600(AsyncTask.java:177) at android.os.AsyncTask.finish(AsyncTask.java:631) at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:644) at android.os.Looper.loop(Looper.java:137) – Dr. Atul Tiwari Mar 06 '14 at 12:14
  • do you have your own `JsonParser` class or it's built-in? – nikis Mar 06 '14 at 12:23
  • i have a separate class named JASONParser, but i dont think it overrides any built-in functions. i have pasted it's full source code on pastebin [link](http://pastebin.com/VfpFHJyz). It was the original source, then i replaced "getjsonfromurl" with the one you provided. Sorry for the confusion – Dr. Atul Tiwari Mar 06 '14 at 12:38
  • one more attempt: try to replace `jParser.getJSONFromUrl("http://medicalguru.in/android/tod.php");` with `jParser.getJSONFromUrl("http://www.medicalguru.in/android/tod.php");` – nikis Mar 06 '14 at 12:51
  • i am really very sorry. you are continuously trying to help me. but emergency call at hospital. will try for sure once i get back and reply. thx. – Dr. Atul Tiwari Mar 06 '14 at 13:24
  • I tried with both, with or without www. But i found problem a bit... please read edit 2. – Dr. Atul Tiwari Mar 06 '14 at 20:04
0
private JSONObject jObj = null;
private JSONArray JArr = null;

and then after;

        URL url = null;
        try {
            url = new URL("your url is here");
        } catch (MalformedURLException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

        JSONParser jParser = new JSONParser();
        String json_value = jParser.getJSONFromUrl(url);
    try {
              JArr = new JSONArray(json_value);
            } catch (JSONException e) {
                e.printStackTrace();
            }
            jObj = null;

            for (int i = 0; i < JArr.length(); i++) {
                try {
                    jObj = JArr.getJSONObject(i);
                    topic_id = jObj.getInt("value");
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
  • I tried to use your code, but will you please have a look at it again. the line "String json_value = jParser.getJSONFromUrl("your url");" is not a String. and also, where is 'json' defined used in line - "JArr = new JSONArray(json);" ? Thanks. – Dr. Atul Tiwari Mar 06 '14 at 12:02
  • tried with your new answer, getting error "The method getJSONFromUrl(String) in the type JSONParser is not applicable for the arguments (URL)", if i try to correct this.. it requires to change the type of url in class "JSONObject getJSONFromUrl(String url)", which in turn need another change in the class.. – Dr. Atul Tiwari Mar 06 '14 at 12:23
  • you must write your url above instead of "your url is here". jParser.getJSONFromUrl(url); don't edit this part. – Muhammed Tanrıkulu Mar 06 '14 at 12:28
  • YES sir, i did write my url at mentioned space. it was the err mentioned above, i was getting on line "String json_value = jParser.getJSONFromUrl(url);" sorry for any confusion caused. – Dr. Atul Tiwari Mar 06 '14 at 12:34