Служба переднего плана с двумя таймерами и двойным уведомлениемAndroid

Форум для тех, кто программирует под Android
Ответить
Anonymous
 Служба переднего плана с двумя таймерами и двойным уведомлением

Сообщение Anonymous »

У меня есть служба переднего плана с двумя таймерами. Я хотел бы, чтобы таймер номер 2 запускался, когда таймер 1 приостанавливается, и я хотел бы, чтобы таймер номер 1 возобновлял работу, когда таймер номер 2 остановлен. Кроме того, я хотел бы отображать состояние таймера № 2 под состоянием таймера № 1 в одном уведомлении. Как я могу добиться такого поведения? На данный момент таймер номер 1 очищается при запуске таймера номер 2, и в уведомлении отображается состояние таймера номер 1 и 2 взаимозаменяемо.
Это код, который я использую:
class StopwatchService: Service() {
@Inject
lateinit var notificationManager: NotificationManager

@Inject
lateinit var notificationBuilder: NotificationCompat.Builder

@Inject
lateinit var activityRepository: IActivitiesRepository

private val binder = StopwatchBinder()

private val job = SupervisorJob()
private val scope = CoroutineScope(Dispatchers.IO + job)

private var duration: Duration = Duration.ZERO
private var subDuration: Duration = Duration.ZERO
private lateinit var timer: Timer
private lateinit var subTimer: Timer

var seconds = mutableIntStateOf(0)
private set
var minutes = mutableIntStateOf(0)
private set
var hours = mutableIntStateOf(0)
private set
var subSeconds = mutableIntStateOf(0)
private set
var subMinutes = mutableIntStateOf(0)
private set
var subHours = mutableIntStateOf(0)
private set
var currentState = mutableStateOf(StopwatchState.Main)
private set

private fun createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val notificationChannel = NotificationChannel(
NOTIFICATION_CHANNEL_ID,
NOTIFICATION_CHANNEL_NAME,
NotificationManager.IMPORTANCE_HIGH
)
notificationChannel.setSound(null, null)
notificationChannel.setShowBadge(true)
val notificationManager = getSystemService(NotificationManager::class.java)
notificationManager.createNotificationChannel(notificationChannel)
}
}

private fun getNotificationManager() {
notificationManager = ContextCompat.getSystemService(
this,
NotificationManager::class.java,
) as NotificationManager
}

override fun onBind(intent: Intent?) = binder

override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
Thread(Runnable {
createNotificationChannel()
getNotificationManager()

intent?.action.let {
when (it) {
START -> startStopwatch { hours, minutes, seconds ->
updateNotification(hours = hours, minutes = minutes, seconds = seconds)
}
PAUSE -> pauseStopwatch({ hours, minutes, seconds ->
updateNotification(hours = hours, minutes = minutes, seconds = seconds)
})
RESUME -> resumeStopwatch({ hours, minutes, seconds ->
updateNotification(hours = hours, minutes = minutes, seconds = seconds)
})
STOP -> stopStopwatch()
}
}
}).start()

return super.onStartCommand(intent, flags, startId)
}

private fun resumeStopwatch(onTick: (hr: String, min: String, sec: String) -> Unit) {
if (this::subTimer.isInitialized) subTimer.cancel()
currentState.value = StopwatchState.Main
// Start the main timer again
timer = fixedRateTimer(initialDelay = 1000L, period = 1000L) {
duration = duration.plus(1.
seconds)
updateTimeUnits()
onTick(
hours.value.pad(),
minutes.value.pad(),
seconds.value.pad()
)
}
}

private fun pauseStopwatch(onTick: (hr: String, min: String, sec: String) -> Unit) {
if (this::timer.isInitialized) timer.cancel()
currentState.value = StopwatchState.Sub
// Start the sub-timer
subTimer = fixedRateTimer(initialDelay = 1000L, period = 1000L) {
subDuration = subDuration.plus(1.
seconds)
updateTimeUnits()
onTick(
subHours.value.pad(),
subMinutes.value.pad(),
subSeconds.value.pad()
)
}
}

@SuppressLint("ForegroundServiceType")
private fun startForegroundService() {
createNotificationChannel()
startForeground(NOTIFICATION_ID, notificationBuilder.build())
}

private fun startStopwatch(onTick: (hr: String, min: String, sec: String) -> Unit) {
timer = fixedRateTimer(initialDelay = 1000L, period = 1000L) {
duration = duration.plus(1.seconds)
updateTimeUnits()
onTick(
hours.value.pad(),
minutes.value.pad(),
seconds.value.pad()
)
}
}

private fun stopForegroundService() {
notificationManager.cancel(NOTIFICATION_ID)
stopForeground(STOP_FOREGROUND_REMOVE)
// Cancel coroutines
job.cancel()
// Stop the service
stopSelf()
}

private fun stopStopwatch() {
duration = Duration.ZERO
currentState.value = StopwatchState.Main
stopForegroundService()
}

private fun updateNotification(hours: String, minutes: String, seconds: String) {
notificationManager.notify(
NOTIFICATION_ID, notificationBuilder.setContentText(
formatTime(
hours = hours,
minutes = minutes,
seconds = seconds
)
).build()
)
}

private fun updateTimeUnits() {
when (currentState.value) {
StopwatchState.Main -> duration.toComponents { hours, minutes, seconds, _ ->
this@StopwatchService.hours.value = hours.toInt()
this@StopwatchService.minutes.value = minutes
this@StopwatchService.seconds.value = seconds
}
StopwatchState.Sub -> subDuration.toComponents { hours, minutes, seconds, _ ->
this@StopwatchService.subHours.value = hours.toInt()
this@StopwatchService.subMinutes.value = minutes
this@StopwatchService.subSeconds.value = seconds
}
}

}

inner class StopwatchBinder : Binder() {
fun getService(): StopwatchService = this@StopwatchService
}
}

@Module
@InstallIn(ServiceComponent::class)
// Updates and modifies the notification along the stopwatch
object NotificationModule {
@ServiceScoped
@Provides
fun provideNotificationBuilder(@ApplicationContext context: Context): NotificationCompat.Builder {
return NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_ID)
.setContentTitle("Activity")
.setContentText("00:00:00")
.setSmallIcon(R.drawable.calendar_success_svgrepo_com)
.setOngoing(true)
.setContentIntent(ServiceHelper.clickPendingIntent(context))
}

@ServiceScoped
@Provides
fun provideNotificationManager(@ApplicationContext context: Context): NotificationManager {
return context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
}
}


Подробнее здесь: https://stackoverflow.com/questions/798 ... tification
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Android»