본문 바로가기
개인 프로젝트/운동일지 App

운동일지 App 문제 해결 #01

by 왕큰새 2022. 2. 17.
728x90

문제1. 백그라운드로  처음 갔을 때 알림이 바로 생성되지 않고 두번 정도 가야 생성이 되는 문제

 

문제2. 타이머를 일시 정지 시켰을 때 알림은 계속 시간이 가는 문제 

 

 

 

문제1. 해결

 

서비스를 수명주기가 ON_STOP 될 때 실행했었는데, 시작 버튼을 눌렀을 때 서비스가 실행되도록 하였다.

 

문제 해결 이전 코드

 @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    fun onAppBackgrounded() {
        val startIntent = Intent(requireActivity(), ForegroundService::class.java)
        startIntent.putExtra(COMMAND_ID, COMMAND_START)
        startIntent.putExtra(STARTED_TIMER_TIME_MS, startTime)
        activity?.startService(startIntent)
    }

 

문제 해결 이후 코드

 

fun onStartBackGroundTimer(time:Long) {
    val startIntent = Intent(requireContext(), ForegroundService::class.java)
    startIntent.putExtra(COMMAND_ID, COMMAND_START)
    startIntent.putExtra(STARTED_TIMER_TIME_MS, time)
    activity?.startService(startIntent)
}

 

문제2. 해결

 

일시정지 버튼을 눌렀을 때, 서비스를 정지시키고

타이머를 재시작하였을 때 재시작 시간으로 서비스를 시작시킨다.

 

fun onPauseTimer() {
    val stopIntent = Intent(requireContext(), ForegroundService::class.java)
    stopIntent.putExtra(COMMAND_ID, COMMAND_STOP)
    activity?.startService(stopIntent)
}

 

타이머 버튼 코드

 

startBtn.setOnClickListener {
    if(!isStart) {
        startTime = System.currentTimeMillis()
        onStartBackGroundTimer(startTime)
        startTimer(startTime)
        binding.startBtn.setImageResource(R.drawable.ic_baseline_pause_24)
    } else {
        if(isNotPaused) {
            onPauseTimer()
            pauseTimer()
            isNotPaused = !isNotPaused
            binding.startBtn.setImageResource(R.drawable.ic_baseline_play_arrow_24)
        } else {
            onStartBackGroundTimer(resumeTime)
            startTime = resumeTime
            startTimer(resumeTime)
            isNotPaused = !isNotPaused
            binding.startBtn.setImageResource(R.drawable.ic_baseline_pause_24)
        }
    }
}

 

 

서비스 코드

 

private fun processCommand(intent: Intent?) {
        when (intent?.extras?.getString(COMMAND_ID) ?: INVALID) {
            COMMAND_START -> {
                val startTime = intent?.extras?.getLong(STARTED_TIMER_TIME_MS) ?: return
                commandStart(startTime)
            }
            COMMAND_STOP -> commandStop()
            INVALID -> return
        }
    }


private fun commandStart(startTime: Long) {
    if (isServiceStarted) {
        return
    }
    Log.i("TAG", "commandStart()")
    try {
        moveToStartedState()
        startForegroundAndShowNotification()
        continueTimer(startTime)
    } finally {
        isServiceStarted = true
    }
}



private fun continueTimer(startTime: Long) {
    job = GlobalScope.launch(Dispatchers.Main) {
        while (true) {
            notificationManager?.notify(
                NOTIFICATION_ID,
                getNotification(
                    (System.currentTimeMillis() - startTime).displayTime().dropLast(3)
                )
            )
            delay(INTERVAL)
        }
    }
}

private fun commandStop() {
    if (!isServiceStarted) {
        return
    }
    Log.i("TAG", "commandStop()")
    try {
        job?.cancel()
        stopForeground(true)
        stopSelf()
    } finally {
        isServiceStarted = false
    }
}

 

 

서비스 클릭했을 때 프래그먼트로 넘어갈 수 있는 방법도 생각해봐할 문제인 것 같다.

 

전체 코드 - https://github.com/sanghyoLe/GiantSecret/blob/master/app/src/main/java/com/example/giantsecret/ui/Routine/RoutineProgressFragment.kt