package com.hyperling.apps.infinitetimer; import android.content.SharedPreferences; import android.graphics.Color; import android.media.MediaPlayer; import android.media.RingtoneManager; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.support.v7.app.ActionBar; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.view.ViewManager; import android.view.WindowManager; import android.widget.Button; import android.widget.EditText; import android.widget.TableRow; import android.widget.TextView; import java.util.Map; public class MainActivity extends AppCompatActivity { String TAG, keySharedPreferences, keyDebug, keyChronometerTime, keyLoopInterval, keyStartStop, keyAppOpen, keyServiceRunning, stringChronometerDefault, stringChronometerTime, stringLoopInterval; // Try to make methods send and accept parameters to eliminate some of these, same with the string* Strings above long longLoopInterval, longStartTime, longEndTime, longTimeLeft; // Interrupt based checking would be nice int waitInterval = 99; boolean DEBUG, start, appOpen, serviceRunning; SharedPreferences sharedPreferences; TextView chronometer; Button btnStartStop, btnChooseTime, btnResetPause; EditText etHours, etMinutes, etSeconds, etMillis; TableRow trTime; TextView tvDot; Uri ringtoneUri; MediaPlayer mediaPlayer; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Prevent the keyboard from popping up automatically this.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN); /***** Get Strings *****/ TAG = getString(R.string.TAG); keySharedPreferences = getString(R.string.keySharedPreferences); keyDebug = getString(R.string.keyDebug); keyChronometerTime = getString(R.string.keyChronometerTime); keyLoopInterval = getString(R.string.keyLoopInterval); keyStartStop = getString(R.string.keyStartStop); keyAppOpen = getString(R.string.keyAppOpen); keyServiceRunning = getString(R.string.keyServiceRunning); stringChronometerDefault = getString(R.string.chronometerDefault); /***** Shared Preferences *****/ sharedPreferences = getSharedPreferences(keySharedPreferences, MODE_PRIVATE); // TODO: Comment these lines! //sharedPreferences.edit().putBoolean(keyDebug, true).apply(); //sharedPreferences.edit().putBoolean(keyStartStop, false).apply(); //sharedPreferences.edit().putString(keyLoopInterval, stringChronometerDefault).apply(); //sharedPreferences.edit().putString(keyChronometerTime, stringChronometerDefault).apply(); // TODO: Keep these! DEBUG = sharedPreferences.getBoolean(keyDebug, false); appOpen = sharedPreferences.getBoolean(keyAppOpen, false); serviceRunning = sharedPreferences.getBoolean(keyServiceRunning, false); /* if (!appOpen && !serviceRunning) { sharedPreferences.edit().putBoolean(keyStartStop, false).apply(); } */ // Sound ringtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION); mediaPlayer = MediaPlayer.create(this, ringtoneUri); if (DEBUG) Log.d(TAG, "MainActivity.onCreate! Got strings."); if (DEBUG){ // Print all preferences Map sharedPreferencesAll = sharedPreferences.getAll(); for (String key : sharedPreferencesAll.keySet()){ Log.d(TAG, "MainActivity.onCreate! key=" + key + " value=" + sharedPreferencesAll.get(key)); } } /***** UI *****/ chronometer = (TextView) findViewById(R.id.chronometer); chronometer.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { doTimeChooser(); } }); btnChooseTime = (Button) findViewById(R.id.btnChooseTime); btnChooseTime.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { doTimeChooser(); } }); btnStartStop = (Button) findViewById(R.id.btnStartStop); btnStartStop.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Button b = (Button) v; startStopChronometer(b.getText().toString()); } }); btnResetPause = (Button) findViewById(R.id.btnResetPause); btnResetPause.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { resetPauseChronometer(); } }); etHours = (EditText) findViewById(R.id.etHours); etMinutes = (EditText) findViewById(R.id.etMinutes); etSeconds = (EditText) findViewById(R.id.etSeconds); etMillis = (EditText) findViewById(R.id.etMillis); trTime = (TableRow) findViewById(R.id.trTime); trTime.setWeightSum(3); tvDot = (TextView) findViewById(R.id.tvDot); tvDot.setEnabled(false); tvDot.setVisibility(View.GONE); etMillis.setEnabled(false); etMillis.setVisibility(View.GONE); //(ViewManager) etMillis.getParent().remove //sharedPreferences.edit().putBoolean(keyStartStop, false).apply(); recoverScreen(); if (DEBUG) Log.d(TAG, "MainActivity.onCreate! Finished."); } private void doTimeChooser(){ if (DEBUG) Log.d(TAG, "MainActivity.openTimeChooser!"); //stringLoopInterval = "00:00:07"; //setEditTexts(stringLoopInterval); } private void setEditTexts(String interval){ if (DEBUG) Log.d(TAG, "MainActivity.setEditTexts! interval=" + interval); if (!interval.equals(stringChronometerDefault)) { String[] time = interval.split(":"); for (int i = 0; i < time.length; i++){ while (time[i].length() < 2){ time[i] = "0" + time[i]; } } if (time.length == 3) { etHours.setText(time[0]); etMinutes.setText(time[1]); etSeconds.setText(time[2]); } } else{ etHours.setText(""); etMinutes.setText(""); etSeconds.setText(""); } setLoopInterval(); } private void setLoopInterval(){ if (DEBUG) Log.d(TAG, "MainActivity.setLoopInterval!"); int hours = Integer.parseInt("0"+etHours.getText().toString()); int minutes = Integer.parseInt("0"+etMinutes.getText().toString()); int seconds = Integer.parseInt("0"+etSeconds.getText().toString()); longLoopInterval = (((hours*60*60) + (minutes*60) + seconds) * 1000); if (DEBUG) Log.d(TAG, "MainActivity.setLoopInterval! longLoopInterval=" + longLoopInterval); setChronometer(longLoopInterval); } private void setChronometer(long milliseconds){ if (DEBUG) Log.d(TAG, "MainActivity.setChronometer! milliseconds=" + milliseconds); //chronometer = (TextView) findViewById(R.id.chronometer); String[] time = {Long.toString(milliseconds/(1000*60*60)), Long.toString((milliseconds/(1000*60)%(60*60))), Long.toString((milliseconds/(1000))%60)}; for (int i = 0; i < time.length; i++){ while (time[i].length() < 2){ time[i] = "0" + time[i]; } } String display = time[0] + ":" + time[1] + ":" + time[2]; // Testing orientation change not allowing chronometer to update /* chronometer = (TextView) findViewById(R.id.chronometer); chronometer.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { doTimeChooser(); } });*/ if (DEBUG) Log.d(TAG, "MainActivity.setChronometer! display=" + display); sharedPreferences.edit().putString(keyChronometerTime, display).apply(); if (DEBUG) Log.d(TAG, "MainActivity.setChronometer! Before=" + chronometer.getText()); chronometer.setText(display); if (DEBUG) Log.d(TAG, "MainActivity.setChronometer! After=" + chronometer.getText()); } private void startStopChronometer(String buttonText){ if (DEBUG) Log.d(TAG, "MainActivity.startStopChronometer!"); start = !start; SharedPreferences.Editor editor = sharedPreferences.edit(); editor.putBoolean(keyStartStop, start); editor.putBoolean(keyAppOpen, true); editor.putBoolean(keyServiceRunning, false); editor.apply(); // hours:minutes:seconds should be disabled during count down. flipInputTexts(); if (buttonText.equals(getString(R.string.btnStart))){ incrementTime.sendEmptyMessage(0); setLoopInterval(); resetTimeLeft(); setStartTime(); } else if (buttonText.equals(getString(R.string.btnPause))){ btnStartStop.setText(getString(R.string.btnResume)); btnResetPause.setEnabled(false); etHours.setEnabled(false); etMinutes.setEnabled(false); etSeconds.setEnabled(false); } else if (buttonText.equals(getString(R.string.btnStop))){ setChronometer(longLoopInterval); } else if (buttonText.equals(getString(R.string.btnResume))){ setStartTime(); incrementTime.sendEmptyMessage(0); btnResetPause.setEnabled(true); } flipStartStopButton(); flipResetPauseButton(); } private void recoverScreen(){ if (DEBUG) Log.d(TAG, "MainActivity.recoverScreen!"); /***** Retrieve the last settings *****/ // Chronometer stringChronometerTime = sharedPreferences.getString(keyChronometerTime, stringChronometerDefault); chronometer.setText(stringChronometerTime); // Loop interval stringLoopInterval = sharedPreferences.getString(keyLoopInterval, stringChronometerDefault); setEditTexts(stringLoopInterval); // Start/Stop Button start = sharedPreferences.getBoolean(keyStartStop, false); flipStartStopButton(); flipResetPauseButton(); flipInputTexts(); // Testing how to keep timer ticking after rotation //start = !start; //startStopChronometer(stringChronometerTime); //incrementTime.sendEmptyMessage(0); } private void flipStartStopButton(){ if (DEBUG) Log.d(TAG, "MainActivity.flipStartStopButton!"); start = sharedPreferences.getBoolean(keyStartStop, false); serviceRunning = sharedPreferences.getBoolean(keyServiceRunning, false); //if (start && !serviceRunning){ if (start){ btnStartStop.setText(getString(R.string.btnStop)); btnStartStop.setBackgroundColor(Color.RED); } else { if (!btnStartStop.getText().toString().equals(getString(R.string.btnResume))) { btnStartStop.setText(getString(R.string.btnStart)); } btnStartStop.setBackgroundColor(Color.GREEN); } } private void resetPauseChronometer(){ if (DEBUG) Log.d(TAG, "MainActivity.resetPauseChronometer!"); start = sharedPreferences.getBoolean(keyStartStop, false); serviceRunning = sharedPreferences.getBoolean(keyServiceRunning, false); //if (start && !serviceRunning){ if (start){ startStopChronometer(btnResetPause.getText().toString()); } else{ setEditTexts(stringChronometerDefault); } } private void flipResetPauseButton(){ if (DEBUG) Log.d(TAG, "MainActivity.flipResetPauseButton!"); start = sharedPreferences.getBoolean(keyStartStop, false); serviceRunning = sharedPreferences.getBoolean(keyServiceRunning, false); //if (start && !serviceRunning){ if (start){ btnResetPause.setText(getString(R.string.btnPause)); btnResetPause.setBackgroundColor(Color.YELLOW); } else { btnResetPause.setText(getString(R.string.btnReset)); btnResetPause.setBackgroundColor(Color.RED); } } private Handler incrementTime = new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); if (DEBUG) Log.d(TAG, "MainActivity.incrementTime.handleMessage!"); appOpen = sharedPreferences.getBoolean(keyAppOpen, true); if (appOpen) { sharedPreferences.edit().putBoolean(keyServiceRunning, false).apply(); } else { sharedPreferences.edit().putBoolean(keyServiceRunning, true).apply(); } start = sharedPreferences.getBoolean(keyStartStop, false); if (start){ //start = !start; //sharedPreferences.edit().putBoolean(keyStartStop, false).apply(); // Calculate new time and text setTimeLeft(); if (DEBUG) Log.d(TAG, "MainActivity.incrementTime.handleMessage! longTimeLeft=" + longTimeLeft); // Check if we need to beep if (longTimeLeft < 1000){ playSound(); resetTimeLeft(); setStartTime(); if (DEBUG) { Log.d(TAG, "MainActivity.incrementTime.handleMessage!C longLoopInterval=" + longLoopInterval); Log.d(TAG, "MainActivity.incrementTime.handleMessage!C longStartTime=" + longStartTime); Log.d(TAG, "MainActivity.incrementTime.handleMessage!C longEndTime=" + longEndTime); Log.d(TAG, "MainActivity.incrementTime.handleMessage!C longTimeLeft=" + longTimeLeft); Log.d(TAG, "MainActivity.incrementTime.handleMessage!C waitInterval=" + waitInterval); Log.d(TAG, "MainActivity.incrementTime.handleMessage!C start=" + start); //chronometer.setText("Test"); //setChronometer(200); /* start=false; startStopChronometer("Start"); */ } } // Wait Runnable task = new Runnable() { @Override public void run() { synchronized (this){ try{ wait(waitInterval); if (DEBUG) Log.d(TAG, "MainActivity.incrementTime.handleMessage! Done waiting."); } catch (Exception e){ e.printStackTrace(); if (DEBUG) Log.d(TAG, "MainActivity.incrementTime.handleMessage! Failed to wait."); } } //sharedPreferences.edit().putBoolean(keyStartStop, true).apply(); incrementTime.sendEmptyMessage(0); //startStopChronometer("Start"); } }; Thread t = new Thread(task); t.start(); } } }; private void setStartTime(){ if (DEBUG) Log.d(TAG, "MainActivity.setStartTime!"); if (longTimeLeft == 0) { if (DEBUG) Log.d(TAG, "MainActivity.setStartTime! longTimeLeft==" + longTimeLeft); // Add extra 1000 so timer starts on interval and beeps after 1 longStartTime = System.currentTimeMillis() + 1000 - waitInterval; if (DEBUG) Log.d(TAG, "MainActivity.setStartTime! longStartTime=" + longStartTime); longEndTime = longStartTime + longLoopInterval; if (DEBUG) Log.d(TAG, "MainActivity.setStartTime! longEndTime=" + longEndTime); } else{ if (DEBUG) Log.d(TAG, "MainActivity.setStartTime! longTimeLeft==" + longTimeLeft); longStartTime = System.currentTimeMillis() - waitInterval; if (DEBUG) Log.d(TAG, "MainActivity.setStartTime! longStartTime=" + longStartTime); longEndTime = longStartTime + longTimeLeft; if (DEBUG) Log.d(TAG, "MainActivity.setStartTime! longEndTime=" + longEndTime); } } private void setTimeLeft(){ if (DEBUG) Log.d(TAG, "MainActivity.setTimeLeft!"); longTimeLeft = longEndTime - System.currentTimeMillis() + waitInterval; if (DEBUG) Log.d(TAG, "MainActivity.setTimeLeft! longTimeLeft=" + longTimeLeft); setChronometer(longTimeLeft); } private void resetTimeLeft(){ if (DEBUG) Log.d(TAG, "MainActivity.resetTimeLeft!"); longTimeLeft = 0; setChronometer(longLoopInterval); } private void playSound(){ if (DEBUG) Log.d(TAG, "MainActivity.playSound!"); /* Original code, did not work on Nexus 7 with CM 12.1-20151117 (Android 5.1.1) Ringtone ringtone = RingtoneManager.getRingtone(getApplicationContext(), ringtoneUri); ringtone.play(); */ //mediaPlayer.reset(); mediaPlayer.start(); } @Override protected void onPause() { super.onPause(); if (DEBUG) Log.d(TAG, "MainActivity.onPause!"); stringLoopInterval = etHours.getText().toString() + ":" + etMinutes.getText().toString() + ":" + etSeconds.getText().toString(); SharedPreferences.Editor editor = sharedPreferences.edit(); editor.putString(keyChronometerTime, chronometer.getText().toString()); editor.putString(keyLoopInterval, stringLoopInterval); editor.putBoolean(keyAppOpen, false); editor.apply(); } @Override protected void onResume() { super.onResume(); if (DEBUG) Log.d(TAG, "MainActivity.onResume!"); sharedPreferences.edit().putBoolean(keyServiceRunning, false).apply(); recoverScreen(); } private void flipInputTexts() { etHours.setEnabled(!start); etMinutes.setEnabled(!start); etSeconds.setEnabled(!start); } }