package com.dougkeen.bart; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.util.List; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.ObjectUtils; import org.holoeverywhere.app.Application; import android.app.AlarmManager; import android.content.Context; import android.media.MediaPlayer; import android.os.Parcel; import android.util.Log; import com.dougkeen.bart.data.DatabaseHelper; import com.dougkeen.bart.data.FavoritesPersistence; import com.dougkeen.bart.model.Constants; import com.dougkeen.bart.model.Departure; import com.dougkeen.bart.model.Station; import com.dougkeen.bart.model.StationPair; import com.googlecode.androidannotations.annotations.Bean; import com.googlecode.androidannotations.annotations.EApplication; @EApplication public class BartRunnerApplication extends Application { private static final int FIVE_MINUTES = 5 * 60 * 1000; private static final String CACHE_FILE_NAME = "lastBoardedDeparture"; private Departure mBoardedDeparture; private boolean mPlayAlarmRingtone; private boolean mAlarmSounding; private MediaPlayer mAlarmMediaPlayer; private static Context context; @Bean FavoritesPersistence favoritesPersistenceContext; private List favorites; public void saveFavorites() { if (favorites != null) { favoritesPersistenceContext.persist(favorites); } } public List getFavorites() { if (favorites == null) { favorites = favoritesPersistenceContext.restore(); if (favorites.isEmpty()) { // Upgrade database, in case favorites are still in there new DatabaseHelper(this).getReadableDatabase().close(); favorites = favoritesPersistenceContext.restore(); } } return favorites; } public void setFavorites(List favorites) { this.favorites = favorites; } public StationPair getFavorite(Station origin, Station destination) { for (StationPair favorite : getFavorites()) { if (origin.equals(favorite.getOrigin()) && destination.equals(favorite.getDestination())) { return favorite; } } return null; } public void addFavorite(StationPair favorite) { getFavorites().add(favorite); saveFavorites(); } public void removeFavorite(StationPair favorite) { getFavorites().remove(favorite); saveFavorites(); } @Override public void onCreate() { super.onCreate(); context = getApplicationContext(); } public static Context getAppContext() { return context; } public boolean shouldPlayAlarmRingtone() { return mPlayAlarmRingtone; } public void setPlayAlarmRingtone(boolean playAlarmRingtone) { this.mPlayAlarmRingtone = playAlarmRingtone; } public Departure getBoardedDeparture() { return getBoardedDeparture(false); } public Departure getBoardedDeparture(boolean useOldCache) { if (mBoardedDeparture == null) { // see if there's a saved one File cachedDepartureFile = new File(getCacheDir(), CACHE_FILE_NAME); if (cachedDepartureFile.exists()) { InputStream inputStream = null; try { inputStream = new FileInputStream(cachedDepartureFile); final byte[] byteArray = IOUtils.toByteArray(inputStream); final Parcel parcel = Parcel.obtain(); parcel.unmarshall(byteArray, 0, byteArray.length); parcel.setDataPosition(0); Departure lastBoardedDeparture = Departure.CREATOR .createFromParcel(parcel); parcel.recycle(); /* * Ooptionally check if the cached one is relatively recent. * If so, restore that to the application context */ long now = System.currentTimeMillis(); if (useOldCache || lastBoardedDeparture.getEstimatedArrivalTime() >= now - FIVE_MINUTES || lastBoardedDeparture.getMeanEstimate() >= now - 2 * FIVE_MINUTES) { mBoardedDeparture = lastBoardedDeparture; } } catch (Exception e) { Log.w(Constants.TAG, "Couldn't read or unmarshal lastBoardedDeparture file", e); try { cachedDepartureFile.delete(); } catch (SecurityException anotherException) { Log.w(Constants.TAG, "Couldn't delete lastBoardedDeparture file", anotherException); } } finally { IOUtils.closeQuietly(inputStream); } } } if (mBoardedDeparture != null && mBoardedDeparture.hasExpired()) { setBoardedDeparture(null); } return mBoardedDeparture; } public void setBoardedDeparture(Departure boardedDeparture) { if (!ObjectUtils.equals(boardedDeparture, mBoardedDeparture) || ObjectUtils.compare(mBoardedDeparture, boardedDeparture) != 0) { if (this.mBoardedDeparture != null) { this.mBoardedDeparture.getAlarmLeadTimeMinutesObservable() .unregisterAllObservers(); this.mBoardedDeparture.getAlarmPendingObservable() .unregisterAllObservers(); // Cancel any pending alarms for the current departure if (this.mBoardedDeparture.isAlarmPending()) { this.mBoardedDeparture .cancelAlarm( this, (AlarmManager) getSystemService(Context.ALARM_SERVICE)); } } this.mBoardedDeparture = boardedDeparture; File cachedDepartureFile = new File(getCacheDir(), CACHE_FILE_NAME); if (mBoardedDeparture == null) { try { cachedDepartureFile.delete(); } catch (SecurityException anotherException) { Log.w(Constants.TAG, "Couldn't delete lastBoardedDeparture file", anotherException); } } else { FileOutputStream fileOutputStream = null; try { fileOutputStream = new FileOutputStream(cachedDepartureFile); Parcel parcel = Parcel.obtain(); mBoardedDeparture.writeToParcel(parcel, 0); fileOutputStream.write(parcel.marshall()); } catch (Exception e) { Log.w(Constants.TAG, "Couldn't write last boarded departure cache file", e); } finally { IOUtils.closeQuietly(fileOutputStream); } } } } public boolean isAlarmSounding() { return mAlarmSounding; } public void setAlarmSounding(boolean alarmSounding) { this.mAlarmSounding = alarmSounding; } public MediaPlayer getAlarmMediaPlayer() { return mAlarmMediaPlayer; } public void setAlarmMediaPlayer(MediaPlayer alarmMediaPlayer) { this.mAlarmMediaPlayer = alarmMediaPlayer; } }