de.incoherent.suseconferenceclient.activities.HomeActivity.java Source code

Java tutorial

Introduction

Here is the source code for de.incoherent.suseconferenceclient.activities.HomeActivity.java

Source

/*******************************************************************************
 * Copyright (c) 2012 Matt Barringer <matt@incoherent.de>.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Public License v2.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * 
 * Contributors:
 *     Matt Barringer <matt@incoherent.de> - initial API and implementation
 ******************************************************************************/
package de.incoherent.suseconferenceclient.activities;

import java.util.ArrayList;

import com.actionbarsherlock.app.ActionBar;
import com.actionbarsherlock.app.ActionBar.Tab;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;
import com.actionbarsherlock.view.MenuItem.OnActionExpandListener;
import com.actionbarsherlock.widget.SearchView;

import de.incoherent.suseconferenceclient.SUSEConferences;
import de.incoherent.suseconferenceclient.Config;
import de.incoherent.suseconferenceclient.adapters.TabAdapter;
import de.incoherent.suseconferenceclient.app.AboutDialog;
import de.incoherent.suseconferenceclient.app.Database;
import de.incoherent.suseconferenceclient.fragments.ChangeLogDialogFragment;
import de.incoherent.suseconferenceclient.fragments.FilterDialogFragment;
import de.incoherent.suseconferenceclient.fragments.MyScheduleFragment;
import de.incoherent.suseconferenceclient.fragments.NewsFeedFragment;
import de.incoherent.suseconferenceclient.fragments.ScheduleFragment;
import de.incoherent.suseconferenceclient.models.Conference;
import de.incoherent.suseconferenceclient.tasks.CacheConferenceTask;
import de.incoherent.suseconferenceclient.tasks.CacheConferenceTask.CacheConferenceTaskListener;
import de.incoherent.suseconferenceclient.tasks.CheckForUpdatesTask;
import de.incoherent.suseconferenceclient.tasks.CheckForUpdatesTask.CheckForUpdatesListener;
import de.incoherent.suseconferenceclient.tasks.GetConferencesTask;
import de.incoherent.suseconferenceclient.R;

import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager.NameNotFoundException;
import android.support.v4.app.FragmentManager;
import android.support.v4.view.ViewPager;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
import android.widget.Toast;

public class HomeActivity extends SherlockFragmentActivity implements GetConferencesTask.ConferenceListListener,
        CacheConferenceTaskListener, CheckForUpdatesListener, OnActionExpandListener {
    final int CONFERENCE_LIST_CODE = 1;
    final String MY_SCHEDULE_TAG = "myschedule";
    final String SCHEDULE_TAG = "schedule";
    final String NEWSFEED_TAG = "newsfeed";
    private ViewPager mPhonePager;
    private TabAdapter mTabsAdapter = null;
    private long mConferenceId = -1;
    private long mVenueId = -1;
    private ProgressDialog mDialog;
    private Conference mConference = null;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home);
        mDialog = null;

        if (savedInstanceState == null) {
            SharedPreferences settings = getSharedPreferences("SUSEConferences", 0);
            mConferenceId = settings.getLong("active_conference", -1);
        } else {
            mConferenceId = savedInstanceState.getLong("conferenceId");
            mVenueId = savedInstanceState.getLong("venueId");
        }

        if (mConferenceId == -1) {
            Log.d("SUSEConferences", "Conference ID is -1");
            if (!hasInternet()) {
                AlertDialog.Builder builder = new AlertDialog.Builder(this);
                builder.setMessage("Please enable internet access and try again.");
                builder.setCancelable(false);
                builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        HomeActivity.this.finish();
                    }
                });
                builder.show();
            } else {
                loadConferences();
            }
        } else {
            if (savedInstanceState != null)
                setView(false);
            else
                setView(true);
        }
    }

    @Override
    public void onSaveInstanceState(Bundle savedInstanceState) {
        super.onSaveInstanceState(savedInstanceState);
        Log.d("SUSEConferences", "saving InstanceState");
        savedInstanceState.putLong("conferenceId", mConferenceId);
        savedInstanceState.putLong("venueId", mVenueId);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        final MenuItem searchItem = menu.add(Menu.NONE, R.id.search, Menu.NONE, "Search");
        searchItem.setIcon(R.drawable.search);
        searchItem.setActionView(R.layout.collapsable_search);
        searchItem.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS | MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);
        searchItem.setOnActionExpandListener(this);

        final EditText searchEdit = (EditText) searchItem.getActionView();
        searchEdit.setOnEditorActionListener(new OnEditorActionListener() {
            @Override
            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                if (actionId == EditorInfo.IME_ACTION_SEARCH) {
                    String query = v.getText().toString();
                    if (query.length() > 0)
                        doSearch(query);
                    searchItem.collapseActionView();
                    return true;
                }
                return false;
            }
        });

        if (hasGoogleMaps()) {
            // With the phone layout, put the maps icon in the popup menu
            if (mPhonePager != null) {
                menu.add(Menu.CATEGORY_SYSTEM, R.id.mapsOptionMenuItem, 9, getString(R.string.mapsOptionMenuItem))
                        .setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);
            } else {
                menu.add(Menu.NONE, R.id.mapsOptionMenuItem, Menu.NONE, getString(R.string.mapsOptionMenuItem))
                        .setIcon(R.drawable.icon_venue_off).setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
            }
        }

        menu.add(Menu.CATEGORY_SYSTEM, R.id.filterEvents, 10, getString(R.string.filter))
                .setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);
        //menu.add(Menu.CATEGORY_SYSTEM, R.id.checkForUpdates, 11, getString(R.string.checkForUpdates))
        //.setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);
        menu.add(Menu.CATEGORY_SYSTEM, R.id.conferenceList, 12, getString(R.string.conferenceList))
                .setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);
        menu.add(Menu.CATEGORY_SYSTEM, R.id.aboutItem, 13, getString(R.string.menu_about))
                .setShowAsAction(MenuItem.SHOW_AS_ACTION_COLLAPSE_ACTION_VIEW);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(final MenuItem menuItem) {
        int itemId = menuItem.getItemId();
        if (itemId == R.id.search) {
            return true;
        } else if (itemId == R.id.conferenceList) {
            launchConferenceListActivity();
            return true;
        } else if (itemId == R.id.checkForUpdates) {
            checkForUpdates();
            return true;
        } else if (itemId == R.id.mapsOptionMenuItem) {
            Intent i = new Intent(HomeActivity.this, MapsActivity.class);
            i.putExtra("venueId", mVenueId);
            startActivity(i);
            return true;
        } else if (itemId == R.id.aboutItem) {
            AboutDialog about = new AboutDialog(this);
            about.setTitle("About");
            about.show();
            return true;
        } else if (itemId == R.id.filterEvents) {
            if (mConference != null) {
                FragmentManager fragmentManager = getSupportFragmentManager();
                FilterDialogFragment newFragment = FilterDialogFragment.newInstance(this.mConferenceId,
                        mConference.getName());
                newFragment.show(fragmentManager, "Filter");
            }
            return true;
        }

        return super.onOptionsItemSelected(menuItem);
    }

    private void doSearch(String query) {
        Database db = SUSEConferences.getDatabase();
        ArrayList<String> results = db.searchEvents(mConferenceId, query);
        if (results.size() == 0) {
            Toast.makeText(this, "No results", Toast.LENGTH_SHORT).show();
            return;
        }

        Intent i = new Intent(HomeActivity.this, SearchResultsActivity.class);
        i.putExtra("conferenceId", this.mConferenceId);
        i.putExtra("query", query);
        i.putExtra("results", results);
        startActivity(i);
    }

    // When the device is rotated, we don't want to go and load up
    // the social stream again, so loadSocial will be set to false
    // and it will just reuse the existing fragment.
    private void setView(boolean loadSocial) {
        Log.d("SUSEConferences", "setView");

        if (mDialog != null)
            mDialog.dismiss();

        showChangeLog();
        Database db = SUSEConferences.getDatabase();
        mConference = db.getConference(mConferenceId);
        mVenueId = db.getConferenceVenue(mConferenceId);
        getSupportActionBar().setTitle(mConference.getName());
        Log.d("SUSEConferences", "Conference ID is " + mConferenceId);

        mPhonePager = (ViewPager) findViewById(R.id.phonePager);
        if (mPhonePager != null) { // Phone layout
            ActionBar bar = getSupportActionBar();
            bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
            Bundle args = new Bundle();
            args.putLong("conferenceId", this.mConferenceId);
            args.putString("socialTag", mConference.getSocialTag());
            args.putString("conferenceName", mConference.getName());

            // If the user has switched the conference after another conference
            // was loaded, we'll just reset everything
            if (mTabsAdapter == null) {
                mTabsAdapter = new TabAdapter(this, mPhonePager);
                Tab myScheduleTab = bar.newTab();

                myScheduleTab.setText(getString(R.string.mySchedule));
                myScheduleTab.setTag(MY_SCHEDULE_TAG);
                mTabsAdapter.addTab(myScheduleTab, MyScheduleFragment.class, args);

                Tab scheduleTab = bar.newTab();
                scheduleTab.setText(getString(R.string.fullSchedule));
                scheduleTab.setTag(SCHEDULE_TAG);
                mTabsAdapter.addTab(scheduleTab, ScheduleFragment.class, args);

                if (hasInternet()) {
                    mTabsAdapter.addTab(bar.newTab().setText(getString(R.string.newsFeed)), NewsFeedFragment.class,
                            args);
                    //mTabsAdapter.addTab(
                    //      bar.newTab().setText(getString(R.string.rssFeed)),
                    //      RssFeedFragment.class,args);
                }
            }
        } else { // Tablet layout
            FragmentManager fm = getSupportFragmentManager();
            Bundle args = new Bundle();
            args.putLong("conferenceId", this.mConferenceId);
            args.putString("socialTag", mConference.getSocialTag());
            args.putString("conferenceName", mConference.getName());
            MyScheduleFragment mySched = new MyScheduleFragment();
            mySched.setArguments(args);
            fm.beginTransaction().add(R.id.myScheduleFragmentLayout, mySched, MY_SCHEDULE_TAG).commit();

            ScheduleFragment sched = new ScheduleFragment();
            sched.setArguments(args);
            fm.beginTransaction().add(R.id.scheduleFragmentLayout, sched, SCHEDULE_TAG).commit();

            if (hasInternet() && loadSocial) {
                NewsFeedFragment newsFeed = new NewsFeedFragment();
                newsFeed.setArguments(args);
                fm.beginTransaction().add(R.id.socialLayout, newsFeed, NEWSFEED_TAG).commit();
            }

            if (!hasInternet()) {
                RelativeLayout horizontal = (RelativeLayout) findViewById(R.id.newsFeedHorizontalLayout);
                if (horizontal != null)
                    horizontal.setVisibility(View.GONE);
                FrameLayout socialLayout = (FrameLayout) findViewById(R.id.socialLayout);
                socialLayout.setVisibility(View.GONE);
                TextView labelView = (TextView) findViewById(R.id.newsFeedTextView);
                labelView.setVisibility(View.GONE);
            }
        }
    }

    private void loadConferences() {
        mDialog = ProgressDialog.show(HomeActivity.this, "", "Downloading conference list, please wait...", true);
        GetConferencesTask task = new GetConferencesTask(Config.BASE_URL, this);
        task.execute();
    }

    @Override
    public void conferencesDownloaded(ArrayList<Conference> conferences) {
        Log.d("SUSEConferences", "Conferences downloaded: " + conferences.size());
        mDialog.dismiss();
        if (conferences.size() == 1) {
            conferenceChosen(conferences.get(0));
        } else if (conferences.size() > 1) {
            launchConferenceListActivity();
        }
    }

    private void conferenceChosen(Conference conference) {
        mConferenceId = conference.getSqlId();
        mConference = conference;
        if (!conference.isCached()) {
            Log.d("SUSEConferences", "Conference is not cached");
            CacheConferenceTask task = new CacheConferenceTask(this, conference, this);
            task.execute();
        } else {
            Log.d("SUSEConferences", "Conference is cached, switching");
            SharedPreferences settings = getSharedPreferences("SUSEConferences", 0);
            SharedPreferences.Editor editor = settings.edit();
            editor.putLong("active_conference", mConferenceId);
            editor.commit();
            setView(true);
        }
    }

    private void checkForUpdates() {
        if (!hasInternet()) {
            Toast.makeText(this, "You don't have internet access!", 3).show();
            return;
        }

        CheckForUpdatesTask task = new CheckForUpdatesTask(this, mConference, this);
        task.execute();
    }

    // Google Maps doesn't work on Kindle devices
    private boolean hasGoogleMaps() {
        try {
            Class.forName("com.google.android.maps.MapView");
            return true;
        } catch (ClassNotFoundException e) {
            return false;
        }
    }

    private boolean hasInternet() {
        boolean ret = true;
        ConnectivityManager manager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo info = manager.getActiveNetworkInfo();
        if (info == null || !info.isConnected())
            ret = false;

        return ret;
    }

    public void filterSet() {
        ScheduleFragment fragment = null;
        if (mPhonePager != null) {
            fragment = (ScheduleFragment) mTabsAdapter.getItem(1);
        } else {
            FragmentManager fragmentManager = getSupportFragmentManager();
            fragment = (ScheduleFragment) fragmentManager.findFragmentByTag(SCHEDULE_TAG);
        }

        if (fragment == null)
            Log.d("SUSEConferences", "Couldn't find fragment!");
        else
            fragment.requery();
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_OK && requestCode == CONFERENCE_LIST_CODE) {
            long id = data.getExtras().getLong("selected_conference");
            if (id != mConferenceId) {
                SharedPreferences settings = getSharedPreferences("SUSEConferences", 0);
                SharedPreferences.Editor editor = settings.edit();
                editor.putLong("active_conference", id);
                editor.commit();
                // TODO This is clumsy, figure out how to handle reloading the fragments
                // without crashes
                Intent i = getBaseContext().getPackageManager()
                        .getLaunchIntentForPackage(getBaseContext().getPackageName());
                i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                startActivity(i);
            }
        } else if (resultCode == RESULT_CANCELED && requestCode == CONFERENCE_LIST_CODE) {
            // If they don't have any conference cached at all, exit
            if (mConferenceId == -1)
                finish();
        }
    }

    private void launchConferenceListActivity() {
        if (mDialog != null)
            mDialog.dismiss();
        mDialog = null;
        Intent i = new Intent(HomeActivity.this, ConferenceListActivity.class);
        startActivityForResult(i, CONFERENCE_LIST_CODE);
    }

    @Override
    public void conferenceCached(long id, String message) {
        Database db = SUSEConferences.getDatabase();
        if (id == -1) {
            Log.d("SUSEConferences", "Error!");
            // TODO handle errors more gracefully
            db.setConferenceAsCached(mConference.getSqlId(), 0);
            db.clearDatabase(mConference.getSqlId());

            if (mDialog != null)
                mDialog.dismiss();

            SharedPreferences settings = getSharedPreferences("SUSEConferences", 0);
            SharedPreferences.Editor editor = settings.edit();
            editor.putLong("active_conference", -1);
            editor.commit();

            AlertDialog.Builder builder = new AlertDialog.Builder(HomeActivity.this);
            builder.setMessage(message);
            builder.setCancelable(false);
            builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                    HomeActivity.this.finish();
                }
            });
            builder.show();
        } else {
            Log.d("SUSEConferences", "Conference cached");
            SharedPreferences settings = getSharedPreferences("SUSEConferences", 0);
            SharedPreferences.Editor editor = settings.edit();
            editor.putLong("active_conference", id);
            editor.commit();
            setView(true);
        }
    }

    private void showChangeLog() {
        SharedPreferences settings = getSharedPreferences("SUSEConferences", 0);
        String lastVersion = settings.getString("changelog_version", "");
        String currentVersion = "";
        int showChangelog = getResources().getInteger(R.integer.showChangelog);
        try {
            currentVersion = getPackageManager().getPackageInfo(getPackageName(), 0).versionName;
        } catch (NameNotFoundException e) {
            e.printStackTrace();
            return;
        }

        SharedPreferences.Editor editor = settings.edit();
        editor.putString("changelog_version", currentVersion);
        editor.commit();

        if (!currentVersion.equals(lastVersion) && showChangelog == 1) {
            FragmentManager fragmentManager = getSupportFragmentManager();
            ChangeLogDialogFragment newFragment = ChangeLogDialogFragment.newInstance();
            newFragment.show(fragmentManager, "Changelog");
        }
    }

    @Override
    public void updatesChecked(long id, String error) {
        if (id == -1) {
            AlertDialog.Builder builder = new AlertDialog.Builder(this);
            builder.setMessage(error);
            builder.setCancelable(false);
            builder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                }
            });
            builder.show();
        } else if (id == 0) {
            Toast.makeText(this, "No updates available", Toast.LENGTH_SHORT).show();
        } else {
            ScheduleFragment scheduleFragment = null;
            MyScheduleFragment myScheduleFragment = null;
            Database db = SUSEConferences.getDatabase();
            mVenueId = db.getConferenceVenue(id);
            if (mPhonePager != null) {
                myScheduleFragment = (MyScheduleFragment) mTabsAdapter.getItem(0);
                scheduleFragment = (ScheduleFragment) mTabsAdapter.getItem(1);
            } else {
                FragmentManager fragmentManager = getSupportFragmentManager();
                myScheduleFragment = (MyScheduleFragment) fragmentManager.findFragmentByTag(MY_SCHEDULE_TAG);
                scheduleFragment = (ScheduleFragment) fragmentManager.findFragmentByTag(SCHEDULE_TAG);
            }

            if (scheduleFragment == null)
                Log.d("SUSEConferences", "Couldn't find fragment!");
            else
                scheduleFragment.requery();

            if (myScheduleFragment == null)
                Log.d("SUSEConferences", "Couldn't find myschedule fragment");
            else
                myScheduleFragment.setItems();
        }
    }

    // Show the keyboard when the user clicks on the search field
    @Override
    public boolean onMenuItemActionExpand(MenuItem item) {
        final EditText searchText = (EditText) item.getActionView();
        searchText.post(new Runnable() {
            @Override
            public void run() {
                searchText.requestFocus();
                InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                imm.showSoftInput(searchText, InputMethodManager.SHOW_IMPLICIT);
            }
        });

        return true;
    }

    // Collapsing the search field doesn't automatically close the soft keyboard,
    // so do that manually
    @Override
    public boolean onMenuItemActionCollapse(MenuItem item) {
        final EditText searchText = (EditText) item.getActionView();
        searchText.post(new Runnable() {
            @Override
            public void run() {
                Log.d("SUSEConferences", "Closing keyboard");
                InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                imm.toggleSoftInput(InputMethodManager.HIDE_IMPLICIT_ONLY, 0);
            }
        });

        return true;
    }

}