Remove EventBus usage

This commit is contained in:
Ensar Sarajčić 2023-10-02 18:24:02 +02:00
parent 163e053e1d
commit ee9a539cf5
10 changed files with 143 additions and 221 deletions

View File

@ -105,8 +105,6 @@ android {
dependencies {
implementation(libs.simple.tools.commons)
implementation(libs.androidx.constraintlayout)
implementation(libs.eventbus)
implementation(libs.bundles.lifecycle)
implementation(libs.bundles.compose)
debugImplementation(libs.bundles.compose.preview)

View File

@ -1,6 +0,0 @@
# EventBus
-keepattributes *Annotation*
-keepclassmembers class ** {
@org.greenrobot.eventbus.Subscribe <methods>;
}
-keep enum org.greenrobot.eventbus.ThreadMode { *; }

View File

@ -12,20 +12,20 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewModelScope
import com.simplemobiletools.commons.compose.extensions.enableEdgeToEdgeSimple
import com.simplemobiletools.commons.compose.theme.AppThemeSurface
import com.simplemobiletools.commons.dialogs.ColorPickerDialog
import com.simplemobiletools.commons.extensions.getContrastColor
import com.simplemobiletools.commons.extensions.getFormattedDuration
import com.simplemobiletools.flashlight.extensions.config
import com.simplemobiletools.flashlight.helpers.SleepTimer
import com.simplemobiletools.flashlight.helpers.stopSleepTimerCountDown
import com.simplemobiletools.flashlight.models.Events
import com.simplemobiletools.flashlight.screens.BrightDisplayScreen
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlin.system.exitProcess
class BrightDisplayActivity : ComponentActivity() {
@ -113,17 +113,16 @@ class BrightDisplayActivity : ComponentActivity() {
val backgroundColor = _backgroundColor.asStateFlow()
init {
EventBus.getDefault().register(this)
}
SleepTimer.timeLeft
.onEach { seconds ->
_timerText.value = seconds.getFormattedDuration()
_timerVisible.value = true
@Subscribe(threadMode = ThreadMode.MAIN)
fun sleepTimerChanged(event: Events.SleepTimerChanged) {
_timerText.value = event.seconds.getFormattedDuration()
_timerVisible.value = true
if (event.seconds == 0) {
exitProcess(0)
}
if (seconds == 0) {
exitProcess(0)
}
}
.launchIn(viewModelScope)
}
fun updateBackgroundColor(color: Int) {
@ -133,10 +132,5 @@ class BrightDisplayActivity : ComponentActivity() {
fun hideTimer() {
_timerVisible.value = false
}
override fun onCleared() {
super.onCleared()
EventBus.getDefault().unregister(this)
}
}
}

View File

@ -23,6 +23,7 @@ import androidx.core.content.ContextCompat
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewModelScope
import com.google.android.material.math.MathUtils
import com.simplemobiletools.commons.compose.extensions.onEventValue
import com.simplemobiletools.commons.compose.theme.AppThemeSurface
@ -39,14 +40,8 @@ import com.simplemobiletools.flashlight.dialogs.SleepTimerCustomDialog
import com.simplemobiletools.flashlight.extensions.config
import com.simplemobiletools.flashlight.extensions.startAboutActivity
import com.simplemobiletools.flashlight.helpers.*
import com.simplemobiletools.flashlight.models.Events
import com.simplemobiletools.flashlight.screens.MainScreen
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.map
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import kotlinx.coroutines.flow.*
import java.util.*
import kotlin.system.exitProcess
@ -173,8 +168,6 @@ class MainActivity : ComponentActivity() {
}
private fun launchAbout() {
val licenses = LICENSE_EVENT_BUS
val faqItems = arrayListOf(
FAQItem(R.string.faq_1_title_commons, R.string.faq_1_text_commons),
FAQItem(R.string.faq_4_title_commons, R.string.faq_4_text_commons)
@ -185,7 +178,7 @@ class MainActivity : ComponentActivity() {
faqItems.add(FAQItem(R.string.faq_6_title_commons, R.string.faq_6_text_commons))
}
startAboutActivity(R.string.app_name, licenses, BuildConfig.VERSION_NAME, faqItems, true)
startAboutActivity(R.string.app_name, 0, BuildConfig.VERSION_NAME, faqItems, true)
}
private fun checkAppOnSDCard() {
@ -323,14 +316,33 @@ class MainActivity : ComponentActivity() {
private val preferences = application.config
private lateinit var camera: MyCameraImpl
init {
camera = MyCameraImpl.newInstance(application, object : CameraTorchListener {
override fun onTorchEnabled(isEnabled: Boolean) {
camera.onTorchEnabled(isEnabled)
if (isEnabled && camera.supportsBrightnessControl()) {
_brightnessBarValue.value = camera.getCurrentBrightnessLevel().toFloat() / camera.getMaximumBrightnessLevel()
}
}
override fun onTorchUnavailable() {
camera.onCameraNotAvailable()
}
})
if (preferences.turnFlashlightOn) {
camera.enableFlashlight()
}
}
private val _timerText: MutableStateFlow<String> = MutableStateFlow("00:00")
val timerText = _timerText.asStateFlow()
private val _timerVisible: MutableStateFlow<Boolean> = MutableStateFlow(false)
val timerVisible = _timerVisible.asStateFlow()
private val _flashlightOn: MutableStateFlow<Boolean> = MutableStateFlow(false)
val flashlightOn = _flashlightOn.asStateFlow()
val flashlightOn = camera.flashlightOnFlow
val brightnessBarVisible = flashlightOn.map {
it && camera.supportsBrightnessControl()
@ -350,38 +362,31 @@ class MainActivity : ComponentActivity() {
private val _stroboscopeBarValue: MutableStateFlow<Float> = MutableStateFlow(0f)
val stroboscopeBarValue = _stroboscopeBarValue.asStateFlow()
private lateinit var camera: MyCameraImpl
init {
EventBus.getDefault().register(this)
_stroboscopeBarValue.value = preferences.stroboscopeProgress.toFloat() / MAX_STROBO_DELAY
camera = MyCameraImpl.newInstance(application, object : CameraTorchListener {
override fun onTorchEnabled(isEnabled: Boolean) {
camera.onTorchEnabled(isEnabled)
if (isEnabled && camera.supportsBrightnessControl()) {
_brightnessBarValue.value = camera.getCurrentBrightnessLevel().toFloat() / camera.getMaximumBrightnessLevel()
SleepTimer.timeLeft
.onEach { seconds ->
_timerText.value = seconds.getFormattedDuration()
_timerVisible.value = true
if (seconds == 0) {
exitProcess(0)
}
}
.launchIn(viewModelScope)
override fun onTorchUnavailable() {
camera.onCameraNotAvailable()
}
})
if (preferences.turnFlashlightOn) {
camera.enableFlashlight()
}
MyCameraImpl.cameraError
.onEach { getApplication<Application>().toast(R.string.camera_error) }
.launchIn(viewModelScope)
_stroboscopeBarValue.value = preferences.stroboscopeProgress.toFloat() / MAX_STROBO_DELAY
}
camera.stroboscopeDisabled
.onEach { _stroboscopeActive.value = false }
.launchIn(viewModelScope)
@Subscribe(threadMode = ThreadMode.MAIN)
fun sleepTimerChanged(event: Events.SleepTimerChanged) {
_timerText.value = event.seconds.getFormattedDuration()
_timerVisible.value = true
if (event.seconds == 0) {
exitProcess(0)
}
camera.sosDisabled
.onEach { _sosActive.value = false }
.launchIn(viewModelScope)
}
fun hideTimer() {
@ -412,7 +417,6 @@ class MainActivity : ComponentActivity() {
}
fun onResume() {
checkState(MyCameraImpl.isFlashlightOn)
camera.handleCameraSetup()
if (preferences.turnFlashlightOn) {
@ -428,34 +432,8 @@ class MainActivity : ComponentActivity() {
}
}
private fun checkState(isEnabled: Boolean) {
_flashlightOn.value = isEnabled
}
@Subscribe
fun stateChangedEvent(event: Events.StateChanged) {
checkState(event.isEnabled)
}
@Subscribe
fun stopStroboscope(event: Events.StopStroboscope) {
_stroboscopeActive.value = false
}
@Subscribe
fun stopSOS(event: Events.StopSOS) {
_sosActive.value = false
}
@Subscribe
fun cameraUnavailable(event: Events.CameraUnavailable) {
getApplication<Application>().toast(R.string.camera_error)
_flashlightOn.value = false
}
override fun onCleared() {
super.onCleared()
EventBus.getDefault().unregister(this)
releaseCamera()
}

View File

@ -7,8 +7,9 @@ import android.os.Handler
import com.simplemobiletools.commons.extensions.showErrorToast
import com.simplemobiletools.commons.helpers.isTiramisuPlus
import com.simplemobiletools.flashlight.extensions.config
import com.simplemobiletools.flashlight.models.Events
import org.greenrobot.eventbus.EventBus
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
internal class CameraFlash(
private val context: Context,
@ -17,6 +18,8 @@ internal class CameraFlash(
private val manager = context.getSystemService(Context.CAMERA_SERVICE) as CameraManager
private val cameraId: String
private val scope = CoroutineScope(Dispatchers.Default)
private val torchCallback = object : CameraManager.TorchCallback() {
override fun onTorchModeChanged(cameraId: String, enabled: Boolean) {
cameraTorchListener?.onTorchEnabled(enabled)
@ -46,10 +49,9 @@ internal class CameraFlash(
}
} catch (e: Exception) {
context.showErrorToast(e)
val mainRunnable = Runnable {
EventBus.getDefault().post(Events.CameraUnavailable())
scope.launch {
MyCameraImpl.cameraError.emit(Unit)
}
Handler(context.mainLooper).post(mainRunnable)
}
}

View File

@ -7,8 +7,13 @@ import com.simplemobiletools.commons.extensions.toast
import com.simplemobiletools.flashlight.R
import com.simplemobiletools.flashlight.extensions.config
import com.simplemobiletools.flashlight.extensions.updateWidgets
import com.simplemobiletools.flashlight.models.Events
import org.greenrobot.eventbus.EventBus
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
class MyCameraImpl private constructor(val context: Context, private var cameraTorchListener: CameraTorchListener? = null) {
var stroboFrequency = 1000L
@ -35,9 +40,13 @@ class MyCameraImpl private constructor(val context: Context, private var cameraT
@Volatile
private var isSOSRunning = false
val cameraError = MutableSharedFlow<Unit>()
fun newInstance(context: Context, cameraTorchListener: CameraTorchListener? = null) = MyCameraImpl(context, cameraTorchListener)
}
private val scope = CoroutineScope(Dispatchers.Default)
private val cameraFlash: CameraFlash?
get() {
if (MyCameraImpl.cameraFlash == null) {
@ -51,6 +60,15 @@ class MyCameraImpl private constructor(val context: Context, private var cameraT
stroboFrequency = context.config.stroboscopeFrequency
}
private val _flashlightOn = MutableStateFlow(false)
val flashlightOnFlow = _flashlightOn.asStateFlow()
private val _sosDisabled = MutableSharedFlow<Unit>()
val sosDisabled = _sosDisabled.asSharedFlow()
private val _stroboscopeDisabled = MutableSharedFlow<Unit>()
val stroboscopeDisabled = _stroboscopeDisabled.asSharedFlow()
fun toggleFlashlight() {
isFlashlightOn = !isFlashlightOn
checkFlashlight()
@ -89,7 +107,9 @@ class MyCameraImpl private constructor(val context: Context, private var cameraT
fun stopStroboscope() {
shouldStroboscopeStop = true
EventBus.getDefault().post(Events.StopStroboscope())
scope.launch {
_stroboscopeDisabled.emit(Unit)
}
}
fun toggleSOS(): Boolean {
@ -129,7 +149,9 @@ class MyCameraImpl private constructor(val context: Context, private var cameraT
fun stopSOS() {
shouldStroboscopeStop = true
EventBus.getDefault().post(Events.StopSOS())
scope.launch {
_sosDisabled.emit(Unit)
}
}
private fun tryInitCamera(): Boolean {
@ -146,8 +168,13 @@ class MyCameraImpl private constructor(val context: Context, private var cameraT
if (MyCameraImpl.cameraFlash == null) {
MyCameraImpl.cameraFlash = CameraFlash(context, cameraTorchListener)
}
scope.launch {
_flashlightOn.emit(isFlashlightOn)
}
} catch (e: Exception) {
EventBus.getDefault().post(Events.CameraUnavailable())
scope.launch {
cameraError.emit(Unit)
}
}
}
@ -209,7 +236,9 @@ class MyCameraImpl private constructor(val context: Context, private var cameraT
private fun stateChanged(isEnabled: Boolean) {
isFlashlightOn = isEnabled
EventBus.getDefault().post(Events.StateChanged(isEnabled))
scope.launch {
_flashlightOn.emit(isEnabled)
}
context.updateWidgets(isEnabled)
}
@ -276,10 +305,14 @@ class MyCameraImpl private constructor(val context: Context, private var cameraT
shouldStroboscopeStop = false
if (isStroboSOS) {
isSOSRunning = false
EventBus.getDefault().post(Events.StopSOS())
scope.launch {
_sosDisabled.emit(Unit)
}
} else {
isStroboscopeRunning = false
EventBus.getDefault().post(Events.StopStroboscope())
scope.launch {
_stroboscopeDisabled.emit(Unit)
}
}
when {

View File

@ -7,23 +7,51 @@ import android.content.Intent
import android.os.CountDownTimer
import com.simplemobiletools.commons.helpers.isSPlus
import com.simplemobiletools.flashlight.extensions.config
import com.simplemobiletools.flashlight.models.Events
import org.greenrobot.eventbus.EventBus
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.launch
import kotlin.system.exitProcess
private var isActive = false
private var sleepTimer: CountDownTimer? = null
object SleepTimer {
private var sleepTimer: CountDownTimer? = null
private val _timeLeft = MutableSharedFlow<Int>()
val timeLeft = _timeLeft.asSharedFlow()
private val scope = CoroutineScope(Dispatchers.Default)
internal fun Context.toggleSleepTimer() {
if (isActive) {
stopSleepTimerCountDown()
} else {
startSleepTimerCountDown()
fun cancel() {
sleepTimer?.cancel()
sleepTimer = null
}
context(Context)
fun startTimer() {
val millisInFuture = config.sleepInTS - System.currentTimeMillis() + 1000L
sleepTimer?.cancel()
sleepTimer = object : CountDownTimer(millisInFuture, 1000) {
override fun onTick(millisUntilFinished: Long) {
val seconds = (millisUntilFinished / 1000).toInt()
scope.launch {
_timeLeft.emit(seconds)
}
}
override fun onFinish() {
config.sleepInTS = 0
scope.launch {
_timeLeft.emit(0)
}
stopSleepTimerCountDown()
exitProcess(0)
}
}
sleepTimer?.start()
}
}
internal fun Context.startSleepTimerCountDown() {
val millisInFuture = config.sleepInTS - System.currentTimeMillis() + 1000L
(getSystemService(Context.ALARM_SERVICE) as AlarmManager).apply {
if (!isSPlus() || canScheduleExactAlarms()) {
setExactAndAllowWhileIdle(
@ -39,30 +67,12 @@ internal fun Context.startSleepTimerCountDown() {
)
}
}
sleepTimer?.cancel()
sleepTimer = object : CountDownTimer(millisInFuture, 1000) {
override fun onTick(millisUntilFinished: Long) {
val seconds = (millisUntilFinished / 1000).toInt()
EventBus.getDefault().post(Events.SleepTimerChanged(seconds))
}
override fun onFinish() {
config.sleepInTS = 0
EventBus.getDefault().post(Events.SleepTimerChanged(0))
stopSleepTimerCountDown()
exitProcess(0)
}
}
sleepTimer?.start()
isActive = true
SleepTimer.startTimer()
}
internal fun Context.stopSleepTimerCountDown() {
(getSystemService(Context.ALARM_SERVICE) as AlarmManager).cancel(getShutDownPendingIntent())
sleepTimer?.cancel()
sleepTimer = null
isActive = false
SleepTimer.cancel()
config.sleepInTS = 0
}

View File

@ -1,13 +0,0 @@
package com.simplemobiletools.flashlight.models
class Events {
class StateChanged(val isEnabled: Boolean)
class CameraUnavailable
class StopStroboscope
class StopSOS
class SleepTimerChanged(val seconds: Int)
}

View File

@ -1,68 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/config_torch_coordinator"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:id="@+id/config_torch_holder"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_margin="@dimen/activity_margin">
<RelativeLayout
android:id="@+id/config_torch_wrapper"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/config_widget_color"
android:layout_marginBottom="@dimen/activity_margin"
android:gravity="center">
<ImageView
android:id="@+id/config_image"
android:layout_width="@dimen/main_button_size"
android:layout_height="@dimen/main_button_size"
android:background="@drawable/ic_flashlight_vector" />
</RelativeLayout>
<ImageView
android:id="@+id/config_widget_color"
android:layout_width="@dimen/widget_colorpicker_size"
android:layout_height="@dimen/widget_colorpicker_size"
android:layout_above="@+id/config_save"
android:layout_margin="@dimen/tiny_margin" />
<RelativeLayout
android:id="@+id/config_widget_seekbar_holder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignTop="@+id/config_widget_color"
android:layout_alignBottom="@+id/config_widget_color"
android:layout_marginStart="@dimen/medium_margin"
android:layout_toEndOf="@+id/config_widget_color"
android:background="@drawable/widget_config_seekbar_background">
<com.simplemobiletools.commons.views.MySeekBar
android:id="@+id/config_widget_seekbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:paddingStart="@dimen/activity_margin"
android:paddingEnd="@dimen/activity_margin" />
</RelativeLayout>
<Button
android:id="@+id/config_save"
style="@style/MyWidgetConfigSaveStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:layout_marginTop="@dimen/tiny_margin"
android:text="@string/ok" />
</RelativeLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -2,12 +2,9 @@
#jetbrains
kotlin = "1.9.10"
#AndroidX
androidx-constraintlayout = "2.1.4"
androidx-customView = "1.2.0-alpha02"
androidx-customViewPooling = "1.0.0"
androidx-lifecycle = "2.7.0-alpha02"
#EventBus
eventbusVersion = "3.3.1"
#Simple tools
simple-commons = "b7dd6ad428"
#Compose
@ -29,7 +26,6 @@ app-version-versionCode = "65"
app-version-versionName = "5.10.0"
[libraries]
#AndroidX
androidx-constraintlayout = { module = "androidx.constraintlayout:constraintlayout", version.ref = "androidx-constraintlayout" }
androidx-customView = { module = "androidx.customview:customview", version.ref = "androidx-customView" }
androidx-customViewPooling = { module = "androidx.customview:customview-poolingcontainer", version.ref = "androidx-customViewPooling" }
#Android X lifecycle
@ -37,8 +33,6 @@ androidx-lifecycle-runtime = { module = "androidx.lifecycle:lifecycle-runtime-kt
androidx-lifecycle-viewModel = { module = "androidx.lifecycle:lifecycle-viewmodel-ktx", version.ref = "androidx-lifecycle" }
androidx-lifecycle-viewModel-compose = { module = "androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "androidx-lifecycle" }
androidx-lifecycle-compose = { module = "androidx.lifecycle:lifecycle-runtime-compose", version.ref = "androidx-lifecycle" }
#EventBus
eventbus = { module = "org.greenrobot:eventbus", version.ref = "eventbusVersion" }
#Simple Mobile Tools
simple-tools-commons = { module = "com.github.SimpleMobileTools:Simple-Commons", version.ref = "simple-commons" }
#Compose