1

In my application, I have a food activity in which the user enters his/her food, and the app requests the food, by the name entered by the user, from a MYSQL database. In the case that the entered food not exist, the string returned by the database should be null.

Currently, when this happens, an exception to occurs since the null value cannot be parsed to a JSON array. My question is: "Is there a way to prevent my app from force closing? Can I handle the exception and display a toast notifying the user that the requested food was not found?" I would like to prevent the app from crashing, and, rather, fail gracefully.

Please help me.

I've shown the relevant code in my application..

private class LoadData extends AsyncTask<Void, Void, String> 
    { 
private  JSONArray jArray;
private  String result = null;
private  InputStream is = null;
private String entered_food_name=choice.getText().toString().trim();
protected void onPreExecute() 
{
}

@Override
protected String doInBackground(Void... params) 
{
   try {
    ArrayList<NameValuePair> nameValuePairs = new            ArrayList<NameValuePair>();
    HttpClient httpclient = new DefaultHttpClient(); 
    HttpPost httppost = new HttpPost("http://10.0.2.2/food.php");
    nameValuePairs.add(new BasicNameValuePair("Name",entered_food_name));
    httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs,"UTF-8"));
    HttpResponse response = httpclient.execute(httppost);

    HttpEntity entity = response.getEntity();
     is = entity.getContent();

        //convert response to string

BufferedReader reader = new BufferedReader(new InputStreamReader(is,"utf-8"),8);
        StringBuilder sb = new StringBuilder();
        String line = null;
        while ((line = reader.readLine()) != null) {
            sb.append(line);
        }

        is.close();


        result =sb.toString();
        result = result.replace('\"', '\'').trim();

    }
    catch(Exception e){
        Log.e("log_tag", " connection" + e.toString());                     
    }


    return result;  

}

@Override
protected void onPostExecute(String result) 
{  
    try{

        String foodName="";
        int Description=0;

        jArray = new JSONArray(result); // here if the result is null an exeption will occur
        JSONObject json_data = null;

        for (int i = 0; i < jArray.length(); i++) {
            json_data = jArray.getJSONObject(i);
            foodName=json_data.getString("Name");
            .
            .
            .
            .
            .
        } 
        catch(JSONException e){ 
            **// what i can do here to prevent my app from crash and 
            //  make toast " the entered food isnot available " ????**
            Log.e("log_tag", "parssing  error " + e.toString()); 
        }   
    }
}
dcow
  • 7,765
  • 3
  • 45
  • 65
user
  • 621
  • 15
  • 46
  • did you try putting the makeToast in the catch that you have? If so what happened? – FoamyGuy May 14 '12 at 16:45
  • I have tried to put the toast in the catch , but the app still crash when the result returned as null – user May 14 '12 at 16:51
  • Did you check the logcat, are you certain that the null value is ncausing a JSONException and not a NullPointerException? – FoamyGuy May 14 '12 at 16:53
  • yes , this is my exception in the log : log_tag(935): parssingorg.json.JSONException: Value
    – user May 14 '12 at 17:36

2 Answers2

3

This will fix your code:

jArray = (result == null) ? new JSONArray() : new JSONArray(result);

Now that you have an empty JSONArray, you will be able to test for null JSONObjects later in your program. Many of the JSON methods return a JSONObject if one is found, of null if none exists.

You might also want to initialize your JSONObject with the no-argument JSON constructor, rather than simply setting it to null. It will avoid problems when passing it to other JSON methods (such as using it in a constructor to a JSONArray():

JSONObject json_data = new JSONObject();

Finally, if you're still getting JSONExceptions, it's because you're not actually passing a valid JSON string to the constructor. You can print out the value of result to the log:

Log.d("JSON Data", result);

You may see some SQL error text or if you retrieve from a web server, then an HTTP error code (404 is common if you don't have your url correct).

If your result does look like JSON, then you can verify whether it's actually valid JSON or not using the JSONLint validator. It will help you catch any errors you may have, especially if you're formatting the JSON yourself.

dcow
  • 7,765
  • 3
  • 45
  • 65
  • This sounds a lot nicer than resorting exceptions to handle everyday end-user mistakes. – Chris Stratton May 14 '12 at 16:55
  • thanks , in this case i check the JSON object if its null , then i make toast " the entered food isnt exist " ? and if the result returned as null parsing exception will not occur ? is that true or i miss understand you ? please help me – user May 14 '12 at 17:11
  • Basically, make sure it's not null before you call a parser on it. – Chris Stratton May 14 '12 at 17:17
  • thanks , i tried it and tested my app by entering not stored food name , and the exception still occur ? can you explain more how i can do that since iam new in android ?please help me – user May 14 '12 at 17:17
  • The exception occurs when you pass a `null` value to the constructor. It is different from the *no-argument* constructor that creates a null object. The exception that is occurring is a Java.lang.NullPointerException, not a JSON.org.JSONException. This is a runtime exception and one that you can't handle with your try/catch block (especial since the assignment doesn't even occur in a try/catch block). You are correct that, now, you can check whether the result returned was null, and show your toast without the runtime exception occurring. – dcow May 14 '12 at 17:19
  • @user88 Also, does the data come in as a JSONArray? Or does it come as a simple JSONObject? If your crash is still occurring, that's the only other reason I can think of -- but the JSONException should cover that.. You might also post your log cat (= – dcow May 14 '12 at 17:25
  • my data returned from my MYSQL server as string then i parse it to JSON array , i added if(result !=null) ---> in this case i will parse it , else make toast and i debug my app and it isnt enter to the if statement for check , and when the result null it passes to catch and this is my log exeption : log_tag(935): parssingorg.json.JSONException: Value
    – user May 14 '12 at 17:33
  • @user88 Yeah, you're not passing valid JSON into the constructor (`result` is not null, but it's not valid JSON either). You're passing HTML. If you print `result` to the log you will see that is the case. Your code is behaving as expected, you're just not getting the data you expected. – dcow May 14 '12 at 18:03
  • yes you are right , the php file return it in this format , how i can check it in this case ? help me – user May 14 '12 at 19:48
  • @user88 Perhaps you are taking on something a bit too advanced? I suggest tackling something simplier at first because I don't think anyone has the time to hold your hand the whole way. Once you learn what a *web request* is, how *http* works, and what your *php* is actually returning, you will be able to handle all the cases necessary. I don't mean to discourage. I would just like to simply point out that we're glad to help with tricky topics, but we're not here to write your programs for you. – dcow May 15 '12 at 02:36
0

Are you looking to capture the Exception and log it (remotely) to aid in crash reporting and debugging? I've used this package to remotely capture Exceptions and it works pretty good:

http://code.google.com/p/android-remote-stacktrace/

Cody Caughlan
  • 32,456
  • 5
  • 63
  • 68
  • Also, Crittercism works wonderfully for remote crash metrics and session logging. Flurry can be setup to log crashes, but it works out of the box with Crittercism. And, they're both free! -- Although Flurry uses Oracle's nasty .do web framework.. – dcow May 14 '12 at 16:52
  • In this way the app doesnt crash even if an exception occur ? – user May 14 '12 at 17:00
  • because I am really want to handle the exception in my app directly when its occur by informing the user that his entered food didnt exist , its possible to do that ? i hope to help me since iam new in android – user May 14 '12 at 17:01