Skip to content

Commit 617a945

Browse files
committed
Refactor: Replace Runnable with TimerTask and update dependencies
This commit refactors the timer scheduling logic by replacing `Runnable` with `TimerTask` for better clarity and consistency with the `java.util.Timer` API. Key changes include: - Replaced `Runnable` with `TimerTask` in `CellState`, `ICellState`, and `MainService`. - Simplified timer scheduling logic in `CellState`. - Updated Gradle wrapper to version 9.1.0. - Bumped `google-services` plugin to 4.4.4. - Increased app version to 2.1.3. - Improved Android 13+ notification permission handling. - Minor code cleanup, including removing unused resources and imports.
1 parent 45bb920 commit 617a945

15 files changed

Lines changed: 52 additions & 55 deletions

File tree

app/build.gradle

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,14 @@ android {
1616
applicationId "com.softartdev.conwaysgameoflife"
1717
minSdkVersion 23
1818
targetSdkVersion 36
19-
versionCode 212
20-
versionName '2.1.2'
19+
versionCode 213
20+
versionName '2.1.3'
2121
resourceConfigurations += ['en']
2222
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
2323
}
2424
buildFeatures {
2525
viewBinding true
26+
buildConfig true
2627
}
2728
signingConfigs {
2829
config {

app/src/androidTest/java/com/softartdev/conwaysgameoflife/ExampleInstrumentedTest.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package com.softartdev.conwaysgameoflife;
22

3+
import static org.junit.Assert.assertEquals;
4+
35
import android.content.Context;
46

57
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -8,11 +10,8 @@
810
import org.junit.Test;
911
import org.junit.runner.RunWith;
1012

11-
import static org.junit.Assert.assertEquals;
12-
1313
/**
1414
* Instrumented test, which will execute on an Android device.
15-
*
1615
* See [testing documentation](http://d.android.com/tools/testing).
1716
*/
1817
@RunWith(AndroidJUnit4.class)

app/src/main/java/com/softartdev/conwaysgameoflife/MainService.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import com.softartdev.conwaysgameoflife.model.CellState
2323
import com.softartdev.conwaysgameoflife.model.ICellState
2424
import com.softartdev.conwaysgameoflife.ui.MainActivity
2525
import timber.log.Timber
26+
import java.util.TimerTask
2627

2728

2829
class MainService : Service() {
@@ -44,7 +45,7 @@ class MainService : Service() {
4445
super.onCreate()
4546
Timber.d("onCreate")
4647
createNotificationChannel(applicationContext, notificationManager)
47-
val runnable: Runnable = object : Runnable {
48+
val timerTask = object : TimerTask() {
4849
val uiHandler = Handler(Looper.myLooper()!!)
4950
override fun run() {
5051
Timber.d("Process generation step: %s", iCellState.countGeneration)//FIXME await on idle
@@ -58,7 +59,7 @@ class MainService : Service() {
5859
} else notificationManager.cancelAll()
5960
}
6061
}
61-
iCellState.setRunnable(runnable)
62+
iCellState.setTimerTask(timerTask)
6263
}
6364

6465
override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {

app/src/main/java/com/softartdev/conwaysgameoflife/model/CellState.java

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public class CellState implements ICellState {
1111
private static final int SHOW_DELAY = 500;
1212
private volatile int period = SHOW_DELAY;
1313
private Timer timer;//FIXME: consider more optimized alternatives for such loop
14-
private Runnable runnable;
14+
private TimerTask timerTask;
1515
private final boolean[][] lifeGeneration = new boolean[LIFE_SIZE][LIFE_SIZE];
1616
private final boolean[][] nextGeneration = new boolean[LIFE_SIZE][LIFE_SIZE];
1717
private int countGeneration = 0;
@@ -26,31 +26,24 @@ public int getPeriod() {
2626
return period;
2727
}
2828

29-
@Override
30-
public void scheduleTimer(Runnable runnable) {
29+
private void scheduleTimer() {
3130
if (timer == null) {
3231
timer = new Timer();
3332
}
34-
this.runnable = runnable;
35-
TimerTask timerTask = new TimerTask() {
36-
@Override
37-
public void run() {
38-
CellState.this.runnable.run();
39-
}
40-
};
33+
if (timerTask == null) return;
4134
timer.schedule(timerTask, 0L, period);
4235
}
4336

4437
@Override
45-
public void setRunnable(Runnable runnable) {
46-
this.runnable = runnable;
38+
public void setTimerTask(TimerTask timerTask) {
39+
this.timerTask = timerTask;
4740
}
4841

4942
@Override
5043
public void updatePeriod(int period) {
5144
cancelTimer();
5245
this.period = period;
53-
scheduleTimer(this.runnable);
46+
scheduleTimer();
5447
}
5548

5649
@Override
@@ -63,7 +56,7 @@ public void cancelTimer() {
6356

6457
@Override
6558
public void resumeTimer() {
66-
scheduleTimer(runnable);
59+
scheduleTimer();
6760
}
6861

6962
@Override

app/src/main/java/com/softartdev/conwaysgameoflife/model/ICellState.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
package com.softartdev.conwaysgameoflife.model;
22

3+
import java.util.TimerTask;
4+
35
public interface ICellState {
46
int getPeriod();
5-
void scheduleTimer(Runnable runnable);
6-
void setRunnable(Runnable runnable);
7+
void setTimerTask(TimerTask timerTask);
78
void updatePeriod(int period);
89
void cancelTimer();
910
void resumeTimer();

app/src/main/java/com/softartdev/conwaysgameoflife/ui/CellLayout.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package com.softartdev.conwaysgameoflife.ui
33
import android.content.Context
44
import android.util.AttributeSet
55
import android.view.View
6-
import android.view.View.OnClickListener
76
import android.widget.GridLayout
87
import com.softartdev.conwaysgameoflife.model.CellState.LIFE_SIZE
98

app/src/main/java/com/softartdev/conwaysgameoflife/ui/MainActivity.kt

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import android.view.Menu
1111
import android.view.MenuItem
1212
import android.widget.SeekBar
1313
import androidx.activity.enableEdgeToEdge
14+
import androidx.activity.result.ActivityResultLauncher
1415
import androidx.activity.result.contract.ActivityResultContracts
1516
import androidx.appcompat.app.AlertDialog
1617
import androidx.appcompat.app.AppCompatActivity
@@ -25,10 +26,13 @@ import com.softartdev.conwaysgameoflife.model.CellState
2526
import com.softartdev.conwaysgameoflife.model.ICellState
2627

2728
class MainActivity : AppCompatActivity() {
28-
29-
private lateinit var binding: ActivityMainBinding
30-
3129
private val iCellState: ICellState = CellState.getInstance()
30+
private val activityResultLauncher: ActivityResultLauncher<String?> = registerForActivityResult(
31+
ActivityResultContracts.RequestPermission(),
32+
this@MainActivity::onPermResult
33+
)
34+
private var toggle: Boolean = false // To start game after permission granted
35+
private lateinit var binding: ActivityMainBinding
3236

3337
override fun onCreate(savedInstanceState: Bundle?) {
3438
super.onCreate(savedInstanceState)
@@ -46,7 +50,8 @@ class MainActivity : AppCompatActivity() {
4650
}
4751
updateStartButtonText()
4852
binding.mainStartButton.setOnClickListener {
49-
if (checkNotificationPermissionGranted(toggle = true)) toggleGame()
53+
toggle = true
54+
if (checkNotificationPermissionGranted()) toggleGame()
5055
}
5156
binding.mainStepButton.setOnClickListener {
5257
val processed = iCellState.processNextGeneration() ?: return@setOnClickListener
@@ -96,26 +101,29 @@ class MainActivity : AppCompatActivity() {
96101
}
97102
}
98103

99-
private fun checkNotificationPermissionGranted(toggle: Boolean = false): Boolean = when {
104+
private fun checkNotificationPermissionGranted(): Boolean = when {
100105
Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU -> when {
101106
ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED -> true
102107
ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.POST_NOTIFICATIONS) -> {
103108
showNotificationPermissionExplanation()
104109
false
105110
}
106111
else -> {
107-
registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted: Boolean ->
108-
when {
109-
isGranted -> if (toggle) toggleGame()
110-
else -> showNotificationPermissionExplanation()
111-
}
112-
}.launch(Manifest.permission.POST_NOTIFICATIONS)
112+
activityResultLauncher.launch(Manifest.permission.POST_NOTIFICATIONS)
113113
false
114114
}
115115
}
116116
else -> true
117117
}
118118

119+
private fun onPermResult(isGranted: Boolean) = when {
120+
isGranted -> {
121+
if (toggle) toggleGame()
122+
toggle = false
123+
}
124+
else -> showNotificationPermissionExplanation()
125+
}
126+
119127
private fun toggleGame() {
120128
with(iCellState) { if (toggleGoNextGeneration()) cancelTimer() else resumeTimer() }
121129
updateStartButtonText()

app/src/main/java/com/softartdev/conwaysgameoflife/ui/MainServiceConnection.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import android.content.ComponentName
44
import android.content.ServiceConnection
55
import android.os.IBinder
66
import com.softartdev.conwaysgameoflife.MainService
7-
import com.softartdev.conwaysgameoflife.model.ICellState
87

98
object MainServiceConnection : ServiceConnection {
109

app/src/main/res/values/colors.xml

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,2 @@
11
<?xml version="1.0" encoding="utf-8"?>
2-
<resources>
3-
<color name="colorPrimary">#3F51B5</color>
4-
<color name="colorPrimaryDark">#303F9F</color>
5-
<color name="colorAccent">#FF4081</color>
6-
</resources>
2+
<resources />

app/src/main/res/values/strings.xml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,12 @@
66
<string name="random">Randomize</string>
77
<string name="clean">Clean</string>
88
<string name="rules_title">Rules</string>
9-
<string name="rules_text">
10-
\n- Any live cell with fewer than 2 live neighbours dies, as if caused by under-population.
11-
\n- Any live cell with more than 3 live neighbours dies, as if by over-population.
12-
\n- Any live cell with 2 or 3 live neighbours lives on to the next generation.
13-
\n- Any dead cell with exactly 3 live neighbours becomes a live cell, as if by reproduction.</string>
9+
<string name="rules_text"><![CDATA[
10+
• Any live cell with fewer than 2 live neighbours dies, as if caused by under-population.\n
11+
• Any live cell with more than 3 live neighbours dies, as if by over-population.\n
12+
• Any live cell with 2 or 3 live neighbours lives on to the next generation.\n
13+
• Any dead cell with exactly 3 live neighbours becomes a live cell, as if by reproduction.
14+
]]></string>
1415
<string name="steps">Steps: %1$d</string>
1516
<string name="notification_channel_id">conway_channel</string>
1617
<string name="notification_channel_name">Game notification channel</string>

0 commit comments

Comments
 (0)