com.ravi.apps.android.newsbytes.MainActivity.java Source code

Java tutorial

Introduction

Here is the source code for com.ravi.apps.android.newsbytes.MainActivity.java

Source

/*
 * Copyright (C) 2015 Ravi
 *
 * 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.ravi.apps.android.newsbytes;

import android.app.DialogFragment;
import android.app.FragmentManager;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.view.ViewCompat;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.transition.TransitionInflater;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.AdView;
import com.ravi.apps.android.newsbytes.service.DeleteFavoriteService;
import com.ravi.apps.android.newsbytes.sync.NewsSyncAdapter;

public class MainActivity extends AppCompatActivity
        implements HeadlinesFragment.OnHeadlineSelectedListener, SharedPreferences.OnSharedPreferenceChangeListener,
        DeleteFavoritesDialogFragment.DeleteFavoritesDialogListener {

    // Tag for logging messages.
    public static final String LOG_TAG = MainActivity.class.getSimpleName();

    public static final String DELETE_FAV_DIALOG_TAG = "delete_fav_dialog_tag";

    // Keys for the shared element transition.
    public static final String IMAGE_XPOS = "image_xpos";
    public static final String IMAGE_YPOS = "image_ypos";
    public static final String IMAGE = "image";
    public static final String TEXT_XPOS = "text_xpos";
    public static final String TEXT_YPOS = "text_ypos";
    public static final String TEXT = "text";

    // Flag indicating whether widget list item was clicked.
    public static boolean isWidgetItemClicked = false;

    // Position of the widget list item that was clicked.
    public static int widgetItemClickedPosition = ListView.INVALID_POSITION;

    // Holds whether the main activity layout contains two panes.
    private boolean mIsTwoPaneMode;

    // Toolbar.
    private Toolbar mToolbar;

    // Key to save preference changed status flag.
    private static final String PREFERENCE_CHANGED_KEY = "preference_changed_key";

    // Flag indicating whether news category preference changed.
    private boolean mHasPreferenceChanged = false;

    // Ad view displaying banner ad.
    private AdView mAdView;

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

        // Start analytics tracking.
        ((NewsApplication) getApplication()).startTracking();

        // Set default values only the first time.
        PreferenceManager.setDefaultValues(this, R.xml.preferences, false);

        // Register to receive events upon any changes to the shared preferences.
        PreferenceManager.getDefaultSharedPreferences(this).registerOnSharedPreferenceChangeListener(this);

        // Get the toolbar and set it as the action bar.
        mToolbar = (Toolbar) findViewById(R.id.tool_bar);
        setSupportActionBar(mToolbar);

        // Get the banner ad view.
        mAdView = (AdView) findViewById(R.id.adview);

        // Create an ad request and load it into the ad view.
        AdRequest adRequest = new AdRequest.Builder().build();
        mAdView.loadAd(adRequest);

        // Check if the layout has two panes and set the flag accordingly.
        if (findViewById(R.id.news_details_container) != null) {
            mIsTwoPaneMode = true;
        } else {
            mIsTwoPaneMode = false;
        }

        // Check if it was a configuration change.
        if (savedInstanceState == null) {
            // Check if the widget list item was clicked.
            Intent intent = getIntent();
            if (intent != null && intent.getAction() != null
                    && intent.getAction().equals(getString(R.string.action_item_clicked))) {
                Log.d(LOG_TAG, getString(R.string.log_on_create_widget_item_clicked));

                // Set the widget list item clicked flag.
                isWidgetItemClicked = true;

                // Extract the match id and position from the intent.
                widgetItemClickedPosition = intent.getIntExtra(getString(R.string.extra_widget_item_position),
                        ListView.INVALID_POSITION);

                Log.d(LOG_TAG, getString(R.string.log_on_create_widget_item_position)
                        + ((Integer) widgetItemClickedPosition).toString());
            }
        } else {
            // Check if it's in two pane mode and the preference changed status was saved.
            if (mIsTwoPaneMode && savedInstanceState.containsKey(PREFERENCE_CHANGED_KEY)) {
                // Extract preference changed status.
                mHasPreferenceChanged = savedInstanceState.getBoolean(PREFERENCE_CHANGED_KEY);
            }
        }

        // Initialize the sync adapter.
        NewsSyncAdapter.initializeSyncAdapter(this);
    }

    @Override
    protected void onDestroy() {
        // Unregister from receiving events upon any changes to the shared preferences.
        PreferenceManager.getDefaultSharedPreferences(this).unregisterOnSharedPreferenceChangeListener(this);

        super.onDestroy();
    }

    @Override
    protected void onResume() {
        super.onResume();

        // Check if it's in two pane mode and preference has been changed.
        // If so, find and remove the details fragment.
        if (mIsTwoPaneMode && mHasPreferenceChanged) {
            // Get the fragment manager.
            FragmentManager fragmentManager = getFragmentManager();

            // Get the details fragment.
            DetailsFragment detailsFragment = (DetailsFragment) fragmentManager
                    .findFragmentByTag(DetailsFragment.DETAILS_FRAGMENT_TAG);

            // Remove the details fragment.
            if (detailsFragment != null) {
                fragmentManager.beginTransaction().remove(detailsFragment).commit();
            }

            // Reset the preference changed flag.
            mHasPreferenceChanged = false;
        }
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        // if it's in two pane mode, then save the preference changed flag.
        if (mIsTwoPaneMode) {
            outState.putBoolean(PREFERENCE_CHANGED_KEY, mHasPreferenceChanged);
        }
    }

    @Override
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
        // If the news notifications preference was changed, do nothing.
        if (key.equals(getString(R.string.pref_notifications_key))) {
            return;
        }

        // Set the news category preference changed flag if it's in two pane mode.
        if (mIsTwoPaneMode) {
            mHasPreferenceChanged = true;
        }

        // Check the current news category preference.
        if (!Utility.getNewsCategoryPreference(this, key)
                .equals(getString(R.string.pref_news_category_favorites))) {
            // Current preference is not favorites, trigger an immediate sync.
            NewsSyncAdapter.syncImmediately(this);
        }

        // Preference has changed, inform widget to refresh it's data.
        Utility.sendDataUpdatedBroadcast(this);
    }

    @Override
    public void onHeadlineSelected(News news, ImageView thumbnailView, String thumbnailTransition,
            TextView headlineView, String headlineTransition) {
        // Check if it's in two pane mode.
        if (mIsTwoPaneMode) {
            // Package the parcelable news data into the arguments bundle.
            Bundle arguments = new Bundle();
            arguments.putParcelable(DetailsFragment.NEWS_DETAILS, news);

            // Create the details fragment object.
            DetailsFragment detailsFragment = new DetailsFragment();

            // Shared element transition - check if device is running on lollipop or above
            // and if ALL of the required parameters for the shared element transition are available.
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && thumbnailView != null
                    && thumbnailTransition != null && headlineView != null && headlineTransition != null) {
                // Set the shared element transition.
                detailsFragment.setSharedElementEnterTransition(
                        TransitionInflater.from(this).inflateTransition(R.transition.change_image_transform));
                detailsFragment.setEnterTransition(
                        TransitionInflater.from(this).inflateTransition(android.R.transition.fade));

                // Add the transition names into the bundle.
                arguments.putString(HeadlinesAdapter.THUMBNAIL_TRANSITION_NAME, thumbnailTransition);
                arguments.putString(HeadlinesAdapter.HEADLINE_TRANSITION_NAME, headlineTransition);

                // Set arguments containing news details.
                detailsFragment.setArguments(arguments);

                // Set the transition names.
                ViewCompat.setTransitionName(thumbnailView, thumbnailTransition);
                ViewCompat.setTransitionName(headlineView, headlineTransition);

                // Add the fragment onto the container.
                getFragmentManager().beginTransaction()
                        .replace(R.id.news_details_container, detailsFragment, DetailsFragment.DETAILS_FRAGMENT_TAG)
                        .addSharedElement(thumbnailView, thumbnailTransition)
                        .addSharedElement(headlineView, headlineTransition).commit();
            } else { // For pre-lollipop devices.
                // Set arguments containing news details.
                detailsFragment.setArguments(arguments);

                // Add the fragment onto the container.
                getFragmentManager().beginTransaction()
                        .setCustomAnimations(android.R.animator.fade_in, android.R.animator.fade_out,
                                android.R.animator.fade_in, android.R.animator.fade_out)
                        .replace(R.id.news_details_container, detailsFragment, DetailsFragment.DETAILS_FRAGMENT_TAG)
                        .commit();
            }
        } else {
            // Create intent to launch details activity.
            Intent intent = new Intent(this, DetailsActivity.class);

            // Add news details into extra.
            intent.putExtra(DetailsFragment.NEWS_DETAILS, news);

            // Shared element transition - check if device is running on lollipop or above
            // and if ALL of the required parameters for the shared element transition are available.
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && thumbnailView != null
                    && thumbnailTransition != null && headlineView != null && headlineTransition != null) {
                // Add the transition names into the intent extra.
                intent.putExtra(HeadlinesAdapter.THUMBNAIL_TRANSITION_NAME, thumbnailTransition);
                intent.putExtra(HeadlinesAdapter.HEADLINE_TRANSITION_NAME, headlineTransition);

                // Add the essential attributes of the shared element views into the intent extra.
                addThumbnailDetailsToIntent(thumbnailView, intent);
                addHeadlineDetailsToIntent(headlineView, intent);
            }

            // Start details activity.
            startActivity(intent);
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the options menu.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Get id of the menu item selected.
        int id = item.getItemId();

        // Check which menu item was clicked.
        if (id == R.id.action_delete_favorites) {
            // Instantiate and show the delete favorites dialog fragment.
            new DeleteFavoritesDialogFragment().show(getFragmentManager(), DELETE_FAV_DIALOG_TAG);

            return true;
        } else if (id == R.id.action_settings) {
            // Start the settings activity.
            Intent intent = new Intent(this, SettingsActivity.class);
            startActivity(intent);

            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onDialogPositiveClick(DialogFragment dialog) {
        // Start the intent service to delete all favorite news stories.
        Intent intent = new Intent(this, DeleteFavoriteService.class);
        startService(intent);
    }

    @Override
    public void onDialogNegativeClick(DialogFragment dialog) {

    }

    /**
     * Adds the thumbnail details into the intent extras.
     */
    private void addThumbnailDetailsToIntent(ImageView imageView, Intent intent) {
        // Get the thumbnail position.
        int[] loc = new int[2];
        imageView.getLocationOnScreen(loc);
        float xPos = loc[0];
        float yPos = loc[1];

        // Get the thumbnail image as a byte array.
        byte[] imageByteArray = Utility.convertToByteArray(imageView);
        if (imageByteArray == null) {
            imageByteArray = new byte[0];
        }

        // Add details into intent extras.
        intent.putExtra(IMAGE_XPOS, xPos);
        intent.putExtra(IMAGE_YPOS, yPos);
        intent.putExtra(IMAGE, imageByteArray);
    }

    /**
     * Adds the headline details into the intent extras.
     */
    private void addHeadlineDetailsToIntent(TextView textView, Intent intent) {
        // Get the headline position.
        int[] location = new int[2];
        textView.getLocationOnScreen(location);
        float xPos = location[0];
        float yPos = location[1];

        // Get the text.
        String text = (String) textView.getText();

        // Add details into intent extras.
        intent.putExtra(TEXT_XPOS, xPos);
        intent.putExtra(TEXT_YPOS, yPos);
        intent.putExtra(TEXT, text);
    }
}