com.oscarsalguero.popularmovies.MainActivity.java Source code

Java tutorial

Introduction

Here is the source code for com.oscarsalguero.popularmovies.MainActivity.java

Source

/***
 * Copyright (c) 2016 Oscar Salguero www.oscarsalguero.com
 * Licensed under the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License. You may obtain
 * a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.oscarsalguero.popularmovies;

import android.content.Context;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.Snackbar;
import android.support.v4.view.MenuItemCompat;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.AppCompatSpinner;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.SpinnerAdapter;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.oscarsalguero.popularmovies.adapter.MovieAdapter;
import com.oscarsalguero.popularmovies.bean.MoviesResponse;
import com.oscarsalguero.popularmovies.model.Movie;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

/**
 * The Main Popular Movies app activity shows a grid of movies that can be sorted by most popular or
 * top rated
 * Created by RacZo on 11/19/16.
 */
public class MainActivity extends AppCompatActivity implements SwipeRefreshLayout.OnRefreshListener {

    private static final String LOG_TAG = MainActivity.class.getName();

    private CoordinatorLayout mCoordinatorLayout;
    private SwipeRefreshLayout mSwipeRefreshLayout;
    private RecyclerView mRecyclerView;
    private MovieAdapter mAdapter;
    private GridLayoutManager mGridLayoutManager;
    private List<Movie> mMovies = new ArrayList<>();

    private static final String API_PATH_MOVIES_POPULAR = "popular";
    private static final String API_PATH_MOVIES_TOP_RATED = "top_rated";

    private String mSortOrder = API_PATH_MOVIES_POPULAR;

    private AdapterView.OnItemSelectedListener onItemSelectedListener = new AdapterView.OnItemSelectedListener() {

        @Override
        public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            Log.d(LOG_TAG, "Selected menu position: " + position);
            switch (position) {
            case 0:
                setSortPath(API_PATH_MOVIES_POPULAR);
                break;
            case 1:
                setSortPath(API_PATH_MOVIES_TOP_RATED);
                break;
            default:
                setSortPath(API_PATH_MOVIES_POPULAR);
                break;
            }
            getMovies();
        }

        @Override
        public void onNothingSelected(AdapterView<?> parent) {
            Log.d(LOG_TAG, "Nothing selected");
        }

    };

    @Override
    protected void onStart() {
        super.onStart();
        Log.d(LOG_TAG, "onStart");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(LOG_TAG, "onCreate");
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        mCoordinatorLayout = (CoordinatorLayout) findViewById(R.id.coordinator_layout);

        mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh_layout);
        mSwipeRefreshLayout.setOnRefreshListener(this);

        mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);

        mGridLayoutManager = new GridLayoutManager(this, 2);
        mGridLayoutManager.setOrientation(GridLayoutManager.VERTICAL);
        mRecyclerView.setHasFixedSize(true);
        mRecyclerView.setLayoutManager(mGridLayoutManager);

        mAdapter = new MovieAdapter(MainActivity.this, mMovies);
        mRecyclerView.setAdapter(mAdapter);

    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);
        Log.d(LOG_TAG, "onRestoreInstanceState");
    }

    @Override
    public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
        super.onSaveInstanceState(outState, outPersistentState);
        Log.d(LOG_TAG, "onSaveInstanceState");
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.d(LOG_TAG, "onPause");
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.d(LOG_TAG, "onResume");
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.d(LOG_TAG, "onStop");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(LOG_TAG, "onDestroy");
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        try {
            Context supportActionBarThemedContext = getSupportActionBar().getThemedContext();
            MenuItem menuItem = menu.findItem(R.id.action_sort);
            SpinnerAdapter spinnerAdapter = ArrayAdapter.createFromResource(supportActionBarThemedContext,
                    R.array.sort_options, R.layout.spinner_dropdown_item);
            AppCompatSpinner sortOptionsSpinner = new AppCompatSpinner(supportActionBarThemedContext);
            sortOptionsSpinner.setAdapter(spinnerAdapter);
            sortOptionsSpinner.setOnItemSelectedListener(onItemSelectedListener);
            MenuItemCompat.setActionView(menuItem, sortOptionsSpinner);
        } catch (Exception e) {
            Log.d(LOG_TAG, "An error has occurred creating sort order dropdown menu in action bar", e);
        }
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    /**
     * Gets the sort order
     *
     * @return a {@link String} with the sort order
     */
    public String getSortOrder() {
        return mSortOrder;
    }

    /**
     * Sets the sort order
     *
     * @param sortOrder a {@link String} with the sort order
     */
    public void setSortPath(String sortOrder) {
        this.mSortOrder = sortOrder;
    }

    /**
     * Gets the movies
     */
    private void getMovies() {
        new FetchMoviesTask().execute(getSortOrder());
    }

    @Override
    public void onRefresh() {
        Log.d(LOG_TAG, "Will refresh...");
        getMovies();
    }

    /**
     * Async task to fetch movie data from API
     */
    private class FetchMoviesTask extends AsyncTask<String, Void, String> {

        private final String LOG_TAG = FetchMoviesTask.class.getSimpleName();

        @Override
        protected String doInBackground(String... params) {

            if (params.length == 0) {
                return null;
            }

            String apiPathSortOrder = params[0];
            String apiKey = BuildConfig.THE_MOVIE_DB_API_KEY;
            if (TextUtils.isEmpty(apiKey)) {
                Snackbar.make(mCoordinatorLayout,
                        "API Key Not Defined. Please add it to your ~/.gradle/gradle.properties files as 'TheMovieDBAPIKey'.",
                        Snackbar.LENGTH_SHORT).show();
            }
            try {

                Uri.Builder uriBuilder = new Uri.Builder();
                uriBuilder.scheme(Constants.API_SCHEME).authority(Constants.API_BASE_URL)
                        .appendPath(Constants.API_PATH_VERSION).appendPath(Constants.API_PATH_MOVIE)
                        .appendPath(apiPathSortOrder).appendQueryParameter(Constants.API_PARAM_API_KEY, apiKey);

                Log.v(LOG_TAG, "Hitting URL: " + uriBuilder.build().toString());

                HttpURLConnection urlConnection = null;
                BufferedReader reader = null;
                String jsonResponseString = null;

                try {

                    URL url = new URL(uriBuilder.toString());
                    urlConnection = (HttpURLConnection) url.openConnection();
                    urlConnection.setRequestMethod(Constants.METHOD_GET);
                    urlConnection.connect();

                    InputStream inputStream = urlConnection.getInputStream();
                    StringBuffer buffer = new StringBuffer();
                    if (inputStream == null) {
                        return null;
                    }
                    reader = new BufferedReader(new InputStreamReader(inputStream));

                    String line;
                    while ((line = reader.readLine()) != null) {
                        buffer.append(line + "\n");
                    }

                    if (buffer.length() == 0) {
                        return null;
                    }
                    jsonResponseString = buffer.toString();

                } catch (IOException e) {
                    Log.e(LOG_TAG, "Error", e);
                    Snackbar.make(mCoordinatorLayout, e.getMessage(), Snackbar.LENGTH_SHORT).show();
                    return null;
                } catch (Exception e) {
                    Log.e(LOG_TAG, "Error", e);
                    Snackbar.make(mCoordinatorLayout, e.getMessage(), Snackbar.LENGTH_SHORT).show();
                    return null;
                } finally {
                    if (urlConnection != null) {
                        urlConnection.disconnect();
                    }
                    if (reader != null) {
                        try {
                            reader.close();
                        } catch (final IOException e) {
                            Log.e(LOG_TAG, "Error closing stream", e);
                        }
                    }
                }

                return jsonResponseString;

            } catch (Exception e) {
                return null;
            }
        }

        @Override
        protected void onPostExecute(String jsonResponseString) {

            Log.v(LOG_TAG, "JSON response: " + jsonResponseString);

            if (jsonResponseString != null) {
                try {
                    Gson gson = new GsonBuilder().create();
                    // Using third party library Gson to parse movies from JSON to a Java object
                    MoviesResponse moviesResponse = gson.fromJson(jsonResponseString, MoviesResponse.class);
                    if (moviesResponse.getResults() != null && moviesResponse.getResults().size() > 0) {
                        mMovies.clear();
                        mMovies.addAll(moviesResponse.getResults());
                        mAdapter.notifyDataSetChanged();
                    } else {
                        Log.e(LOG_TAG, "Movie results is null");
                        Snackbar.make(mCoordinatorLayout, getString(R.string.error_no_results),
                                Snackbar.LENGTH_SHORT).show();
                    }
                } catch (Exception e) {
                    String errorMessage = "Error parsing JSON response";
                    Log.e(LOG_TAG, errorMessage, e);
                    Snackbar.make(mCoordinatorLayout, errorMessage, Snackbar.LENGTH_SHORT).show();
                }
            } else {
                Snackbar.make(mCoordinatorLayout, getString(R.string.error_loading_movies), Snackbar.LENGTH_SHORT)
                        .show();
            }

            // Stopping swipe refresh layout
            if (mSwipeRefreshLayout.isRefreshing()) {
                mSwipeRefreshLayout.post(new Runnable() {
                    @Override
                    public void run() {
                        mSwipeRefreshLayout.setRefreshing(false);
                        Log.d(LOG_TAG, "Stopped refreshing");
                    }
                });
            }
        }

    }

}