0

I am loading JSON from server but the app crashes if the internet is not available. How to fix this problem? I have added try catch in most part. Unable to find the problem. lvMovies.setAdapter(adapter); gives error when internet is not available. Code works fine when internet is available

public class JSONTest extends AppCompatActivity implements SwipeRefreshLayout.OnRefreshListener {

    private ListView lvMovies;
    private ProgressDialog dialog;
    private SwipeRefreshLayout swipeRefreshLayout;

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

        swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipeMovieHits);
        swipeRefreshLayout.setOnRefreshListener(this);

        // Create default options which will be used for every
        //  displayImage(...) call if no options will be passed to this method
        DisplayImageOptions defaultOptions = new DisplayImageOptions.Builder()
                .cacheInMemory(true)
                .cacheOnDisk(true)
                .build();
        ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(getApplicationContext())
                .defaultDisplayImageOptions(defaultOptions)
                .build();
        ImageLoader.getInstance().init(config); // Do it on Application start

        lvMovies = (ListView) findViewById(R.id.lvMovies);
        dialog = new ProgressDialog(this);
        dialog.setIndeterminate(true);
        dialog.setCancelable(false);
        dialog.setMessage("Loading...");
        //new JSONTask().execute("http://ankushkapoor2016.16mb.com/ankush/myjson.txt");
        //new JSONTask().execute("http://jsonparsing.parseapp.com/jsonData/moviesDemoList.txt");
    }

    @Override
    public void onRefresh() { //SwipeRefreshLayout Refresh Listener
        try {
            new JSONTask().execute("http://jsonparsing.parseapp.com/jsonData/moviesData.txt");
        } catch (Exception e) {
            Toast.makeText(JSONTest.this, e.getMessage() + "\n\n" + e.getCause(), Toast.LENGTH_LONG).show();
        }
    }

    public class JSONTask extends AsyncTask<String, String, List<MovieModel>> {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            dialog.show();
        }

        @Override
        protected List<MovieModel> doInBackground(String... params) {

            HttpURLConnection connection = null;
            BufferedReader reader = null;

            try {
                URL url = new URL(params[0]);
                connection = (HttpURLConnection) url.openConnection();
                connection.connect();

                InputStream stream = connection.getInputStream();
                reader = new BufferedReader(new InputStreamReader(stream));

                StringBuffer buffer = new StringBuffer();
                String line = "";
                while ((line = reader.readLine()) != null) {
                    buffer.append(line);
                }

                String finalJson1 = buffer.toString();

                SharedPreferences sharedPreferences = getSharedPreferences("JSON_DATA", Context.MODE_PRIVATE);
                SharedPreferences.Editor editor = sharedPreferences.edit();
                editor.putString("json", finalJson1);
                editor.commit();

                String finalJson=sharedPreferences.getString("json","N/A");

                JSONObject parentObject = new JSONObject(finalJson);
                JSONArray parentArray = parentObject.getJSONArray("movies");

                List<MovieModel> movieModelList = new ArrayList<>();
                for (int i = 0; i < parentArray.length(); i++) {
                    JSONObject finalObject = parentArray.getJSONObject(i);
                    MovieModel movieModel = new MovieModel();
                    movieModel.setMovie(finalObject.getString("movie"));
                    movieModel.setYear(finalObject.getInt("year"));
                    movieModel.setRating((float) finalObject.getDouble("rating"));
                    movieModel.setDuration(finalObject.getString("duration"));
                    movieModel.setDirector(finalObject.getString("director"));
                    movieModel.setTagline(finalObject.getString("tagline"));
                    movieModel.setImage(finalObject.getString("image"));
                    movieModel.setStory(finalObject.getString("story"));

                    List<MovieModel.Cast> castList = new ArrayList<>();
                    for (int j = 0; j < finalObject.getJSONArray("cast").length(); j++) {
                        MovieModel.Cast cast = new MovieModel.Cast();
                        cast.setName(finalObject.getJSONArray("cast").getJSONObject(j).getString("name"));
                        castList.add(cast);
                    }
                    movieModel.setCastList(castList);
                    movieModelList.add(movieModel);
                }
                return movieModelList;
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (JSONException e) {
                e.printStackTrace();
            } finally {
                if (connection != null)
                    connection.disconnect();
                try {
                    if (reader != null)
                        reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            return null;
        }

        @Override
        protected void onPostExecute(List<MovieModel> s) {
            super.onPostExecute(s);
            dialog.dismiss();
            MovieAdapter adapter = new MovieAdapter(getApplicationContext(), R.layout.row, s);
            lvMovies.setAdapter(adapter);
            if (swipeRefreshLayout.isRefreshing()) {
                swipeRefreshLayout.setRefreshing(false);
            }
        }
    }

    public class MovieAdapter extends ArrayAdapter {

        private List<MovieModel> movieModelList;
        private int resource;
        private LayoutInflater inflater;

        public MovieAdapter(Context context, int resource, List<MovieModel> objects) {
            super(context, resource, objects);
            movieModelList = objects;
            this.resource = resource;
            inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            ViewHolder holder = null;
            if (convertView == null) {
                holder = new ViewHolder();
                convertView = inflater.inflate(resource, null);
                holder.ivMovieIcon = (ImageView) convertView.findViewById(R.id.ivIcon);
                holder.tvMovie = (TextView) convertView.findViewById(R.id.tvMovie);
                holder.tvTagline = (TextView) convertView.findViewById(R.id.tvTagline);
                holder.tvYear = (TextView) convertView.findViewById(R.id.tvYear);
                holder.tvDuration = (TextView) convertView.findViewById(R.id.tvDuration);
                holder.tvDirector = (TextView) convertView.findViewById(R.id.tvDirector);
                holder.rbMovieRating = (RatingBar) convertView.findViewById(R.id.rbMovie);
                holder.tvCast = (TextView) convertView.findViewById(R.id.tvCast);
                holder.tvStory = (TextView) convertView.findViewById(R.id.tvStory);
                convertView.setTag(holder);
            } else {
                holder = (ViewHolder) convertView.getTag();
            }

            final ProgressBar progressBar;
            progressBar = (ProgressBar) convertView.findViewById(R.id.progressBar);

            try {
                ImageLoader.getInstance().displayImage(movieModelList.get(position).getImage(), holder.ivMovieIcon, new ImageLoadingListener() {
                    @Override
                    public void onLoadingStarted(String imageUri, View view) {
                        progressBar.setVisibility(View.VISIBLE);
                    }

                    @Override
                    public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
                        progressBar.setVisibility(View.GONE);
                    }

                    @Override
                    public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
                        progressBar.setVisibility(View.GONE);
                    }

                    @Override
                    public void onLoadingCancelled(String imageUri, View view) {
                        progressBar.setVisibility(View.GONE);
                    }
                });
                holder.tvMovie.setText(movieModelList.get(position).getMovie());
                holder.tvTagline.setText(movieModelList.get(position).getTagline());
                holder.tvYear.setText("Year: " + movieModelList.get(position).getYear());
                holder.tvDuration.setText(movieModelList.get(position).getDuration());
                holder.tvDirector.setText(movieModelList.get(position).getDirector());

                holder.rbMovieRating.setRating(movieModelList.get(position).getRating() / 2);


                StringBuffer stringBuffer = new StringBuffer();
                for (MovieModel.Cast cast : movieModelList.get(position).getCastList()) {
                    stringBuffer.append(cast.getName() + ", ");
                }
                holder.tvCast.setText(stringBuffer);
                holder.tvStory.setText(movieModelList.get(position).getStory());
            } catch (Exception e) {
                Toast.makeText(getContext(), e.getMessage() + "\n" + e.getCause(), Toast.LENGTH_SHORT).show();
            }
            return convertView;
        }

        class ViewHolder {
            private ImageView ivMovieIcon;
            private TextView tvMovie;
            private TextView tvTagline;
            private TextView tvYear;
            private TextView tvDuration;
            private TextView tvDirector;
            private RatingBar rbMovieRating;
            private TextView tvCast;
            private TextView tvStory;
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_json, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        if (id == R.id.jsonRefresh) {
            try {
                new JSONTask().execute("http://jsonparsing.parseapp.com/jsonData/moviesData.txt");
                return true;
            } catch (Exception e) {
                Toast.makeText(JSONTest.this, e.getMessage() + "\n\n" + e.getCause(), Toast.LENGTH_LONG).show();
            }
        }
        return super.onOptionsItemSelected(item);
    }
}
akkk
  • 1,457
  • 4
  • 23
  • 41

2 Answers2

2

To prevent crash you should check is device have internet connection, to do that you can use:

private boolean isNetworkAvailable() {
    ConnectivityManager connectivityManager 
      = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
    return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}

You will also need to add to your AndroidManifest:

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

If you provide logcat message, then maybe I can tell you more about your problem.

OneCricketeer
  • 179,855
  • 19
  • 132
  • 245
cisekluke
  • 36
  • 3
1

Your problem is that you are returning a null arraylist when the internet exceptions are caught. So, the onPostExecute gets null, then the adapter gets null.

If you don't want a null value, pre-declare an empty list and always return it.

Then, the app won't crash, but you will see no data populate in the list, so you may want to do some additional validation that internet is available.

@Override
protected List<MovieModel> doInBackground(String... params) {

    List<MovieModel> movieModelList = new ArrayList<>();

    try {
        // TODO: Stuff

        return movieModelList;
    } catch ( ... ) {

    } finally {

    }

    return movieModelList;
}
OneCricketeer
  • 179,855
  • 19
  • 132
  • 245