У меня есть служба переднего плана с двумя таймерами. Я хотел бы, чтобы таймер номер 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
Служба переднего плана с двумя таймерами и двойным уведомлением ⇐ Android
Форум для тех, кто программирует под Android
-
Anonymous
1761781411
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
}
}
Подробнее здесь: [url]https://stackoverflow.com/questions/79804225/foreground-service-with-two-timers-and-double-notification[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия