com.ephemeraldreams.gallyshuttle.ui.ScheduleActivity.java Source code

Java tutorial

Introduction

Here is the source code for com.ephemeraldreams.gallyshuttle.ui.ScheduleActivity.java

Source

/*
 *  Copyright (C) 2014 Timothy Yu
 *
 *  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.ephemeraldreams.gallyshuttle.ui;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.FragmentManager;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
import android.net.ConnectivityManager;
import android.os.Build;
import android.os.Bundle;
import android.provider.AlarmClock;
import android.support.v4.view.PagerTabStrip;
import android.support.v4.view.ViewPager;
import android.text.TextUtils;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;

import com.ephemeraldreams.gallyshuttle.R;
import com.ephemeraldreams.gallyshuttle.annotations.qualifiers.AlarmRingtoneChoice;
import com.ephemeraldreams.gallyshuttle.annotations.qualifiers.AlarmVibration;
import com.ephemeraldreams.gallyshuttle.api.ShuttleApiService;
import com.ephemeraldreams.gallyshuttle.api.models.ApiResponse;
import com.ephemeraldreams.gallyshuttle.data.CacheManager;
import com.ephemeraldreams.gallyshuttle.data.ScheduleUtils;
import com.ephemeraldreams.gallyshuttle.data.models.Schedule;
import com.ephemeraldreams.gallyshuttle.data.preferences.BooleanPreference;
import com.ephemeraldreams.gallyshuttle.data.preferences.StringPreference;
import com.ephemeraldreams.gallyshuttle.ui.adapters.TimesFragmentPagerAdapter;
import com.ephemeraldreams.gallyshuttle.ui.events.PrepareAlarmReminderEvent;
import com.squareup.otto.Bus;
import com.squareup.otto.Subscribe;

import java.io.FileNotFoundException;

import javax.inject.Inject;

import butterknife.InjectView;
import rx.Observable;
import rx.Observer;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
import timber.log.Timber;

/**
 * Activity to handle preparation and displaying schedule.
 */
public class ScheduleActivity extends BaseActivity implements Observer<ApiResponse> {

    private static final int[] SCHEDULE_IDS = { R.array.continuous_stations, R.array.alt_continuous_stations,
            R.array.late_night_stations, R.array.weekend_stations, R.array.modified_stations };

    private static final String EXTRA_SCHEDULE = "schedule";

    @InjectView(R.id.schedule_pager_tabs_strip)
    PagerTabStrip schedulePagerTabStrip;
    @InjectView(R.id.schedule_view_pager)
    ViewPager scheduleViewPager;
    private TimesFragmentPagerAdapter timesFragmentPagerAdapter;

    @Inject
    ShuttleApiService shuttleApiService;
    @Inject
    CacheManager cacheManager;
    private ProgressDialog progressDialog;
    private BroadcastReceiver networkStateBroadCastReceiver;
    private boolean isNetworkStateBroadcastReceiverRegistered;

    private int scheduleId;
    private Schedule schedule;
    @Inject
    Resources resources;

    @Inject
    Bus bus;
    @Inject
    FragmentManager fragmentManager;
    @Inject
    @AlarmRingtoneChoice
    StringPreference alarmRingtoneChoiceStringPreference;
    @Inject
    @AlarmVibration
    BooleanPreference alarmVibrationBooleanPreference;

    /**
     * Launch ScheduleActivity with specified schedule id.
     *
     * @param activity   Activity to launch from.
     * @param scheduleId Schedule to display.
     */
    public static void launchActivity(Activity activity, int scheduleId) {
        Intent intent = new Intent(activity, ScheduleActivity.class);
        intent.putExtra(EXTRA_SCHEDULE, SCHEDULE_IDS[scheduleId]);
        activity.startActivity(intent);
    }

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

        if (getIntent() != null) {
            scheduleId = getIntent().getIntExtra(EXTRA_SCHEDULE, SCHEDULE_IDS[0]);
        } else {
            scheduleId = SCHEDULE_IDS[0];
        }

        schedulePagerTabStrip.setTabIndicatorColor(getResources().getColor(R.color.buff));
        schedulePagerTabStrip.setBackgroundColor(getResources().getColor(R.color.blue));

        loadSchedule();
    }

    @Override
    public void onResume() {
        super.onResume();
        bus.register(this);
        if (networkStateBroadCastReceiver != null && !isNetworkStateBroadcastReceiverRegistered) {
            registerNetworkBroadcastReceiver();
        }
    }

    @Override
    public void onPause() {
        super.onPause();
        bus.unregister(this);
        if (networkStateBroadCastReceiver != null && isNetworkStateBroadcastReceiverRegistered) {
            unregisterNetworkBroadcastReceiver();
        }
    }

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

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.action_settings:
            SettingsActivity.launchActivity(this);
            return true;
        default:
            return super.onOptionsItemSelected(item);
        }
    }

    /**
     * Attempt to load from cache or download schedule from web.
     */
    private void loadSchedule() {

        progressDialog = new ProgressDialog(this);
        progressDialog.setMessage(getString(R.string.loading_message));
        progressDialog.show();

        String title = ScheduleUtils.getScheduleTitle(scheduleId, resources);

        if (cacheManager.scheduleCacheFileExists(cacheManager.getScheduleFile(title))) {
            try {
                schedule = cacheManager.readScheduleCacheFile(title);
                onCompleted();
            } catch (FileNotFoundException e) {
                Timber.e(e, "Cached file for " + title + " schedule not found.");
                loadScheduleFromWeb();
            }
        } else {
            loadScheduleFromWeb();
        }
    }

    /**
     * Download schedule data from web.
     */
    private void loadScheduleFromWeb() {
        Observable<ApiResponse> apiResponseObservable;
        switch (scheduleId) {
        case R.array.continuous_stations:
            apiResponseObservable = shuttleApiService.getContinuousSchedule();
            break;
        case R.array.alt_continuous_stations:
            apiResponseObservable = shuttleApiService.getAlternativeContinuousSchedule();
            break;
        case R.array.late_night_stations:
            apiResponseObservable = shuttleApiService.getLateNightSchedule();
            break;
        case R.array.weekend_stations:
            apiResponseObservable = shuttleApiService.getWeekendSchedule();
            break;
        case R.array.modified_stations:
            apiResponseObservable = shuttleApiService.getModifiedSchedule();
            break;
        default:
            apiResponseObservable = shuttleApiService.getContinuousSchedule();
            break;
        }
        apiResponseObservable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
                .subscribe(this);
    }

    @Override
    public void onNext(ApiResponse apiResponse) {
        schedule = new Schedule(scheduleId, apiResponse, resources);
        cacheManager.createScheduleCacheFile(schedule);
    }

    @Override
    public void onCompleted() {
        getSupportActionBar().setTitle(schedule.title);
        timesFragmentPagerAdapter = new TimesFragmentPagerAdapter(fragmentManager, schedule);
        scheduleViewPager.setAdapter(timesFragmentPagerAdapter);
        progressDialog.dismiss();
        Timber.d("Download complete.");
    }

    @Override
    public void onError(Throwable e) {
        Timber.e(e, "Error downloading schedule.");
        Toast.makeText(this, "Error loading schedule. Please check your Internet connection.", Toast.LENGTH_LONG)
                .show();
        registerNetworkBroadcastReceiver();
    }

    /**
     * Register a {@link #networkStateBroadCastReceiver}, which monitor for Internet connection
     * re-establishment.
     */
    private void registerNetworkBroadcastReceiver() {
        networkStateBroadCastReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                // Internet connection has been re-established.
                unregisterNetworkBroadcastReceiver();
            }
        };
        registerReceiver(networkStateBroadCastReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
        isNetworkStateBroadcastReceiverRegistered = true;
    }

    /**
     * Unregister {@link #networkStateBroadCastReceiver} and try loading schedule from web.
     */
    private void unregisterNetworkBroadcastReceiver() {
        loadScheduleFromWeb();
        unregisterReceiver(networkStateBroadCastReceiver);
        isNetworkStateBroadcastReceiverRegistered = false;
        networkStateBroadCastReceiver = null;
        Timber.d("Network broadcast receiver dismissed.");
    }

    /**
     * Display reminder confimation dialog and set alarm.
     *
     * @param event Event to get {@link PrepareAlarmReminderEvent#hour}, {@link PrepareAlarmReminderEvent#minute},
     *              and {@link PrepareAlarmReminderEvent#reminderDialogMessage}.
     */
    @Subscribe
    public void setAlarm(PrepareAlarmReminderEvent event) {

        final Intent alarmIntent = buildAlarmIntent(event.hour, event.minute);

        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("Set Alarm Reminder").setMessage(event.reminderDialogMessage)
                .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        startActivity(Intent.createChooser(alarmIntent, "Set alarm"));
                    }
                }).setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {

                    }
                });
        AlertDialog setReminderDialog = builder.create();
        setReminderDialog.show();
    }

    /**
     * Build an alarm intent to pass to other activities or alarm applications.
     *
     * @param hour   Alarm hour to set.
     * @param minute Alarm minute to set
     * @return Alarm intent.
     */
    private Intent buildAlarmIntent(int hour, int minute) {
        Intent alarmIntent = new Intent(AlarmClock.ACTION_SET_ALARM);
        CharSequence station = scheduleViewPager.getAdapter().getPageTitle(scheduleViewPager.getCurrentItem());
        alarmIntent.putExtra(AlarmClock.EXTRA_MESSAGE, station + " arrival reminder.");
        alarmIntent.putExtra(AlarmClock.EXTRA_SKIP_UI, false);
        alarmIntent.putExtra(AlarmClock.EXTRA_HOUR, hour);
        alarmIntent.putExtra(AlarmClock.EXTRA_MINUTES, minute);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            alarmIntent.putExtra(AlarmClock.EXTRA_VIBRATE, alarmVibrationBooleanPreference.get());
            if (TextUtils.isEmpty(alarmRingtoneChoiceStringPreference.get())) {
                alarmIntent.putExtra(AlarmClock.VALUE_RINGTONE_SILENT, true);
            } else {
                alarmIntent.putExtra(AlarmClock.EXTRA_RINGTONE, alarmRingtoneChoiceStringPreference.get());
            }
        }
        return alarmIntent;
    }
}