Skip to content

Commit bbee699

Browse files
committed
Improve managers to use instances and improve context handling
1 parent 5957eae commit bbee699

34 files changed

+477
-434
lines changed

app/src/main/java/com/wstxda/toolkit/base/BaseTileService.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import android.app.PendingIntent
55
import android.content.Intent
66
import android.os.Build
77
import android.service.quicksettings.TileService
8+
import androidx.annotation.CallSuper
89
import kotlinx.coroutines.CoroutineScope
910
import kotlinx.coroutines.Dispatchers
1011
import kotlinx.coroutines.SupervisorJob
@@ -14,11 +15,13 @@ abstract class BaseTileService : TileService() {
1415

1516
protected val serviceScope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
1617

18+
@CallSuper
1719
override fun onStartListening() {
1820
super.onStartListening()
1921
updateTile()
2022
}
2123

24+
@CallSuper
2225
override fun onDestroy() {
2326
super.onDestroy()
2427
serviceScope.cancel()

app/src/main/java/com/wstxda/toolkit/manager/audio/SoundModeManager.kt

Lines changed: 44 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -7,71 +7,77 @@ import android.content.Intent
77
import android.content.IntentFilter
88
import android.media.AudioManager
99
import android.os.Build
10-
import kotlinx.coroutines.flow.MutableStateFlow
11-
import kotlinx.coroutines.flow.asStateFlow
10+
import kotlinx.coroutines.CoroutineScope
11+
import kotlinx.coroutines.Dispatchers
12+
import kotlinx.coroutines.SupervisorJob
13+
import kotlinx.coroutines.cancel
14+
import kotlinx.coroutines.channels.awaitClose
15+
import kotlinx.coroutines.flow.Flow
16+
import kotlinx.coroutines.flow.callbackFlow
17+
import kotlinx.coroutines.flow.distinctUntilChanged
18+
import kotlinx.coroutines.launch
1219

13-
object SoundModeManager {
20+
class SoundModeManager(private val context: Context) {
1421

15-
private lateinit var audioManager: AudioManager
16-
private lateinit var notificationManager: NotificationManager
22+
private val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
23+
private val notificationManager =
24+
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
25+
private val managerScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
1726

18-
private val _currentMode = MutableStateFlow(SoundMode.NORMAL)
19-
val currentMode = _currentMode.asStateFlow()
27+
val currentModeFlow: Flow<SoundMode> = callbackFlow {
28+
trySend(getCurrentModeInternal())
2029

21-
private val ringerModeReceiver = object : BroadcastReceiver() {
22-
override fun onReceive(context: Context, intent: Intent) {
23-
if (intent.action == AudioManager.RINGER_MODE_CHANGED_ACTION) {
24-
_currentMode.value = getCurrentModeInternal()
30+
val receiver = object : BroadcastReceiver() {
31+
override fun onReceive(context: Context, intent: Intent) {
32+
if (intent.action == AudioManager.RINGER_MODE_CHANGED_ACTION) {
33+
trySend(getCurrentModeInternal())
34+
}
2535
}
2636
}
27-
}
28-
29-
fun init(context: Context) {
30-
audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
31-
notificationManager =
32-
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
33-
34-
_currentMode.value = getCurrentModeInternal()
3537

3638
context.registerReceiver(
37-
ringerModeReceiver,
39+
receiver,
3840
IntentFilter(AudioManager.RINGER_MODE_CHANGED_ACTION),
3941
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
4042
Context.RECEIVER_NOT_EXPORTED
4143
} else 0
4244
)
43-
}
45+
46+
awaitClose {
47+
try {
48+
context.unregisterReceiver(receiver)
49+
} catch (_: IllegalArgumentException) {
50+
}
51+
}
52+
}.distinctUntilChanged()
4453

4554
fun hasPermission(): Boolean {
46-
return if (::notificationManager.isInitialized) {
47-
notificationManager.isNotificationPolicyAccessGranted
48-
} else false
55+
return notificationManager.isNotificationPolicyAccessGranted
4956
}
5057

5158
fun cycleMode() {
5259
if (!hasPermission()) return
5360

54-
val newMode = when (_currentMode.value) {
55-
SoundMode.NORMAL -> SoundMode.VIBRATE
56-
SoundMode.VIBRATE -> SoundMode.SILENT
57-
SoundMode.SILENT -> SoundMode.NORMAL
61+
managerScope.launch {
62+
val current = getCurrentModeInternal()
63+
val newMode = when (current) {
64+
SoundMode.NORMAL -> SoundMode.VIBRATE
65+
SoundMode.VIBRATE -> SoundMode.SILENT
66+
SoundMode.SILENT -> SoundMode.NORMAL
67+
}
68+
audioManager.ringerMode = newMode.ringerMode
5869
}
59-
audioManager.ringerMode = newMode.ringerMode
6070
}
6171

62-
private fun getCurrentModeInternal(): SoundMode {
63-
if (!::audioManager.isInitialized) return SoundMode.NORMAL
72+
fun cleanup() {
73+
managerScope.cancel()
74+
}
75+
76+
fun getCurrentModeInternal(): SoundMode {
6477
return when (audioManager.ringerMode) {
6578
AudioManager.RINGER_MODE_VIBRATE -> SoundMode.VIBRATE
6679
AudioManager.RINGER_MODE_SILENT -> SoundMode.SILENT
6780
else -> SoundMode.NORMAL
6881
}
6982
}
70-
71-
fun unregisterReceiver(context: Context) {
72-
try {
73-
context.unregisterReceiver(ringerModeReceiver)
74-
} catch (_: IllegalArgumentException) {
75-
}
76-
}
7783
}

app/src/main/java/com/wstxda/toolkit/manager/counter/CounterManager.kt

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,33 +7,39 @@ import androidx.core.content.edit
77
import com.wstxda.toolkit.tiles.counter.CounterAddTileService
88
import com.wstxda.toolkit.tiles.counter.CounterRemoveTileService
99
import com.wstxda.toolkit.tiles.counter.CounterResetTileService
10+
import kotlinx.coroutines.CoroutineScope
11+
import kotlinx.coroutines.Dispatchers
12+
import kotlinx.coroutines.SupervisorJob
1013
import kotlinx.coroutines.flow.MutableStateFlow
1114
import kotlinx.coroutines.flow.asStateFlow
15+
import kotlinx.coroutines.launch
1216

13-
object CounterManager {
17+
class CounterManager(context: Context) {
1418

15-
private const val PREFS_NAME = "counter_prefs"
16-
private const val KEY_COUNT = "count"
17-
private const val KEY_ACTION = "last_action"
19+
companion object {
20+
private const val PREFS_NAME = "counter_prefs"
21+
private const val KEY_COUNT = "count"
22+
private const val KEY_ACTION = "last_action"
23+
}
1824

19-
private lateinit var appContext: Context
25+
private val appContext = context.applicationContext
26+
private val managerScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
2027

2128
private val _count = MutableStateFlow(0)
2229
val count = _count.asStateFlow()
2330

2431
private val _lastAction = MutableStateFlow(CounterAction.NONE)
2532
val lastAction = _lastAction.asStateFlow()
2633

27-
fun initialize(context: Context) {
28-
if (::appContext.isInitialized) return
29-
appContext = context.applicationContext
30-
31-
val prefs = getPrefs()
32-
_count.value = prefs.getInt(KEY_COUNT, 0)
34+
init {
35+
managerScope.launch {
36+
val prefs = getPrefs()
37+
_count.value = prefs.getInt(KEY_COUNT, 0)
3338

34-
val actionString = prefs.getString(KEY_ACTION, CounterAction.NONE.name)
35-
_lastAction.value =
36-
runCatching { CounterAction.valueOf(actionString!!) }.getOrDefault(CounterAction.NONE)
39+
val actionString = prefs.getString(KEY_ACTION, CounterAction.NONE.name)
40+
_lastAction.value =
41+
runCatching { CounterAction.valueOf(actionString!!) }.getOrDefault(CounterAction.NONE)
42+
}
3743
}
3844

3945
fun increment() {
@@ -55,15 +61,15 @@ object CounterManager {
5561
_count.value = newValue
5662
_lastAction.value = action
5763

58-
getPrefs().edit {
59-
putInt(KEY_COUNT, newValue)
60-
putString(KEY_ACTION, action.name)
64+
managerScope.launch {
65+
getPrefs().edit {
66+
putInt(KEY_COUNT, newValue)
67+
putString(KEY_ACTION, action.name)
68+
}
6169
}
6270
}
6371

6472
private fun refreshAllTiles() {
65-
if (!::appContext.isInitialized) return
66-
6773
val classes = listOf(
6874
CounterAddTileService::class.java,
6975
CounterRemoveTileService::class.java,
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.wstxda.toolkit.manager.counter
2+
3+
import android.content.Context
4+
5+
object CounterModule {
6+
@Volatile
7+
private var instance: CounterManager? = null
8+
9+
fun getInstance(context: Context): CounterManager {
10+
return instance ?: synchronized(this) {
11+
instance ?: CounterManager(context.applicationContext).also { instance = it }
12+
}
13+
}
14+
}

app/src/main/java/com/wstxda/toolkit/manager/games/CoinFlipManager.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package com.wstxda.toolkit.manager.games
22

33
import kotlin.random.Random
44

5-
object CoinFlipManager {
5+
class CoinFlipManager() {
66

77
var headsCount = 0
88
private set

app/src/main/java/com/wstxda/toolkit/manager/games/DiceRollManager.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package com.wstxda.toolkit.manager.games
22

33
import kotlin.random.Random
44

5-
object DiceRollManager {
5+
class DiceRollManager() {
66

77
fun roll(): Int {
88
return Random.nextInt(1, 7)

0 commit comments

Comments
 (0)