diff --git a/SweetDreamsLib/AndroidManifest.xml b/SweetDreamsLib/AndroidManifest.xml index b0d7079..a7e79ea 100644 --- a/SweetDreamsLib/AndroidManifest.xml +++ b/SweetDreamsLib/AndroidManifest.xml @@ -3,7 +3,7 @@ android:installLocation="auto" android:versionCode="5" android:versionName="0.0.5" package="com.TwentyCodes.android.SweetDreamsLib"> - diff --git a/SweetDreamsLib/ChangeLog b/SweetDreamsLib/ChangeLog index e69de29..44e23ff 100644 --- a/SweetDreamsLib/ChangeLog +++ b/SweetDreamsLib/ChangeLog @@ -0,0 +1,8 @@ +fixes #172 +added a check in SweetDreamsMain to see if the timer is <= to 0. if so close application. This resulted in the application +closing if the exit on finish was selected because the timer is always 0 or less than if it isn't running. +modified line in Service for when timer is decreased to stop at 0. + +in short. the issue was being that the timer only had two states. it was either -1 or above zero. if the timer was -1 it represented both the timer was complete +and that a timer never existed. thus the application would not close. modified the timer to be at 0 if the timer never existed and -1 if finished. above zero +represents still in play \ No newline at end of file diff --git a/SweetDreamsLib/res/drawable-hdpi/icon.png b/SweetDreamsLib/res/drawable-hdpi/icon.png index 8074c4c..5c99a4a 100644 Binary files a/SweetDreamsLib/res/drawable-hdpi/icon.png and b/SweetDreamsLib/res/drawable-hdpi/icon.png differ diff --git a/SweetDreamsLib/res/drawable-ldpi/icon.png b/SweetDreamsLib/res/drawable-ldpi/icon.png index 1095584..ff0bb88 100644 Binary files a/SweetDreamsLib/res/drawable-ldpi/icon.png and b/SweetDreamsLib/res/drawable-ldpi/icon.png differ diff --git a/SweetDreamsLib/res/drawable-mdpi/icon.png b/SweetDreamsLib/res/drawable-mdpi/icon.png index a07c69f..628ba02 100644 Binary files a/SweetDreamsLib/res/drawable-mdpi/icon.png and b/SweetDreamsLib/res/drawable-mdpi/icon.png differ diff --git a/SweetDreamsLib/res/raw/ac.ogg b/SweetDreamsLib/res/raw/ac.ogg deleted file mode 100644 index 8029165..0000000 Binary files a/SweetDreamsLib/res/raw/ac.ogg and /dev/null differ diff --git a/SweetDreamsLib/res/raw/beach.ogg b/SweetDreamsLib/res/raw/beach.ogg index 92a4ce5..e9bb6c0 100644 Binary files a/SweetDreamsLib/res/raw/beach.ogg and b/SweetDreamsLib/res/raw/beach.ogg differ diff --git a/SweetDreamsLib/res/raw/crickets.ogg b/SweetDreamsLib/res/raw/crickets.ogg index d429c63..1386775 100644 Binary files a/SweetDreamsLib/res/raw/crickets.ogg and b/SweetDreamsLib/res/raw/crickets.ogg differ diff --git a/SweetDreamsLib/res/raw/falls.ogg b/SweetDreamsLib/res/raw/falls.ogg index 47f5be5..b6b1f83 100644 Binary files a/SweetDreamsLib/res/raw/falls.ogg and b/SweetDreamsLib/res/raw/falls.ogg differ diff --git a/SweetDreamsLib/res/raw/river.ogg b/SweetDreamsLib/res/raw/river.ogg index 8ccde88..e7dd211 100644 Binary files a/SweetDreamsLib/res/raw/river.ogg and b/SweetDreamsLib/res/raw/river.ogg differ diff --git a/SweetDreamsLib/res/raw/wn.ogg b/SweetDreamsLib/res/raw/wn.ogg new file mode 100644 index 0000000..1a5c321 Binary files /dev/null and b/SweetDreamsLib/res/raw/wn.ogg differ diff --git a/SweetDreamsLib/res/values/sounds.xml b/SweetDreamsLib/res/values/sounds.xml index 65da885..5e7da7f 100644 --- a/SweetDreamsLib/res/values/sounds.xml +++ b/SweetDreamsLib/res/values/sounds.xml @@ -5,6 +5,6 @@ Beach Crickets Water Falls - Air Conditioner + White Noise diff --git a/SweetDreamsLib/src/com/TwentyCodes/android/SweetDreamsLib/Playback.aidl b/SweetDreamsLib/src/com/TwentyCodes/android/SweetDreamsLib/Playback.aidl new file mode 100644 index 0000000..53a63b8 --- /dev/null +++ b/SweetDreamsLib/src/com/TwentyCodes/android/SweetDreamsLib/Playback.aidl @@ -0,0 +1,20 @@ +/** + * Playback.aidl + * @date Feb 19, 2011 + * @author ricky barrette + * @author Twenty Codes, LLC + */ + +package com.TwentyCodes.android.SweetDreamsLib; + +interface Playback { + + void play(int resId); + + void stop(); + + boolean isPlaying(); + + long getTimeRemaining(); + +} \ No newline at end of file diff --git a/SweetDreamsLib/src/com/TwentyCodes/android/SweetDreamsLib/PlaybackService.java b/SweetDreamsLib/src/com/TwentyCodes/android/SweetDreamsLib/PlaybackService.java new file mode 100644 index 0000000..6d58069 --- /dev/null +++ b/SweetDreamsLib/src/com/TwentyCodes/android/SweetDreamsLib/PlaybackService.java @@ -0,0 +1,176 @@ +/** + * PlaybackService.java + * @date Feb 19, 2011 + * @author ricky barrette + * @author Twenty Codes, LLC + */ +package com.TwentyCodes.android.SweetDreamsLib; + +import android.app.Service; +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.media.MediaPlayer; +import android.os.Handler; +import android.os.IBinder; +import android.os.RemoteException; +import android.util.Log; + +import com.TwentyCodes.android.SweetDreamsLib.Playback.Stub; + +/** + * This service will handle sound track play back to allow for seem-less play back while configuration changes happen + * @author ricky barrette + */ +public class PlaybackService extends Service implements Runnable{ + + private MediaPlayer mMediaPlayer; + private long mTimeRemaining = 0; + private Handler mHandler; + + private final Stub mPlayback = new Playback.Stub(){ + + /** + * a convince method used to get the amount of time left + * (non-Javadoc) + * @see com.TwentyCodes.android.SweetDreamsLib.Playback#getTimeRemaining() + * @author ricky barrette + */ + @Override + public long getTimeRemaining() throws RemoteException { + return mTimeRemaining; + } + + /** + * returns whether or not the media player is playing + * (non-Javadoc) + * @see com.TwentyCodes.android.SweetDreamsLib.Playback#isPlaying() + * @author ricky barrette + */ + @Override + public boolean isPlaying() throws RemoteException { + if(mMediaPlayer != null) + return mMediaPlayer.isPlaying(); + else + return false; + } + + /** + * plays the specified sound track, infinitely looping it + * (non-Javadoc) + * @see com.TwentyCodes.android.SweetDreamsLib.Playback#play(int) + * @author ricky barrette + */ + @Override + public void play(int resId) throws RemoteException { + stop(); + mMediaPlayer = MediaPlayer.create(PlaybackService.this, resId); + mMediaPlayer.setLooping(true); + mMediaPlayer.start(); + + SharedPreferences settings = PlaybackService.this.getSharedPreferences(Settings.SETTINGS, Context.MODE_PRIVATE); + + boolean timerEnabled = settings.getBoolean(Settings.TIMER_ENABLED, false); + + if(SweetDreamsMain.isFUll == false) + timerEnabled = true; + + if (timerEnabled){ + mTimeRemaining = (settings.getInt("timer_length", 30) * 60000); + + //start the timer + mHandler.postDelayed(PlaybackService.this, 1000l); + } + + } + + /** + * Stops the play back of the sound track + * (non-Javadoc) + * @see com.TwentyCodes.android.SweetDreamsLib.Playback#stop() + * @author ricky barrette + */ + @Override + public void stop() throws RemoteException { + try { + mMediaPlayer.stop(); + } catch (Exception e) { + e.printStackTrace(); + } + mHandler.removeCallbacks(PlaybackService.this); + } + + }; + + /** + * (non-Javadoc) + * @see android.app.Service#onBind(android.content.Intent) + * @author ricky barrette + */ + @Override + public IBinder onBind(Intent intent) { + return mPlayback; + } + + @Override + public void onCreate(){ + Log.v(SweetDreamsMain.TAG, "PlaybackService.onCreate()"); + super.onCreate(); + mHandler = new Handler(); + } + + /** + * Called when the service is about to be destroyed. + * Here we release the media player + * (non-Javadoc) + * @see android.app.Service#onDestroy() + * @author ricky barrette + */ + @Override + public void onDestroy(){ + Log.v(SweetDreamsMain.TAG, "PlaybackService.onDestroy()"); + try { + mMediaPlayer.stop(); + } catch (Exception e) { + e.printStackTrace(); + } + try { + mMediaPlayer.release(); + } catch (Exception e) { + e.printStackTrace(); + } + + mHandler.removeCallbacks(this); + mTimeRemaining = 0; + super.onDestroy(); + } + + @Override + public void run() { + Log.v(SweetDreamsMain.TAG, "Tick"); + + //stop the timer if there is nothing playing + if(mMediaPlayer != null) { + if(! mMediaPlayer.isPlaying()) + mHandler.removeCallbacks(this); + } + else + mHandler.removeCallbacks(this); + + mTimeRemaining = mTimeRemaining - 1000l; + + if(mTimeRemaining <= 0) { + try { + mTimeRemaining = -1; + mPlayback.stop(); + } catch (RemoteException e) { + e.printStackTrace(); + } + this.stopSelf(); + } + + //que the next tick + mHandler.postDelayed(this, 1000l); + } + +} \ No newline at end of file diff --git a/SweetDreamsLib/src/com/TwentyCodes/android/SweetDreamsLib/Settings.java b/SweetDreamsLib/src/com/TwentyCodes/android/SweetDreamsLib/Settings.java index fa230db..6e8c3ea 100644 --- a/SweetDreamsLib/src/com/TwentyCodes/android/SweetDreamsLib/Settings.java +++ b/SweetDreamsLib/src/com/TwentyCodes/android/SweetDreamsLib/Settings.java @@ -26,7 +26,7 @@ public class Settings extends PreferenceActivity implements OnPreferenceChangeLi protected static final String SOUND_BEACH = "Beach"; protected static final String SOUND_CRICKETS = "Crickets"; protected static final String SOUND_FALLS = "Water Falls"; - protected static final String SOUND_AC = "Air Conditioner"; + protected static final String SOUND_WN = "White Noise"; //the following strings are for saving volume level from the audiomanager.STREAM_MUSIC so we can restore them back when the app quits protected static final String MUSIC_VOLUME = "music_volume"; @@ -47,7 +47,7 @@ public class Settings extends PreferenceActivity implements OnPreferenceChangeLi getPreferenceManager().setSharedPreferencesName(SETTINGS); //load preferences xml - this.addPreferencesFromResource( SweetDreamsFull.isFUll ? R.xml.settings : R.xml.settings_lite); + this.addPreferencesFromResource( SweetDreamsMain.isFUll ? R.xml.settings : R.xml.settings_lite); //get shared_prefs SharedPreferences settings = getPreferenceManager().getSharedPreferences(); @@ -69,7 +69,7 @@ public class Settings extends PreferenceActivity implements OnPreferenceChangeLi Preference timerLength = findPreference(TIMER_LENGTH); timerLength.setOnPreferenceChangeListener(this); try { - if(SweetDreamsFull.isFUll) + if(SweetDreamsMain.isFUll) timerLength.setSummary(settings.getInt(TIMER_LENGTH, 5)); else timerLength.setSummary(30); diff --git a/SweetDreamsLib/src/com/TwentyCodes/android/SweetDreamsLib/SweetDreamsFull.java b/SweetDreamsLib/src/com/TwentyCodes/android/SweetDreamsLib/SweetDreamsMain.java similarity index 54% rename from SweetDreamsLib/src/com/TwentyCodes/android/SweetDreamsLib/SweetDreamsFull.java rename to SweetDreamsLib/src/com/TwentyCodes/android/SweetDreamsLib/SweetDreamsMain.java index 8a5e84b..70b1e00 100644 --- a/SweetDreamsLib/src/com/TwentyCodes/android/SweetDreamsLib/SweetDreamsFull.java +++ b/SweetDreamsLib/src/com/TwentyCodes/android/SweetDreamsLib/SweetDreamsMain.java @@ -4,17 +4,20 @@ */ package com.TwentyCodes.android.SweetDreamsLib; -import com.TwentyCodes.android.exception.ExceptionHandler; - import android.app.Activity; +import android.content.ComponentName; import android.content.Context; import android.content.Intent; +import android.content.ServiceConnection; import android.content.SharedPreferences; import android.content.SharedPreferences.Editor; import android.media.AudioManager; -import android.media.MediaPlayer; import android.os.Bundle; -import android.os.CountDownTimer; +import android.os.Handler; +import android.os.IBinder; +import android.os.RemoteException; +import android.telephony.PhoneStateListener; +import android.telephony.TelephonyManager; import android.util.Log; import android.view.Menu; import android.view.MenuItem; @@ -25,34 +28,73 @@ import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.TextView; +import com.TwentyCodes.android.exception.ExceptionHandler; + /** * this class is responsible for setting up the ui and handling ui events * @author ricky */ -public class SweetDreamsFull extends Activity implements OnClickListener, OnSeekBarChangeListener{ +public class SweetDreamsMain extends Activity implements OnClickListener, OnSeekBarChangeListener, ServiceConnection, Runnable { private boolean isPlaying; private ImageButton mPlayPauseButton; private AudioManager mAudioManager; private final int STREAM = AudioManager.STREAM_MUSIC; - protected static MediaPlayer mMediaPlayer; private ExceptionHandler mDamageReport; private final int SETTINGS = Menu.FIRST; private final int QUIT = Menu.FIRST +1; private SharedPreferences mSettings; - protected static final String TAG = "WhiteNoise"; - private Timer mTimer; + protected static final String TAG = "SweetDreams"; + private Playback mService; + private Handler mHandler; + private SeekBar mVolume; protected static TextView mTimeLeftTextView; protected static boolean isFUll = true; + protected static final boolean DEBUG = true; + protected boolean inCall; + /** + * Call back class for PhoneStateListener to be used + * @author ricky barrette + */ + private class MyPhoneStateListener extends PhoneStateListener { + @Override + public void onCallStateChanged(int state,String incomingNumber){ + Log.e(TAG, "PhoneCallStateNotified.Incoming"); + switch(state){ + case TelephonyManager.CALL_STATE_RINGING: + if(isPlaying){ + inCall = true; + stopPlaying(); + } + break; + case TelephonyManager.CALL_STATE_IDLE: + if(inCall){ + inCall = false; + try { + loadSound(); + } catch (RemoteException e) { + e.printStackTrace(); + } + } + break; + case TelephonyManager.CALL_STATE_OFFHOOK: + if(isPlaying){ + inCall = true; + stopPlaying(); + } + break; + } + } + } + /** * adjusts the provided Stream volume to the provided level * @param stream * @param level * @author ricky barrette */ - private void adjustVolume(int stream, int level) { - + private void adjustVolume(int stream, int level) { /* * if the seek bar is set to a value that is higher than what the the stream value is set for * then subtract the seek bar's value from the current volume of the stream, and then @@ -79,38 +121,38 @@ public class SweetDreamsFull extends Activity implements OnClickListener, OnSeek } /** - * loads the sound from shared_prefs that the user wants, and set the mediaplayer to loop + * loads the sound from shared_prefs that the user wants, and starts the playback service * loads river sound track by default. * * @author ricky barrette + * @throws RemoteException */ - private void loadSound(){ - Log.i(TAG,"loadSound()"); - try { - mMediaPlayer.reset(); - } catch (Exception e) { - e.printStackTrace(); - } + private void loadSound() throws RemoteException{ + if (DEBUG) + Log.i(TAG,"loadSound()"); + + mPlayPauseButton.setBackgroundDrawable(getResources().getDrawable(R.drawable.pause_button)); + isPlaying = true; + String sound = mSettings.getString("sounds", Settings.SOUND_RIVER); - Log.v(TAG,"sound = "+ sound); + if (DEBUG) + Log.v(TAG,"sound = "+ sound); if (sound != null){ - if (sound.equals(Settings.SOUND_BEACH)) - mMediaPlayer = MediaPlayer.create(this, R.raw.beach); + if (mService != null) { + if (sound.equals(Settings.SOUND_BEACH)) + mService.play(R.raw.beach); + if (sound.equals(Settings.SOUND_WN)) + mService.play(R.raw.wn); + if (sound.equals(Settings.SOUND_CRICKETS)) + mService.play(R.raw.crickets); + if (sound.equals(Settings.SOUND_FALLS)) + mService.play(R.raw.falls); + if (sound.equals(Settings.SOUND_RIVER)) + mService.play(R.raw.river); + } - if (sound.equals(Settings.SOUND_AC)) - mMediaPlayer = MediaPlayer.create(this, R.raw.ac); - - if (sound.equals(Settings.SOUND_CRICKETS)) - mMediaPlayer = MediaPlayer.create(this, R.raw.crickets); - - if (sound.equals(Settings.SOUND_FALLS)) - mMediaPlayer = MediaPlayer.create(this, R.raw.falls); - - if (sound.equals(Settings.SOUND_RIVER)) - mMediaPlayer = MediaPlayer.create(this, R.raw.river); - - mMediaPlayer.setLooping(true); } + } /** @@ -119,6 +161,8 @@ public class SweetDreamsFull extends Activity implements OnClickListener, OnSeek */ @Override public void onClick(View v) { + if (DEBUG) + Log.i(TAG, "onClick()"); /* * if the sound track is no playing then * change the button background from a play symbol to a pause symbol, set isPlaying to true, load the user preferred sound track, and play it @@ -126,25 +170,17 @@ public class SweetDreamsFull extends Activity implements OnClickListener, OnSeek * change the button background from a pause symbol to a play symbol, set isPlaying to false, and stop playing the sound track */ if (!isPlaying){ - mPlayPauseButton.setBackgroundDrawable(getResources().getDrawable(R.drawable.pause_button)); - isPlaying = true; - loadSound(); - mMediaPlayer.start(); - - boolean timerEnabled = mSettings.getBoolean(Settings.TIMER_ENABLED, false); - - if(isFUll == false) - timerEnabled = true; - - if (timerEnabled){ - Log.v(TAG,"Starting timer"); - long time = + (mSettings.getInt("timer_length", 30) * 60000); - Log.v(TAG,"time = " + time); - mTimer = new Timer(time); - mTimer.start(); + try { + loadSound(); + } catch (RemoteException e) { + e.printStackTrace(); } - } else { - stopPlaying(); + + //if the timer is enabled, then start the ui updating handler + if(mSettings.getBoolean(Settings.TIMER_ENABLED, false) || ! isFUll) + mHandler.post(this); + } else { + stopPlaying(); } } @@ -158,8 +194,8 @@ public class SweetDreamsFull extends Activity implements OnClickListener, OnSeek @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); -// setContentView(R.layout.main); - Log.i(TAG,"onCreate()"); + if (DEBUG) + Log.i(TAG,"onCreate()"); // setup crash report handler mDamageReport = new ExceptionHandler(this); @@ -174,17 +210,24 @@ public class SweetDreamsFull extends Activity implements OnClickListener, OnSeek mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); //initialize the volume seekbar and set - SeekBar sbVolume = (SeekBar) findViewById(R.id.volume); - sbVolume.setOnSeekBarChangeListener(this); - sbVolume.setMax(mAudioManager.getStreamMaxVolume(STREAM)); - sbVolume.setProgress(mAudioManager.getStreamVolume(STREAM)); + mVolume = (SeekBar) findViewById(R.id.volume); + mVolume.setOnSeekBarChangeListener(this); + mVolume.setMax(mAudioManager.getStreamMaxVolume(STREAM)); + mVolume.setProgress(mAudioManager.getStreamVolume(STREAM)); + + mTimeLeftTextView = (TextView) findViewById(R.id.time_left); //load shared_prefs mSettings = getSharedPreferences(Settings.SETTINGS, 0); - loadSound(); + startService(new Intent(this, PlaybackService.class)); + mHandler = new Handler(); + saveStreamVolume(STREAM); + + TelephonyManager telephonyManager = (TelephonyManager)getSystemService(TELEPHONY_SERVICE); + telephonyManager.listen(new MyPhoneStateListener(), PhoneStateListener.LISTEN_CALL_STATE); } /** @@ -199,17 +242,25 @@ public class SweetDreamsFull extends Activity implements OnClickListener, OnSeek } /** - * here we set the Stream volume back to what ever it was when the activity started * (non-Javadoc) * @see android.app.Activity#onDestroy() * @author ricky barrette */ @Override public void onDestroy(){ - adjustVolume(STREAM,mSettings.getInt(Settings.MUSIC_VOLUME, 0)); + mHandler.removeCallbacks(this); + + if(this.isPlaying && this.isFinishing() && mService != null) + stopPlaying(); + + this.unbindService(this); + + if(this.isFinishing()) + this.stopService(new Intent(this, PlaybackService.class)); + super.onDestroy(); } - + /** * handles menu selection * @author ricky barrette 3-30-2010 @@ -220,7 +271,7 @@ public class SweetDreamsFull extends Activity implements OnClickListener, OnSeek case SETTINGS: Intent intent = new Intent().setClass(this, Settings.class); startActivity(intent); - stopPlaying(); + stopPlaying(); return true; case QUIT: @@ -231,8 +282,18 @@ public class SweetDreamsFull extends Activity implements OnClickListener, OnSeek return false; } + /** + * called when the activity is being paused. + * here we cancel the timer if it exists to prevent any funky stuff from happening + * (non-Javadoc) + * @see android.app.Activity#onPause() + * @author ricky barrette + */ @Override public void onPause(){ + if (DEBUG) + Log.v(TAG, "onPause()"); + mHandler.removeCallbacks(this); super.onPause(); } @@ -253,11 +314,6 @@ public class SweetDreamsFull extends Activity implements OnClickListener, OnSeek } } - @Override - public void onRestart(){ - super.onRestart(); - } - /** * we load the track title textview in onResume so it will update every time the activity loads * (non-Javadoc) @@ -266,20 +322,19 @@ public class SweetDreamsFull extends Activity implements OnClickListener, OnSeek */ @Override public void onResume(){ + if (DEBUG) + Log.v(TAG,"onResume()"); super.onResume(); + this.bindService(new Intent(this, PlaybackService.class), this, Context.BIND_AUTO_CREATE); TextView trackTitle = (TextView) findViewById(R.id.track_title); trackTitle.setText(mSettings.getString(Settings.SOUNDS,"Rainy River")); - } - - @Override - public void onStart(){ - super.onStart(); + mHandler.post(this); } @Override public void onStartTrackingTouch(SeekBar seekBar) { /* - * NOT YET IMPLEMENTED + * NOT IMPLEMENTED * needed for OnSeekBarChangeListener */ } @@ -292,19 +347,14 @@ public class SweetDreamsFull extends Activity implements OnClickListener, OnSeek */ @Override public void onStop(){ - stopPlaying(); - try { - mMediaPlayer.release(); - } catch (Exception e) { - e.printStackTrace(); - } + mHandler.removeCallbacks(this); super.onStop(); } @Override public void onStopTrackingTouch(SeekBar seekBar) { /* - * NOT YET IMPLEMENTED + * NOT IMPLEMENTED * needed for OnSeekBarChangeListener */ } @@ -325,74 +375,101 @@ public class SweetDreamsFull extends Activity implements OnClickListener, OnSeek * stops music from playing, sets the pay_pause button background to a play symbol, and if the time is enabled, cancels the timer * * @author ricky barrette + * @throws RemoteException */ private void stopPlaying(){ + if (DEBUG) + Log.i(TAG, "stopPlaying()"); mPlayPauseButton.setBackgroundDrawable(getResources().getDrawable(R.drawable.play_button)); isPlaying = false; try { - mMediaPlayer.stop(); - } catch (IllegalStateException e) { + mService.stop(); + } catch (RemoteException e) { + e.printStackTrace(); + } catch (NullPointerException e){ e.printStackTrace(); - Log.e(TAG,"failed to stop media player"); } - if (mTimer != null) { - mTimer.cancel(); - mTimer = null; - mTimeLeftTextView.setText(""); + mHandler.removeCallbacks(this); + mTimeLeftTextView.setText(""); + } + + /** + * called when we get our connection to the playback service + * (non-Javadoc) + * @see android.content.ServiceConnection#onServiceConnected(android.content.ComponentName, android.os.IBinder) + * @author ricky barrette + */ + @Override + public void onServiceConnected(ComponentName name, IBinder service) { + if (DEBUG) + Log.v(TAG,"onServiceConnected()"); + mService = Playback.Stub.asInterface(service); + try { + isPlaying = mService.isPlaying(); + } catch (RemoteException e) { + e.printStackTrace(); + } catch (NullPointerException e){ + e.printStackTrace(); + } + + if(isPlaying) { + mPlayPauseButton.setBackgroundDrawable(getResources().getDrawable(R.drawable.pause_button)); + mHandler.post(this); } } /** - * this internal class will handle timing functions such as a timer that stops play back of a sound track & updates timeLeft textview every second + * called when we disconnect from our service + * (non-Javadoc) + * @see android.content.ServiceConnection#onServiceDisconnected(android.content.ComponentName) * @author ricky barrette */ - class Timer extends CountDownTimer { + @Override + public void onServiceDisconnected(ComponentName name) { + mService = null; + } + + /** + * convince method for formating the seconds string + * @param seconds + * @return formated string + * @author ricky barrette + */ + private String padTime(int seconds){ + if (seconds <= 9) + return "0"+ seconds; + return ""+ seconds; + } + + /** + * the run method of this runnable activity that is used to update the ui with the amount of time left + * (non-Javadoc) + * @see java.lang.Runnable#run() + * @author ricky barrette + */ + @Override + public void run() { - /** - * creates a new count down timer that stops play back of a sound track after specified time, and - * updates timeLeft textview every second - * @param millisInFuture - */ - public Timer(long millisInFuture) { - super(millisInFuture, 1000l); - Log.i(TAG,"Timer()"); - Log.v(TAG,"millisInFuture = "+ millisInFuture); - mTimeLeftTextView = (TextView) findViewById(R.id.time_left); - int hours = (int) (millisInFuture / 3600000); - millisInFuture = millisInFuture - (hours * 3600000); - int minutes = (int) ( millisInFuture / 60000); - int seconds = (int) (millisInFuture % 60000); - seconds = seconds / 1000; - mTimeLeftTextView.setText(hours +" : "+ padTime(minutes) +" : "+ padTime(seconds)); + boolean isTimerEnabled = mSettings.getBoolean("timer_enabled", false); + //if there is another instance in the que, remove it + mHandler.removeCallbacks(this); + + //get the time remaining + long millisUntilFinished = 1; + try { + millisUntilFinished = mService.getTimeRemaining(); + } catch (RemoteException e) { + e.printStackTrace(); + } catch (NullPointerException e){ + e.printStackTrace(); } - - /** - * stops the sound track being played by the media player - * (non-Javadoc) - * @see android.os.CountDownTimer#onFinish() - * @author ricky barrette - */ - @Override - public void onFinish() { - Log.i(TAG,"onFinish()"); - mTimeLeftTextView.setText(""); + + //update the UI + if(millisUntilFinished == -1 && isTimerEnabled){ + if (DEBUG) + Log.i(TAG, "run().timer is up"); stopPlaying(); - //if the user enables exit on finish, then kill the application - if(mSettings.getBoolean(Settings.TIMER_EXIT_ON_FINISH, false)){ - Log.v(TAG,"exit on finish enabled, calling finish()"); - finish(); - } - } - - /** - * updates the timeLeft textView to display the current time left till sound stops - * @see android.os.CountDownTimer#onTick(long) - * @param millisUntilFinished - * @author ricky barrette - */ - @Override - public void onTick(long millisUntilFinished) { - Log.i(TAG,"onTick()"); + } else { int hours = (int) (millisUntilFinished / 3600000); millisUntilFinished = millisUntilFinished - (hours * 3600000); int minutes = (int) ( millisUntilFinished / 60000); @@ -401,17 +478,12 @@ public class SweetDreamsFull extends Activity implements OnClickListener, OnSeek mTimeLeftTextView.setText(hours +" : "+ padTime(minutes) +" : "+ padTime(seconds)); } - /** - * convince method for formating the seconds string - * @param seconds - * @return formated string - * @author ricky barrette - */ - private String padTime(int seconds){ - if (seconds <= 9) - return "0"+ seconds; - return ""+ seconds; - } + //if the time is 0 && if exit on finish is enabled, then exit else just stop playing then finish + if(millisUntilFinished == -1 && isTimerEnabled) + if(mSettings.getBoolean(Settings.TIMER_EXIT_ON_FINISH, false)) + this.finish(); + //que another ui update + mHandler.postDelayed(this, 1000l); } } \ No newline at end of file