2

I got all my json parsing request to work, but now when I disable all the internet in my device, when I launch it it crashes and says "app has stopped working".

Where in my code should I add an exception that says "you don't have internet connection to use this app" and a button that says "try again" so people press the button and the app reloads again?

This is my main activity:

import java.util.ArrayList;
import java.util.HashMap;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.net.ConnectivityManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.widget.ListView;

public class MainActivity extends Activity {
    // Declare Variables
    JSONObject jsonobject;
    JSONArray jsonarray;
    ListView listview;
    ListViewAdapter adapter;
    ProgressDialog mProgressDialog;
    ArrayList<HashMap<String, String>> arraylist;
    static String RANK = "rank";
    static String COUNTRY = "country";
    static String POPULATION = "population";
    static String FLAG = "flag";

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // Get the view from listview_main.xml
        setContentView(R.layout.listview_main);
        // Execute DownloadJSON AsyncTask
        new DownloadJSON().execute();
    }

    


    // DownloadJSON AsyncTask
    private class DownloadJSON extends AsyncTask<Void, Void, Void> {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            // Create a progressdialog
            mProgressDialog = new ProgressDialog(MainActivity.this);
            // Set progressdialog title
            mProgressDialog.setTitle("Actualizando Información");
            // Set progressdialog message
            mProgressDialog.setMessage("Cargando...");
            mProgressDialog.setIndeterminate(false);
            // Show progressdialog
            mProgressDialog.show();
        }

        @Override
        protected Void doInBackground(Void... params) {
            // Create an array
            arraylist = new ArrayList<HashMap<String, String>>();
            // Retrieve JSON Objects from the given URL address
            jsonobject = JSONfunctions
                    .getJSONfromURL("http://www.androidbegin.com/tutorial/jsonparsetutorial.txt");

            try {
                // Locate the array name in JSON
                jsonarray = jsonobject.getJSONArray("worldpopulation");



                for (int i = 0; i < jsonarray.length(); i++) {

                    HashMap<String, String> map = new HashMap<String, String>();
                    jsonobject = jsonarray.getJSONObject(i);
                    // Retrive JSON Objects
                    map.put("rank", jsonobject.getString("rank"));
                    map.put("country", jsonobject.getString("country"));
                    map.put("population", jsonobject.getString("population"));
                    map.put("flag", jsonobject.getString("flag"));
                    // Set the JSON Objects into the array
                    arraylist.add(map);
                }

            } catch (JSONException e) {
                Log.e("Error", e.getMessage());
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onPostExecute(Void args) {
            // Locate the listview in listview_main.xml
            listview = (ListView) findViewById(R.id.listview);
            // Pass the results into ListViewAdapter.java
            adapter = new ListViewAdapter(MainActivity.this, arraylist);
            // Set the adapter to the ListView
            listview.setAdapter(adapter);
            // Close the progressdialog
            mProgressDialog.dismiss();
        }
    }
}

And my JsonFunctions:

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONException;
import org.json.JSONObject;

import android.util.Log;

public class JSONfunctions {

    public static JSONObject getJSONfromURL(String url) {
        InputStream is = null;
        String result = "";
        JSONObject jArray = null;

        // Download JSON data from URL
        try {
            HttpClient httpclient = new DefaultHttpClient();
            HttpPost httppost = new HttpPost(url);
            HttpResponse response = httpclient.execute(httppost);
            HttpEntity entity = response.getEntity();
            is = entity.getContent();

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

        // Convert response to string
        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();
            result = sb.toString();
        } catch (Exception e) {
            Log.e("log_tag", "Error converting result " + e.toString());
        }

        try {

            jArray = new JSONObject(result);
        } catch (JSONException e) {
            Log.e("log_tag", "Error parsing data " + e.toString());
        }

        return jArray;
    }
}
mkrieger1
  • 19,194
  • 5
  • 54
  • 65
gioton
  • 33
  • 1
  • 8

3 Answers3

3

Try checking if there is internet before you execute your DownloadJson method in OnCreate

Read here on how to check if you have an internet connection.

And here is a snippet creating a Snackbar to tell the user that there is no connection.

First add a string in strings.xml

<string name="try_again">Reconnect</string>

And add create a snackbar if there is no internet connection, your code might look like this

boolean internet_connection(){
    //Check if connected to internet, output accordingly
    ConnectivityManager cm =
            (ConnectivityManager)this.getSystemService(Context.CONNECTIVITY_SERVICE);

    NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
    boolean isConnected = activeNetwork != null &&
            activeNetwork.isConnectedOrConnecting();
    return isConnected;
}
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // Get the view from listview_main.xml
    setContentView(R.layout.listview_main);
    if (internet_connection()){
        // Execute DownloadJSON AsyncTask
        new DownloadJSON().execute();
    }else{
        //create a snackbar telling the user there is no internet connection and issuing a chance to reconnect
        final Snackbar snackbar = Snackbar.make(findViewById(android.R.id.content), 
                                                  "No internet connection.", 
                                                    Snackbar.LENGTH_SHORT);
        snackbar.setActionTextColor(ContextCompat.getColor(getApplicationContext(),
                                      R.color.lime));
        snackbar.setAction(R.string.try_again, new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //recheck internet connection and call DownloadJson if there is internet
            }
        }).show();
    }

}

Hope this helps

Community
  • 1
  • 1
Ultar
  • 46
  • 3
1

The best and simplest solution for handle this issue is that use try catch block in your onPost execute() in async task. like this

    @Override
    protected void onPostExecute(String s) {
        try {
            super.onPostExecute(s);
            loading.dismiss();
        }catch (Exception ex){
            Toast.makeText(UserLogin.this, "Something is going wrong, please try again!", Toast.LENGTH_LONG).show();
        }
    }

simply this will prevent your app from crash.

0

Your app is crashing because you continue code execution even after an exception has been caught and your InputStream is null.

A quick fix would be to return null in all three catch blocks.

In onPostExecute(), check if the result is null, that would mean an error occurred in doInBackground().

However that wouldn't really let you know what kind of error occurred (was it a network error? was it a parsing error?)

My advice would be to use an HTTP library that could handle most of the work for you. Retrofit is a great option.

Benito Bertoli
  • 25,285
  • 12
  • 54
  • 61