메인 Activity인 DeskClock 에서 onStart() -onStop() 부분을 보면 isApplicationInForeground로 앱이 현재 포그라운드 상태인지 플래그를 변경해주고 있다.
override fun onStart() {
...
DataModel.dataModel.isApplicationInForeground = true
}
override fun onStop() {
...
DataModel.dataModel.isApplicationInForeground = false
...
}
DataModel 의 isApplicationInForegound를 보면, NotificationModel.isApplicationInForeground를 참조하고 있음을 알 수 있다. 그리고 값을 설정하는 경우, TimerModel의 updateNotification()을 불러준다.
var isApplicationInForeground: Boolean
/**
* @return `true` when the application is open in the foreground; `false` otherwise
*/
get() {
...
return mNotificationModel!!.isApplicationInForeground
}
/**
* @param inForeground `true` to indicate the application is open in the foreground
*/
set(inForeground) {
if (mNotificationModel!!.isApplicationInForeground != inForeground) {
mNotificationModel!!.isApplicationInForeground = inForeground
// Refresh all notifications in response to a change in app open state.
mTimerModel!!.updateNotification()
mTimerModel!!.updateMissedNotification()
...
}
}
TimerModel의 updateNotification()을 살펴보면, TimerModel이 가지고 있는 타이머 목록인 mutableTimers에서 실행중이거나 일시정지된 타이머들을 unexpired 리스트에 추가한다. 즉, 현재 동작중인 타이머들을 가지고 NotificationBuilder.build()를 이용하여 Notification을 만들고 띄워주게 된다. 동일한 코드내에서, 동작중인 타이머가 없거나 앱이 포그라운드 상태이면 Notification을 cancel하여 없애준다.
fun updateNotification() {
// Filter the timers to just include unexpired ones.
val unexpired: MutableList<Timer> = mutableListOf()
for (timer in mutableTimers) {
if (timer.isRunning || timer.isPaused) {
unexpired.add(timer)
}
}
// If no unexpired timers exist, cancel the notification.
if (unexpired.isEmpty()) {
if(mNotificationBuilder.isChannelCreated(mNotificationManager)) {
LogUtils.i("Cancelling Notifications when list is empty")
mNotificationManager.cancel(mNotificationModel.unexpiredTimerNotificationId)
}
return
}
// Sort the unexpired timers to locate the next one scheduled to expire.
unexpired.sortWith(Timer.EXPIRY_COMPARATOR)
//Build and setup a channel for notifications
LogUtils.i("Channel being setup!!!!")
// Otherwise build and post a notification reflecting the latest unexpired timers.
val notification: Notification =
mNotificationBuilder.build(mContext, mNotificationModel, unexpired)
val notificationId = mNotificationModel.unexpiredTimerNotificationId
mNotificationBuilder.buildChannel(mContext, mNotificationManager)
// Notifications should be hidden if the app is open.
if (mNotificationModel.isApplicationInForeground) {
if(mNotificationBuilder.isChannelCreated(mNotificationManager)) {
LogUtils.i("Cancelling notifications when the app is in foreground")
mNotificationManager.cancel(mNotificationModel.unexpiredTimerNotificationId)
}
return
}
mNotificationManager.notify(notificationId, notification)
}