diff --git a/README.md b/README.md
index fe8e612..7a9415e 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,13 @@
-# android-infinite-timer
+# Infinite Timer
-Timer which loops over the specified interval, playing your default notification sound each time it hits 0.
\ No newline at end of file
+Timer which loops over the specified interval, playing your default notification sound each time it hits 0.
+
+## Update Notes
+
+### 2025-07-11
+(This article)[https://sijus.medium.com/resurrecting-a-5-year-old-android-app-a-developers-journey-59d8f5689e5b]
+ was very helpful in getting this app updated from SDK 25 to 36.
+
+## Licenses
+Chime sound byte came free from here:
+https://pixabay.com/sound-effects/chime-sound-7143/
diff --git a/app/build.gradle b/app/build.gradle
index 21a9460..e5b53a3 100755
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,14 +1,14 @@
apply plugin: 'com.android.application'
android {
- compileSdkVersion 28
- buildToolsVersion '28.0.3'
+ namespace "com.hyperling.apps.infinitetimer"
+ compileSdkVersion 36
defaultConfig {
applicationId "com.hyperling.apps.infinitetimer"
- minSdkVersion 15
- targetSdkVersion 28
- versionCode 7
- versionName "1.06"
+ minSdkVersion 14
+ targetSdkVersion 36
+ versionCode 8
+ versionName "1.1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
diff --git a/app/src/androidTest/java/com/hyperling/apps/infinitetimer/deleteme/ExampleInstrumentedTest.java b/app/src/androidTest/java/com/hyperling/apps/infinitetimer/deleteme/ExampleInstrumentedTest.java
deleted file mode 100755
index 068a20c..0000000
--- a/app/src/androidTest/java/com/hyperling/apps/infinitetimer/deleteme/ExampleInstrumentedTest.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package com.hyperling.apps.infinitetimer.deleteme;
-
-import android.content.Context;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static org.junit.Assert.*;
-
-/**
- * Instrumentation test, which will execute on an Android device.
- *
- * @see Testing documentation
- */
-@RunWith(AndroidJUnit4.class)
-public class ExampleInstrumentedTest {
- @Test
- public void useAppContext() throws Exception {
- // Context of the app under test.
- Context appContext = InstrumentationRegistry.getTargetContext();
-
- assertEquals("infinitetimer.apps.hyperling.com.infinitetimer", appContext.getPackageName());
- }
-}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 0f3a62d..72bd899 100755
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -1,18 +1,17 @@
-
+
-
+
-
diff --git a/app/src/main/java/com/hyperling/apps/infinitetimer/MainActivity.java b/app/src/main/java/com/hyperling/apps/infinitetimer/MainActivity.java
index ed37980..05f5547 100755
--- a/app/src/main/java/com/hyperling/apps/infinitetimer/MainActivity.java
+++ b/app/src/main/java/com/hyperling/apps/infinitetimer/MainActivity.java
@@ -1,28 +1,35 @@
package com.hyperling.apps.infinitetimer;
+import android.app.NotificationManager;
+import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.graphics.Color;
+import android.media.AudioManager;
import android.media.MediaPlayer;
+import android.media.Ringtone;
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.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
+import android.view.KeyEvent;
import android.view.View;
-import android.view.ViewManager;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
+import android.widget.SeekBar;
import android.widget.TableRow;
import android.widget.TextView;
+import java.net.URI;
import java.util.Map;
public class MainActivity extends AppCompatActivity {
- String TAG,
+ String TAG = "MainActivity.",
keySharedPreferences, keyDebug, keyChronometerTime, keyLoopInterval,
keyStartStop, keyAppOpen, keyServiceRunning,
stringChronometerDefault, stringChronometerTime, stringLoopInterval;
@@ -47,8 +54,15 @@ public class MainActivity extends AppCompatActivity {
Uri ringtoneUri;
MediaPlayer mediaPlayer;
+ SeekBar seekBar;
+ AudioManager audioManager;
+ TextView tvSeekBar;
+
@Override
protected void onCreate(Bundle savedInstanceState) {
+ String tag = "onCreate";
+ if (DEBUG) Log.d(tag, "Starting");
+
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
@@ -56,7 +70,6 @@ public class MainActivity extends AppCompatActivity {
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);
@@ -67,36 +80,83 @@ public class MainActivity extends AppCompatActivity {
stringChronometerDefault = getString(R.string.chronometerDefault);
+ if (DEBUG) Log.d(tag, "Got strings.");
+
/***** 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);
+ DEBUG = sharedPreferences.getBoolean(keyDebug, true);
appOpen = sharedPreferences.getBoolean(keyAppOpen, false);
serviceRunning = sharedPreferences.getBoolean(keyServiceRunning, false);
- /*
- if (!appOpen && !serviceRunning) {
- sharedPreferences.edit().putBoolean(keyStartStop, false).apply();
- }
- */
+ if (DEBUG) Log.d(tag, "Got preferences.");
// Sound
ringtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
+ if (DEBUG) Log.d(tag, "ringtoneUri=" + ringtoneUri.toString());
mediaPlayer = MediaPlayer.create(this, ringtoneUri);
+ if (mediaPlayer == null) {
+ if (DEBUG) Log.d(tag, "Media Player is null, trying alarm");
+ ringtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALARM);
+ mediaPlayer = MediaPlayer.create(this, ringtoneUri);
+ }
+ if (mediaPlayer == null) {
+ if (DEBUG) Log.d(tag, "Media Player is null, trying ringtone");
+ ringtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE);
+ mediaPlayer = MediaPlayer.create(this, ringtoneUri);
+ }
+ if (mediaPlayer == null) {
+ if (DEBUG) Log.d(tag, "Media Player is null, trying all");
+ ringtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_ALL);
+ mediaPlayer = MediaPlayer.create(this, ringtoneUri);
+ }
+ if (mediaPlayer == null) {
+ if (DEBUG) Log.d(tag, "Media Player is null, trying local sound byte");
+ mediaPlayer = MediaPlayer.create(this, R.raw.chime_sound_7143);
+ }
+ if (mediaPlayer == null) {
+ String message = "Could not find a notification, alarm, or ringtone to play.";
+ message += " App will not be able to function without one of these.";
+ message += " Please exit and install a system notification sound.";
- if (DEBUG) Log.d(TAG, "MainActivity.onCreate! Got strings.");
+ new AlertDialog.Builder(MainActivity.this)
+ .setTitle("Error")
+ .setMessage(message)
+ .setPositiveButton("Exit", new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ dialog.dismiss();
+ finish();
+ }
+ })
+ .setCancelable(false)
+ .show()
+ ;
+ } else {
+ if (DEBUG) Log.d(tag, "mediaPlayer=" + mediaPlayer.toString());
+ }
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));
+ String value = sharedPreferencesAll.get(key).toString();
+ Log.d(tag, "key=" + key + " value=" + value);
+
+ // If app crashed, ensure buttons are correct.
+ if (key.equals(keyStartStop) && value.equals("true")) {
+ if (DEBUG) Log.d(tag, "Shutting off improper START value");
+
+ // Ensure START is always off if we are creating (not resuming).
+ int count = 0;
+ while (!sharedPreferences.edit().putBoolean(keyStartStop, false).commit() && count < 50) {
+ if (DEBUG) Log.d(tag, "Commit failed, trying again. count=" + count);
+ count++;
+ }
+
+ boolean checkStartStop = sharedPreferences.getBoolean(keyStartStop, false);;
+ Log.d(tag, "key=" + key + " value=" + checkStartStop);
+ }
}
}
@@ -150,21 +210,54 @@ public class MainActivity extends AppCompatActivity {
etMillis.setVisibility(View.GONE);
//(ViewManager) etMillis.getParent().remove
- //sharedPreferences.edit().putBoolean(keyStartStop, false).apply();
+ seekBar = findViewById(R.id.seekBar);
+ setVolumeControlStream(AudioManager.STREAM_MUSIC);
+
+ audioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
+ int maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
+ seekBar.setMax(maxVolume);
+
+ tvSeekBar = findViewById(R.id.tvSeekbar);
+
+ syncVolume();
+
+ seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
+ audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, i, AudioManager.FLAG_SHOW_UI);
+ syncVolume();
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ syncVolume();
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ syncVolume();
+ }
+ });
+
+
recoverScreen();
- if (DEBUG) Log.d(TAG, "MainActivity.onCreate! Finished.");
+ if (DEBUG) Log.d(tag, "Finished");
}
private void doTimeChooser(){
- if (DEBUG) Log.d(TAG, "MainActivity.openTimeChooser!");
+ String tag = TAG + "doTimeChooser";
+ if (DEBUG) Log.d(tag, "Starting");
//stringLoopInterval = "00:00:07";
//setEditTexts(stringLoopInterval);
+
+ if (DEBUG) Log.d(tag, "Finished");
}
private void setEditTexts(String interval){
- if (DEBUG) Log.d(TAG, "MainActivity.setEditTexts! interval=" + interval);
+ String tag = TAG + "setEditTexts";
+ if (DEBUG) Log.d(tag, "Starting, interval=" + interval);
if (!interval.equals(stringChronometerDefault)) {
String[] time = interval.split(":");
@@ -188,29 +281,67 @@ public class MainActivity extends AppCompatActivity {
}
setLoopInterval();
+ if (DEBUG) Log.d(tag, "Finished");
}
private void setLoopInterval(){
- if (DEBUG) Log.d(TAG, "MainActivity.setLoopInterval!");
+ String tag = TAG + "setLoopInterval";
+ if (DEBUG) Log.d(tag, "Starting");
- int hours = Integer.parseInt("0"+etHours.getText().toString());
- int minutes = Integer.parseInt("0"+etMinutes.getText().toString());
- int seconds = Integer.parseInt("0"+etSeconds.getText().toString());
+ int hours = 0, minutes = 0, seconds = 0;
+ try {
+ hours = Integer.parseInt("0" + etHours.getText().toString());
+ } catch (Exception e) {
+ if (DEBUG) Log.d(tag, "Hours had an exception, using highest value");
+ hours = 99;
+ }
+ try {
+ minutes = Integer.parseInt("0" + etMinutes.getText().toString());
+ } catch (Exception e) {
+ if (DEBUG) Log.d(tag, "Minutes had an exception, using highest value");
+ minutes = 59;
+ }
+ try {
+ seconds = Integer.parseInt("0" + etSeconds.getText().toString());
+ } catch (Exception e) {
+ if (DEBUG) Log.d(tag, "Seconds had an exception, using highest value");
+ seconds = 59;
+ }
+
+ if ((hours + (minutes/60) + (seconds/60/60)) > 99) {
+ if (DEBUG) Log.d(tag, "Sum is over 99 hours, setting to 99:59:59");
+ hours = 99;
+ minutes = 59;
+ seconds = 59;
+ }
+
+ if (DEBUG) Log.d(tag, "hours=" + hours);
+ if (DEBUG) Log.d(tag, "minutes=" + minutes);
+ if (DEBUG) Log.d(tag, "seconds=" + seconds);
+
+ if (hours > 0) etHours.setText("" + hours);
+ if (minutes > 0) etMinutes.setText("" + minutes);
+ if (seconds > 0) etSeconds.setText("" + seconds);
longLoopInterval = (((hours*60*60) + (minutes*60) + seconds) * 1000);
- if (DEBUG) Log.d(TAG, "MainActivity.setLoopInterval! longLoopInterval=" + longLoopInterval);
+ if (DEBUG) Log.d(tag, "longLoopInterval=" + longLoopInterval);
setChronometer(longLoopInterval);
+
+ if (DEBUG) Log.d(tag, "Finished");
}
private void setChronometer(long milliseconds){
- if (DEBUG) Log.d(TAG, "MainActivity.setChronometer! milliseconds=" + milliseconds);
+ String tag = TAG + "setChronometer";
+ if (DEBUG) Log.d(tag, "Starting, 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)};
+ String[] time = {
+ Long.toString(milliseconds/(1000*60*60)),
+ Long.toString((milliseconds/(1000*60))%60),
+ Long.toString((milliseconds/(1000))%60)
+ };
for (int i = 0; i < time.length; i++){
while (time[i].length() < 2){
@@ -229,16 +360,18 @@ public class MainActivity extends AppCompatActivity {
doTimeChooser();
}
});*/
- if (DEBUG) Log.d(TAG, "MainActivity.setChronometer! display=" + display);
+ if (DEBUG) Log.d(tag, "display=" + display);
sharedPreferences.edit().putString(keyChronometerTime, display).apply();
- if (DEBUG) Log.d(TAG, "MainActivity.setChronometer! Before=" + chronometer.getText());
+ if (DEBUG) Log.d(tag, "Before=" + chronometer.getText());
chronometer.setText(display);
- if (DEBUG) Log.d(TAG, "MainActivity.setChronometer! After=" + chronometer.getText());
+ if (DEBUG) Log.d(tag, "After=" + chronometer.getText());
+ if (DEBUG) Log.d(tag, "Finished");
}
private void startStopChronometer(String buttonText){
- if (DEBUG) Log.d(TAG, "MainActivity.startStopChronometer!");
+ String tag = TAG + "startStopChronometer";
+ if (DEBUG) Log.d(tag, "Starting");
start = !start;
SharedPreferences.Editor editor = sharedPreferences.edit();
@@ -274,10 +407,13 @@ public class MainActivity extends AppCompatActivity {
flipStartStopButton();
flipResetPauseButton();
+
+ if (DEBUG) Log.d(tag, "Finished");
}
private void recoverScreen(){
- if (DEBUG) Log.d(TAG, "MainActivity.recoverScreen!");
+ String tag = TAG + "recoverScreen";
+ if (DEBUG) Log.d(tag, "Starting");
/***** Retrieve the last settings *****/
// Chronometer
@@ -290,6 +426,7 @@ public class MainActivity extends AppCompatActivity {
// Start/Stop Button
start = sharedPreferences.getBoolean(keyStartStop, false);
+ if (DEBUG) Log.d(tag, "start=" + start);
flipStartStopButton();
flipResetPauseButton();
@@ -301,10 +438,13 @@ public class MainActivity extends AppCompatActivity {
//startStopChronometer(stringChronometerTime);
//incrementTime.sendEmptyMessage(0);
+
+ if (DEBUG) Log.d(tag, "Finished");
}
private void flipStartStopButton(){
- if (DEBUG) Log.d(TAG, "MainActivity.flipStartStopButton!");
+ String tag = TAG + "flipStartStopButton";
+ if (DEBUG) Log.d(tag, "Starting");
start = sharedPreferences.getBoolean(keyStartStop, false);
serviceRunning = sharedPreferences.getBoolean(keyServiceRunning, false);
@@ -319,10 +459,13 @@ public class MainActivity extends AppCompatActivity {
}
btnStartStop.setBackgroundColor(Color.GREEN);
}
+
+ if (DEBUG) Log.d(tag, "Finished");
}
private void resetPauseChronometer(){
- if (DEBUG) Log.d(TAG, "MainActivity.resetPauseChronometer!");
+ String tag = TAG + "resetPauseChronometer";
+ if (DEBUG) Log.d(tag, "Starting");
start = sharedPreferences.getBoolean(keyStartStop, false);
serviceRunning = sharedPreferences.getBoolean(keyServiceRunning, false);
@@ -333,10 +476,13 @@ public class MainActivity extends AppCompatActivity {
else{
setEditTexts(stringChronometerDefault);
}
+
+ if (DEBUG) Log.d(tag, "Finished");
}
private void flipResetPauseButton(){
- if (DEBUG) Log.d(TAG, "MainActivity.flipResetPauseButton!");
+ String tag = TAG + "flipResetPauseButton";
+ if (DEBUG) Log.d(tag, "Starting");
start = sharedPreferences.getBoolean(keyStartStop, false);
serviceRunning = sharedPreferences.getBoolean(keyServiceRunning, false);
@@ -349,13 +495,17 @@ public class MainActivity extends AppCompatActivity {
btnResetPause.setText(getString(R.string.btnReset));
btnResetPause.setBackgroundColor(Color.RED);
}
+
+ if (DEBUG) Log.d(tag, "Finished");
}
- private Handler incrementTime = new Handler(){
+ private final Handler incrementTime = new Handler(){
@Override
public void handleMessage(Message msg) {
+ String tag = TAG + "handleMessage";
+ if (DEBUG) Log.d(tag, "Starting");
+
super.handleMessage(msg);
- if (DEBUG) Log.d(TAG, "MainActivity.incrementTime.handleMessage!");
appOpen = sharedPreferences.getBoolean(keyAppOpen, true);
if (appOpen) {
@@ -372,7 +522,7 @@ public class MainActivity extends AppCompatActivity {
// Calculate new time and text
setTimeLeft();
- if (DEBUG) Log.d(TAG, "MainActivity.incrementTime.handleMessage! longTimeLeft=" + longTimeLeft);
+ if (DEBUG) Log.d(tag, "longTimeLeft=" + longTimeLeft);
// Check if we need to beep
if (longTimeLeft < 1000){
@@ -381,12 +531,12 @@ public class MainActivity extends AppCompatActivity {
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);
+ Log.d(tag, "longLoopInterval=" + longLoopInterval);
+ Log.d(tag, "longStartTime=" + longStartTime);
+ Log.d(tag, "longEndTime=" + longEndTime);
+ Log.d(tag, "longTimeLeft=" + longTimeLeft);
+ Log.d(tag, "waitInterval=" + waitInterval);
+ Log.d(tag, "start=" + start);
//chronometer.setText("Test");
//setChronometer(200);
/*
@@ -404,11 +554,11 @@ public class MainActivity extends AppCompatActivity {
synchronized (this){
try{
wait(waitInterval);
- if (DEBUG) Log.d(TAG, "MainActivity.incrementTime.handleMessage! Done waiting.");
+ if (DEBUG) Log.d(tag, "Done waiting.");
}
catch (Exception e){
e.printStackTrace();
- if (DEBUG) Log.d(TAG, "MainActivity.incrementTime.handleMessage! Failed to wait.");
+ if (DEBUG) Log.d(tag, "Failed to wait.");
}
}
//sharedPreferences.edit().putBoolean(keyStartStop, true).apply();
@@ -419,59 +569,146 @@ public class MainActivity extends AppCompatActivity {
Thread t = new Thread(task);
t.start();
}
+ if (DEBUG) Log.d(tag, "Finished");
}
};
private void setStartTime(){
- if (DEBUG) Log.d(TAG, "MainActivity.setStartTime!");
+ String tag = TAG + "setStartTime";
+ if (DEBUG) Log.d(tag, "Starting");
+ if (DEBUG) Log.d(tag, "System.currentTimeMillis()=" + System.currentTimeMillis());
if (longTimeLeft == 0) {
- if (DEBUG) Log.d(TAG, "MainActivity.setStartTime! longTimeLeft==" + longTimeLeft);
+ if (DEBUG) Log.d(tag, "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);
+ if (DEBUG) Log.d(tag, "longStartTime=" + longStartTime);
longEndTime = longStartTime + longLoopInterval;
- if (DEBUG) Log.d(TAG, "MainActivity.setStartTime! longEndTime=" + longEndTime);
- }
- else{
- if (DEBUG) Log.d(TAG, "MainActivity.setStartTime! longTimeLeft==" + longTimeLeft);
+ if (DEBUG) Log.d(tag, "longEndTime=" + longEndTime);
+ } else {
+ if (DEBUG) Log.d(tag, "longTimeLeft=" + longTimeLeft);
longStartTime = System.currentTimeMillis() - waitInterval;
- if (DEBUG) Log.d(TAG, "MainActivity.setStartTime! longStartTime=" + longStartTime);
+ if (DEBUG) Log.d(tag, "longStartTime=" + longStartTime);
longEndTime = longStartTime + longTimeLeft;
- if (DEBUG) Log.d(TAG, "MainActivity.setStartTime! longEndTime=" + longEndTime);
+ if (DEBUG) Log.d(tag, "longEndTime=" + longEndTime);
}
+
+ if (DEBUG) Log.d(tag, "Finished");
}
private void setTimeLeft(){
- if (DEBUG) Log.d(TAG, "MainActivity.setTimeLeft!");
+ String tag = TAG + "setTimeLeft";
+ if (DEBUG) Log.d(tag, "Starting");
longTimeLeft = longEndTime - System.currentTimeMillis() + waitInterval;
- if (DEBUG) Log.d(TAG, "MainActivity.setTimeLeft! longTimeLeft=" + longTimeLeft);
+ if (DEBUG) Log.d(tag, "longTimeLeft=" + longTimeLeft);
setChronometer(longTimeLeft);
+
+ if (DEBUG) Log.d(tag, "Finished");
}
private void resetTimeLeft(){
- if (DEBUG) Log.d(TAG, "MainActivity.resetTimeLeft!");
+ String tag = TAG + "resetTimeLeft";
+ if (DEBUG) Log.d(tag, "Starting");
+
longTimeLeft = 0;
setChronometer(longLoopInterval);
+
+ if (DEBUG) Log.d(tag, "Finished");
}
private void playSound(){
- if (DEBUG) Log.d(TAG, "MainActivity.playSound!");
+ String tag = TAG + "playSound";
+ if (DEBUG) Log.d(tag, "Starting");
- /* Original code, did not work on Nexus 7 with CM 12.1-20151117 (Android 5.1.1)
- Ringtone ringtone = RingtoneManager.getRingtone(getApplicationContext(), ringtoneUri);
+ /* Original code, did not work on Nexus 7 with CM 12.1-20151117 (Android 5.1.1) * /
+ Uri uri = Uri.parse("android.resource://" + getPackageName() + "/raw/chime_sound_7143");
+ //Ringtone ringtone = RingtoneManager.getRingtone(getApplicationContext(), ringtoneUri);
+ Ringtone ringtone = RingtoneManager.getRingtone(getApplicationContext(), uri);
ringtone.play();
- */
+ /**/
- //mediaPlayer.reset();
- mediaPlayer.start();
+ try {
+ mediaPlayer.start();
+ } catch (Exception e) {
+ sharedPreferences.edit().putBoolean(keyStartStop, false).apply();
+
+ String message = "Failed to play a notification sound.";
+ message += " Please screenshot this error and send it to me@hyperling.com:\n\n";
+ message += e.toString();
+
+ new AlertDialog.Builder(MainActivity.this)
+ .setTitle("Error")
+ .setMessage(message)
+ .setPositiveButton("Exit", new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ dialog.dismiss();
+ finish();
+ }
+ })
+ .setCancelable(false)
+ .show()
+ ;
+ }
+
+ if (DEBUG) Log.d(tag, "Finished");
+ }
+
+ private void flipInputTexts() {
+ String tag = TAG + "flipInputTexts";
+ if (DEBUG) Log.d(tag, "Starting");
+
+ etHours.setEnabled(!start);
+ etMinutes.setEnabled(!start);
+ etSeconds.setEnabled(!start);
+
+ if (DEBUG) Log.d(tag, "Finished");
+ }
+
+ private void resetAll() {
+ String tag = TAG + "resetAll";
+ if (DEBUG) Log.d(tag, "Starting");
+
+ if (DEBUG) Log.d(tag, "Resetting screen values...");
+ setChronometer(0);
+ setEditTexts("");
+ setLoopInterval();
+ if (DEBUG) Log.d(tag, "Values reset");
+
+ if (DEBUG) Log.d(tag, "Resetting SharedPreferences...");
+ start = false;
+ SharedPreferences.Editor editor = sharedPreferences.edit();
+ editor.putBoolean(keyStartStop, start);
+ editor.putBoolean(keyAppOpen, start);
+ editor.putBoolean(keyServiceRunning, start);
+ int count = 0;
+ while (!editor.commit() && count < 50) {
+ Log.i(tag, "Failed! Reattempting commit... count=" + count);
+ count++;
+ };
+ if (DEBUG) Log.d(tag, "SharedPreferences reset");
+
+ if (DEBUG) Log.d(tag, "Finished");
+ }
+
+ public void syncVolume() {
+ String tag = TAG + "syncVolume";
+ if (DEBUG) Log.d(tag, "Starting");
+
+ int currVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
+ seekBar.setProgress(currVolume);
+
+ String volume = getString(R.string.tvSeekBar) + seekBar.getProgress() + "/" + seekBar.getMax();
+ tvSeekBar.setText(volume);
+
+ if (DEBUG) Log.d(tag, "Finished");
}
@Override
protected void onPause() {
- super.onPause();
- if (DEBUG) Log.d(TAG, "MainActivity.onPause!");
+ String tag = TAG + "onPause";
+ if (DEBUG) Log.d(tag, "Starting");
stringLoopInterval =
etHours.getText().toString() + ":" +
@@ -483,22 +720,50 @@ public class MainActivity extends AppCompatActivity {
editor.putString(keyLoopInterval, stringLoopInterval);
editor.putBoolean(keyAppOpen, false);
editor.apply();
+
+ if (DEBUG) Log.d(tag, "Done with local code, calling super.");
+
+ super.onPause();
+
+ if (DEBUG) Log.d(tag, "Finished");
}
@Override
protected void onResume() {
super.onResume();
- if (DEBUG) Log.d(TAG, "MainActivity.onResume!");
+
+ String tag = TAG + "onResume";
+ if (DEBUG) Log.d(tag, "Starting");
sharedPreferences.edit().putBoolean(keyServiceRunning, false).apply();
recoverScreen();
+
+ if (DEBUG) Log.d(tag, "Finished");
}
- private void flipInputTexts() {
- etHours.setEnabled(!start);
- etMinutes.setEnabled(!start);
- etSeconds.setEnabled(!start);
+ @Override
+ protected void onDestroy() {
+ String tag = TAG + "onDestroy";
+ if (DEBUG) Log.d(tag, "Starting");
+
+ resetAll();
+
+ if (DEBUG) Log.d(tag, "Done with local code, calling super..");
+
+ super.onDestroy();
+
+ if (DEBUG) Log.d(tag, "Finished");
}
-}
+ // TODO: This is somehow always 1 action behind the actual volume when pressing volume buttons.
+ // Like when doing down+up+down, the bar does nothing+down+up.
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ if (keyCode == KeyEvent.KEYCODE_VOLUME_UP || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
+ boolean bool = super.onKeyDown(keyCode, event);
+ syncVolume();
+ return bool;
+ }
+ return super.onKeyDown(keyCode, event);
+ }}
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index f7238ed..d30d6ed 100755
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -4,6 +4,7 @@
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:layout_marginTop="?android:actionBarSize"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
@@ -157,4 +158,27 @@
+
+
+
+
+
+
diff --git a/app/src/main/res/menu/menu_main.xml b/app/src/main/res/menu/menu_main.xml
index ddf5d9e..a7af6f4 100755
--- a/app/src/main/res/menu/menu_main.xml
+++ b/app/src/main/res/menu/menu_main.xml
@@ -5,20 +5,18 @@
android:id="@+id/action_milis"
android:orderInCategory="100"
android:title="@string/action_millis"
- app:showAsAction="never"
android:checkable="true" />
+ />
\ No newline at end of file
diff --git a/app/src/main/res/drawable/icon_512.png b/app/src/main/res/mipmap/icon_512.png
similarity index 100%
rename from app/src/main/res/drawable/icon_512.png
rename to app/src/main/res/mipmap/icon_512.png
diff --git a/app/src/main/res/mipmap/icon_rounded.png b/app/src/main/res/mipmap/icon_rounded.png
new file mode 100644
index 0000000..70a529e
Binary files /dev/null and b/app/src/main/res/mipmap/icon_rounded.png differ
diff --git a/app/src/main/res/mipmap/icon_rounded_512.png b/app/src/main/res/mipmap/icon_rounded_512.png
new file mode 100644
index 0000000..6585742
Binary files /dev/null and b/app/src/main/res/mipmap/icon_rounded_512.png differ
diff --git a/app/src/main/res/raw/chime_sound_7143.mp3 b/app/src/main/res/raw/chime_sound_7143.mp3
new file mode 100644
index 0000000..d9dbf34
Binary files /dev/null and b/app/src/main/res/raw/chime_sound_7143.mp3 differ
diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml
new file mode 100644
index 0000000..8f4f0ed
--- /dev/null
+++ b/app/src/main/res/values-es/strings.xml
@@ -0,0 +1,40 @@
+
+
+ Infinite Timer
+ v20250711
+ com.hyperling.apps.infinitetimer
+
+
+ InfiniteTimer
+ DEBUG
+ ChronometerTime
+ LoopInterval
+ StartStop
+ AppOpen
+ ServiceRunning
+
+
+ Empezar
+ Terminar
+ Elige un Tiempo
+ Reiniciar
+ Pausa
+ Seguir
+
+ 00:00:00
+
+ Horas
+ Minutos
+ Segundos
+ Millis
+ .
+
+ Tiempo entre notificaciones:
+ Cuenta regresiva hasta notificación:
+
+ Enable Millisecs
+ Enable Ads
+ Exit
+
+ Volumen:
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 8039e06..5df19ae 100755
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1,7 +1,7 @@
Infinite Timer
- Test v201610291024
+ v20250711
com.hyperling.apps.infinitetimer
@@ -35,4 +35,6 @@
Enable Millisecs
Enable Ads
Exit
+
+ Media Volume:
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index 4785832..c0cfd8f 100755
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -1,7 +1,7 @@
-
-