com.robsterthelobster.ucibustracker.ArrivalsFragment.java Source code

Java tutorial

Introduction

Here is the source code for com.robsterthelobster.ucibustracker.ArrivalsFragment.java

Source

/*
* Copyright (C) 2014 The Android Open Source Project
*
* 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.robsterthelobster.ucibustracker;

import android.app.Activity;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.robsterthelobster.ucibustracker.data.ArrivalsCursorWrapper;
import com.robsterthelobster.ucibustracker.data.ArrivalsPredictionAdapter;
import com.robsterthelobster.ucibustracker.data.UciBusIntentService;
import com.robsterthelobster.ucibustracker.data.db.BusContract;

import java.util.Calendar;

public class ArrivalsFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> {

    private final String TAG = ArrivalsFragment.class.getSimpleName();

    private final int ARRIVAL_LOADER = 0;
    private final int STOP_ARRIVAL_LOADER = 1;
    private final int NO_LOCATION_LOADER = 2;

    private final String[] ARRIVAL_COLUMNS = { BusContract.ArrivalEntry._ID,
            BusContract.ArrivalEntry.TABLE_NAME + "." + BusContract.ArrivalEntry.ROUTE_ID,
            BusContract.ArrivalEntry.TABLE_NAME + "." + BusContract.ArrivalEntry.ROUTE_NAME,
            BusContract.ArrivalEntry.TABLE_NAME + "." + BusContract.ArrivalEntry.STOP_ID,
            BusContract.ArrivalEntry.PREDICTION_TIME, BusContract.ArrivalEntry.MINUTES,
            BusContract.ArrivalEntry.MIN_ALT, BusContract.ArrivalEntry.MIN_ALT_2,
            BusContract.ArrivalEntry.SECONDS_TO_ARRIVAL,
            BusContract.RouteEntry.TABLE_NAME + "." + BusContract.RouteEntry.COLOR,
            BusContract.StopEntry.TABLE_NAME + "." + BusContract.StopEntry.STOP_NAME,
            BusContract.FavoriteEntry.TABLE_NAME + "." + BusContract.FavoriteEntry.FAVORITE,
            BusContract.StopEntry.LATITUDE, BusContract.StopEntry.LONGITUDE };
    public static final int C_ROUTE_ID = 1;
    public static final int C_ROUTE_NAME = 2;
    public static final int C_STOP_ID = 3;
    public static final int C_PREDICTION_TIME = 4;
    public static final int C_MINUTES = 5;
    public static final int C_MIN_ALT = 6;
    public static final int C_MIN_ALT2 = 7;
    public static final int C_SECONDS = 8;
    public static final int C_COLOR = 9;
    public static final int C_STOP_NAME = 10;
    public static final int C_FAVORITE = 11;
    public static final int C_LATITUDE = 12;
    public static final int C_LONGITUDE = 13;

    protected RecyclerView mRecyclerView;
    protected SwipeRefreshLayout mySwipeRefreshLayout;
    protected ArrivalsPredictionAdapter mAdapter;
    protected RecyclerView.LayoutManager mLayoutManager;
    protected TextView emptyView;
    //Handler mHandler = new Handler();
    Activity mActivity;

    private String routeName;
    private boolean hasRoute = false;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Bundle arguments = getArguments();
        if (arguments != null) {
            routeName = arguments.getString(Constants.ROUTE_NAME_KEY);
            hasRoute = true;
        }
        if (hasRoute)
            updateRouteData();

        startLoaders();
    }

    @SuppressWarnings("deprecation")
    @Override
    public void onAttach(Activity activity) {
        mActivity = activity;
        super.onAttach(activity);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_arrivals, container, false);
        rootView.setTag(TAG);

        mRecyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerView);
        emptyView = (TextView) rootView.findViewById(R.id.empty_view);

        mLayoutManager = new LinearLayoutManager(getActivity());
        mRecyclerView.setLayoutManager(mLayoutManager);
        mRecyclerView.addItemDecoration(new SimpleDividerItemDecoration(getContext()));

        mySwipeRefreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.swipe_refresh);

        mySwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                Log.i(TAG, "onRefresh called from SwipeRefreshLayout");

                updateRouteDataImmediately();
            }
        });

        mAdapter = new ArrivalsPredictionAdapter(getContext(), null);
        mRecyclerView.setAdapter(mAdapter);
        setHasOptionsMenu(true);

        updateRouteDataImmediately();

        return rootView;
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        // Inflate the menu; this adds items to the action bar if it is present.
        inflater.inflate(R.menu.arrivals_menu, menu);
    }

    @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

        switch (item.getItemId()) {
        case R.id.menu_refresh:
            Log.i(TAG, "Refresh menu item selected");
            mySwipeRefreshLayout.setRefreshing(true);
            updateRouteDataImmediately();
            break;
        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onSaveInstanceState(Bundle savedInstanceState) {
        super.onSaveInstanceState(savedInstanceState);
    }

    @Override
    public Loader<Cursor> onCreateLoader(int id, Bundle bundle) {

        String sortOrder;
        String location = "";
        if (Utility.isLocationLatLonAvailable(getContext())) {
            double latitude = Utility.getLocationLatitude(getContext());
            double longitude = Utility.getLocationLongitude(getContext());

            double fudge = Math.pow(Math.cos(Math.toRadians(latitude)), 2);

            String latOrder = "(" + latitude + " - " + BusContract.StopEntry.LATITUDE + ")";
            String longOrder = "(" + longitude + " - " + BusContract.StopEntry.LONGITUDE + ")";
            location = "(" + latOrder + "*" + latOrder + "+" + longOrder + "*" + longOrder + "*" + fudge + "), ";
        }

        switch (id) {
        case ARRIVAL_LOADER:
            // FAVORITES, THEN ARRIVAL TIME
            sortOrder = BusContract.FavoriteEntry.FAVORITE + " DESC, " + location
                    + BusContract.ArrivalEntry.SECONDS_TO_ARRIVAL + " ASC";
            return new CursorLoader(getContext(), BusContract.ArrivalEntry.CONTENT_URI, ARRIVAL_COLUMNS,
                    BusContract.ArrivalEntry.IS_CURRENT + " =? ", new String[] { "1" }, sortOrder);
        case STOP_ARRIVAL_LOADER:
            return new CursorLoader(getContext(), BusContract.ArrivalEntry.CONTENT_URI, ARRIVAL_COLUMNS,
                    BusContract.ArrivalEntry.IS_CURRENT + " = ?" + " AND " + BusContract.ArrivalEntry.TABLE_NAME
                            + "." + BusContract.ArrivalEntry.ROUTE_NAME + " = ?",
                    new String[] { "1", routeName },
                    BusContract.StopEntry.TABLE_NAME + "." + BusContract.StopEntry.STOP_ID);
        default:
            Log.d(TAG, "Not valid id: " + id);
            return null;
        }
    }

    @Override
    public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
        int id = loader.getId();
        switch (id) {
        // Only the arrival_loader needs to have the cursor filtered
        case ARRIVAL_LOADER:
            cursor = new ArrivalsCursorWrapper(cursor, Utility.getLocationLatitude(getContext()),
                    Utility.getLocationLongitude(getContext()),
                    getContext().getResources().getInteger(R.integer.nearby_distance));
        case STOP_ARRIVAL_LOADER:
            mAdapter.swapCursor(cursor);
            break;
        default:
            Log.d(TAG, "Not valid id: " + id);
        }

        updateEmptyView();

        // stop refreshing after finish
        mySwipeRefreshLayout.setRefreshing(false);
    }

    @Override
    public void onLoaderReset(Loader loader) {
    }

    private void updateRouteDataImmediately() {
        Intent intent = new Intent(getActivity(), UciBusIntentService.class);
        getActivity().startService(intent);
    }

    private void updateRouteData() {
        Intent alarmIntent = new Intent(getActivity(), UciBusIntentService.AlarmReceiver.class);

        PendingIntent pi = PendingIntent.getBroadcast(getActivity(), 0, alarmIntent, 0);

        AlarmManager am = (AlarmManager) getActivity().getSystemService(Context.ALARM_SERVICE);

        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(System.currentTimeMillis());
        calendar.add(Calendar.SECOND, 0);
        long frequency = 60 * 1000; // one minute, which is the minimum

        am.setRepeating(AlarmManager.RTC, calendar.getTimeInMillis(), frequency, pi);
    }

    private void startLoaders() {
        if (hasRoute) {
            startLoader(STOP_ARRIVAL_LOADER);
        } else {
            startLoader(ARRIVAL_LOADER);
        }
    }

    private void startLoader(int loader_id) {
        Loader loader = getLoaderManager().getLoader(loader_id);
        if (loader != null) {
            getLoaderManager().restartLoader(loader_id, null, this);
        } else {
            getLoaderManager().initLoader(loader_id, null, this);
        }
    }

    private void updateEmptyView() {
        if (mAdapter.getItemCount() == 0) {
            int message = R.string.empty_no_data_from_server;
            if (!Utility.isNetworkAvailable(getContext())) {
                message = R.string.empty_no_connection_message;
            } else if (mAdapter.getCursor() instanceof ArrivalsCursorWrapper
                    && Utility.isLocationLatLonAvailable(getContext())) {
                message = R.string.empty_no_nearby_message;
            }
            emptyView.setText(message);
            mRecyclerView.setVisibility(View.GONE);
            emptyView.setVisibility(View.VISIBLE);
        } else {
            mRecyclerView.setVisibility(View.VISIBLE);
            emptyView.setVisibility(View.GONE);
        }
    }
}