{"id":1898,"date":"2023-06-08T12:27:35","date_gmt":"2023-06-08T03:27:35","guid":{"rendered":"http:\/\/batmask.dothome.co.kr\/?p=1898"},"modified":"2025-09-11T18:54:16","modified_gmt":"2025-09-11T09:54:16","slug":"deskclock-%ec%bd%94%eb%93%9c%eb%b6%84%ec%84%9d-2-app%ea%b3%bc-notificaiton-%ec%a0%84%ed%99%98","status":"publish","type":"post","link":"http:\/\/batmask.net\/index.php\/2023\/06\/08\/1898\/","title":{"rendered":"DeskClock \ucf54\ub4dc\ubd84\uc11d #2 : App\uacfc Notificaiton \uc804\ud658"},"content":{"rendered":"\n<p> \uba54\uc778 Activity\uc778 DeskClock \uc5d0\uc11c onStart() -onStop() \ubd80\ubd84\uc744 \ubcf4\uba74 isApplicationInForeground\ub85c \uc571\uc774 \ud604\uc7ac \ud3ec\uadf8\ub77c\uc6b4\ub4dc \uc0c1\ud0dc\uc778\uc9c0 \ud50c\ub798\uadf8\ub97c \ubcc0\uacbd\ud574\uc8fc\uace0 \uc788\ub2e4. <\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-Roboto-Mono.ttf\" style=\"font-size:clamp(14px, .875rem, 21px);font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#adbac7;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:clamp(20px, 1.25rem, 30px);--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#22272e\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#adbac7;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>override fun onStart() {\n...\n    DataModel.dataModel.isApplicationInForeground = true\n}\n\noverride fun onStop() {\n\n...\n        DataModel.dataModel.isApplicationInForeground = false\n\n...\n}<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki github-dark-dimmed\" style=\"background-color: #22272e\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #F47067\">override<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">fun<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">onStart<\/span><span style=\"color: #ADBAC7\">() {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #F47067\">..<\/span><span style=\"color: #ADBAC7\">.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    DataModel.dataModel.isApplicationInForeground <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">true<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">}<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F47067\">override<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">fun<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">onStop<\/span><span style=\"color: #ADBAC7\">() {<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F47067\">..<\/span><span style=\"color: #ADBAC7\">.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        DataModel.dataModel.isApplicationInForeground <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #6CB6FF\">false<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #F47067\">..<\/span><span style=\"color: #ADBAC7\">.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>DataModel \uc758 isApplicationInForegound\ub97c \ubcf4\uba74, NotificationModel.isApplicationInForeground\ub97c \ucc38\uc870\ud558\uace0 \uc788\uc74c\uc744 \uc54c \uc218 \uc788\ub2e4. \uadf8\ub9ac\uace0 \uac12\uc744 \uc124\uc815\ud558\ub294 \uacbd\uc6b0, TimerModel\uc758 updateNotification()\uc744 \ubd88\ub7ec\uc900\ub2e4.<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-Roboto-Mono.ttf\" style=\"font-size:clamp(14px, .875rem, 21px);font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#adbac7;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:clamp(20px, 1.25rem, 30px);--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#22272e\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#adbac7;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>var isApplicationInForeground: Boolean\n    \/**\n        * @return `true` when the application is open in the foreground; `false` otherwise\n        *\/\n    get() {\n        ...\n        return mNotificationModel!!.isApplicationInForeground\n    }\n    \/**\n        * @param inForeground `true` to indicate the application is open in the foreground\n        *\/\n    set(inForeground) {\n        if (mNotificationModel!!.isApplicationInForeground != inForeground) {\n            mNotificationModel!!.isApplicationInForeground = inForeground\n\n            \/\/ Refresh all notifications in response to a change in app open state.\n            mTimerModel!!.updateNotification()\n            mTimerModel!!.updateMissedNotification()\n            ...\n        }\n    }\n<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki github-dark-dimmed\" style=\"background-color: #22272e\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #F47067\">var<\/span><span style=\"color: #ADBAC7\"> isApplicationInForeground: <\/span><span style=\"color: #F69D50\">Boolean<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #768390\">\/**<\/span><\/span>\n<span class=\"line\"><span style=\"color: #768390\">        * <\/span><span style=\"color: #F47067\">@return<\/span><span style=\"color: #768390\"> `true` when the application is open in the foreground; `false` otherwise<\/span><\/span>\n<span class=\"line\"><span style=\"color: #768390\">        *\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">get<\/span><span style=\"color: #ADBAC7\">() {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">..<\/span><span style=\"color: #ADBAC7\">.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">return<\/span><span style=\"color: #ADBAC7\"> mNotificationModel<\/span><span style=\"color: #F47067\">!!<\/span><span style=\"color: #ADBAC7\">.isApplicationInForeground<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #768390\">\/**<\/span><\/span>\n<span class=\"line\"><span style=\"color: #768390\">        * <\/span><span style=\"color: #F47067\">@param<\/span><span style=\"color: #768390\"> <\/span><span style=\"color: #F69D50\">inForeground<\/span><span style=\"color: #768390\"> `true` to indicate the application is open in the foreground<\/span><\/span>\n<span class=\"line\"><span style=\"color: #768390\">        *\/<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">set<\/span><span style=\"color: #ADBAC7\">(inForeground) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">if<\/span><span style=\"color: #ADBAC7\"> (mNotificationModel<\/span><span style=\"color: #F47067\">!!<\/span><span style=\"color: #ADBAC7\">.isApplicationInForeground <\/span><span style=\"color: #F47067\">!=<\/span><span style=\"color: #ADBAC7\"> inForeground) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            mNotificationModel<\/span><span style=\"color: #F47067\">!!<\/span><span style=\"color: #ADBAC7\">.isApplicationInForeground <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> inForeground<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #768390\">\/\/ Refresh all notifications in response to a change in app open state.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            mTimerModel<\/span><span style=\"color: #F47067\">!!<\/span><span style=\"color: #ADBAC7\">.<\/span><span style=\"color: #DCBDFB\">updateNotification<\/span><span style=\"color: #ADBAC7\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            mTimerModel<\/span><span style=\"color: #F47067\">!!<\/span><span style=\"color: #ADBAC7\">.<\/span><span style=\"color: #DCBDFB\">updateMissedNotification<\/span><span style=\"color: #ADBAC7\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            <\/span><span style=\"color: #F47067\">..<\/span><span style=\"color: #ADBAC7\">.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    }<\/span><\/span>\n<span class=\"line\"><\/span><\/code><\/pre><\/div>\n\n\n\n<p>TimerModel\uc758 updateNotification()\uc744 \uc0b4\ud3b4\ubcf4\uba74, TimerModel\uc774 \uac00\uc9c0\uace0 \uc788\ub294 \ud0c0\uc774\uba38 \ubaa9\ub85d\uc778 mutableTimers\uc5d0\uc11c \uc2e4\ud589\uc911\uc774\uac70\ub098 \uc77c\uc2dc\uc815\uc9c0\ub41c \ud0c0\uc774\uba38\ub4e4\uc744 unexpired \ub9ac\uc2a4\ud2b8\uc5d0 \ucd94\uac00\ud55c\ub2e4. \uc989, \ud604\uc7ac \ub3d9\uc791\uc911\uc778 \ud0c0\uc774\uba38\ub4e4\uc744 \uac00\uc9c0\uace0 NotificationBuilder.build()\ub97c \uc774\uc6a9\ud558\uc5ec Notification\uc744 \ub9cc\ub4e4\uace0 \ub744\uc6cc\uc8fc\uac8c \ub41c\ub2e4. \ub3d9\uc77c\ud55c \ucf54\ub4dc\ub0b4\uc5d0\uc11c, \ub3d9\uc791\uc911\uc778 \ud0c0\uc774\uba38\uac00 \uc5c6\uac70\ub098 \uc571\uc774 \ud3ec\uadf8\ub77c\uc6b4\ub4dc \uc0c1\ud0dc\uc774\uba74 Notification\uc744 cancel\ud558\uc5ec \uc5c6\uc560\uc900\ub2e4. <\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-Roboto-Mono.ttf\" style=\"font-size:clamp(14px, .875rem, 21px);font-family:Code-Pro-Roboto-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#adbac7;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:clamp(20px, 1.25rem, 30px);--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#22272e\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" style=\"color:#adbac7;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><pre class=\"code-block-pro-copy-button-pre\" aria-hidden=\"true\"><textarea class=\"code-block-pro-copy-button-textarea\" tabindex=\"-1\" aria-hidden=\"true\" readonly>fun updateNotification() {\n    \/\/ Filter the timers to just include unexpired ones.\n    val unexpired: MutableList&lt;Timer> = mutableListOf()\n    for (timer in mutableTimers) {\n        if (timer.isRunning || timer.isPaused) {\n            unexpired.add(timer)\n        }\n    }\n\n    \/\/ If no unexpired timers exist, cancel the notification.\n    if (unexpired.isEmpty()) {\n        if(mNotificationBuilder.isChannelCreated(mNotificationManager)) {\n            LogUtils.i(\"Cancelling Notifications when list is empty\")\n            mNotificationManager.cancel(mNotificationModel.unexpiredTimerNotificationId)\n        }\n        return\n    }\n\n    \/\/ Sort the unexpired timers to locate the next one scheduled to expire.\n    unexpired.sortWith(Timer.EXPIRY_COMPARATOR)\n\n    \/\/Build and setup a channel for notifications\n    LogUtils.i(\"Channel being setup!!!!\")\n    \/\/ Otherwise build and post a notification reflecting the latest unexpired timers.\n    val notification: Notification =\n            mNotificationBuilder.build(mContext, mNotificationModel, unexpired)\n    val notificationId = mNotificationModel.unexpiredTimerNotificationId\n    mNotificationBuilder.buildChannel(mContext, mNotificationManager)\n\n    \/\/ Notifications should be hidden if the app is open.\n    if (mNotificationModel.isApplicationInForeground) {\n        if(mNotificationBuilder.isChannelCreated(mNotificationManager)) {\n            LogUtils.i(\"Cancelling notifications when the app is in foreground\")\n            mNotificationManager.cancel(mNotificationModel.unexpiredTimerNotificationId)\n        }\n        return\n    }\n    \n    mNotificationManager.notify(notificationId, notification)\n}<\/textarea><\/pre><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki github-dark-dimmed\" style=\"background-color: #22272e\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #F47067\">fun<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">updateNotification<\/span><span style=\"color: #ADBAC7\">() {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #768390\">\/\/ Filter the timers to just include unexpired ones.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">val<\/span><span style=\"color: #ADBAC7\"> unexpired: <\/span><span style=\"color: #F69D50\">MutableList<\/span><span style=\"color: #ADBAC7\">&lt;<\/span><span style=\"color: #F69D50\">Timer<\/span><span style=\"color: #ADBAC7\">&gt; <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #DCBDFB\">mutableListOf<\/span><span style=\"color: #ADBAC7\">()<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">for<\/span><span style=\"color: #ADBAC7\"> (timer <\/span><span style=\"color: #F47067\">in<\/span><span style=\"color: #ADBAC7\"> mutableTimers) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">if<\/span><span style=\"color: #ADBAC7\"> (timer.isRunning <\/span><span style=\"color: #F47067\">||<\/span><span style=\"color: #ADBAC7\"> timer.isPaused) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            unexpired.<\/span><span style=\"color: #DCBDFB\">add<\/span><span style=\"color: #ADBAC7\">(timer)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #768390\">\/\/ If no unexpired timers exist, cancel the notification.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">if<\/span><span style=\"color: #ADBAC7\"> (unexpired.<\/span><span style=\"color: #DCBDFB\">isEmpty<\/span><span style=\"color: #ADBAC7\">()) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">if<\/span><span style=\"color: #ADBAC7\">(mNotificationBuilder.<\/span><span style=\"color: #DCBDFB\">isChannelCreated<\/span><span style=\"color: #ADBAC7\">(mNotificationManager)) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            LogUtils.<\/span><span style=\"color: #DCBDFB\">i<\/span><span style=\"color: #ADBAC7\">(<\/span><span style=\"color: #96D0FF\">&quot;Cancelling Notifications when list is empty&quot;<\/span><span style=\"color: #ADBAC7\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            mNotificationManager.<\/span><span style=\"color: #DCBDFB\">cancel<\/span><span style=\"color: #ADBAC7\">(mNotificationModel.unexpiredTimerNotificationId)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">return<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    }<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #768390\">\/\/ Sort the unexpired timers to locate the next one scheduled to expire.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    unexpired.<\/span><span style=\"color: #DCBDFB\">sortWith<\/span><span style=\"color: #ADBAC7\">(Timer.EXPIRY_COMPARATOR)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #768390\">\/\/Build and setup a channel for notifications<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    LogUtils.<\/span><span style=\"color: #DCBDFB\">i<\/span><span style=\"color: #ADBAC7\">(<\/span><span style=\"color: #96D0FF\">&quot;Channel being setup!!!!&quot;<\/span><span style=\"color: #ADBAC7\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #768390\">\/\/ Otherwise build and post a notification reflecting the latest unexpired timers.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">val<\/span><span style=\"color: #ADBAC7\"> notification: <\/span><span style=\"color: #F69D50\">Notification<\/span><span style=\"color: #ADBAC7\"> <\/span><span style=\"color: #F47067\">=<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            mNotificationBuilder.<\/span><span style=\"color: #DCBDFB\">build<\/span><span style=\"color: #ADBAC7\">(mContext, mNotificationModel, unexpired)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">val<\/span><span style=\"color: #ADBAC7\"> notificationId <\/span><span style=\"color: #F47067\">=<\/span><span style=\"color: #ADBAC7\"> mNotificationModel.unexpiredTimerNotificationId<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    mNotificationBuilder.<\/span><span style=\"color: #DCBDFB\">buildChannel<\/span><span style=\"color: #ADBAC7\">(mContext, mNotificationManager)<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #768390\">\/\/ Notifications should be hidden if the app is open.<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><span style=\"color: #F47067\">if<\/span><span style=\"color: #ADBAC7\"> (mNotificationModel.isApplicationInForeground) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">if<\/span><span style=\"color: #ADBAC7\">(mNotificationBuilder.<\/span><span style=\"color: #DCBDFB\">isChannelCreated<\/span><span style=\"color: #ADBAC7\">(mNotificationManager)) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            LogUtils.<\/span><span style=\"color: #DCBDFB\">i<\/span><span style=\"color: #ADBAC7\">(<\/span><span style=\"color: #96D0FF\">&quot;Cancelling notifications when the app is in foreground&quot;<\/span><span style=\"color: #ADBAC7\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">            mNotificationManager.<\/span><span style=\"color: #DCBDFB\">cancel<\/span><span style=\"color: #ADBAC7\">(mNotificationModel.unexpiredTimerNotificationId)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">        <\/span><span style=\"color: #F47067\">return<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    <\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">    mNotificationManager.<\/span><span style=\"color: #DCBDFB\">notify<\/span><span style=\"color: #ADBAC7\">(notificationId, notification)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #ADBAC7\">}<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\uba54\uc778 Activity\uc778 DeskClock \uc5d0\uc11c onStart() -onStop() \ubd80\ubd84\uc744 \ubcf4\uba74 isApplicationInForeground\ub85c \uc571\uc774 \ud604\uc7ac \ud3ec\uadf8\ub77c\uc6b4\ub4dc \uc0c1\ud0dc\uc778\uc9c0 \ud50c\ub798\uadf8\ub97c \ubcc0\uacbd\ud574\uc8fc\uace0 \uc788\ub2e4. DataModel \uc758 isApplicationInForegound\ub97c \ubcf4\uba74, NotificationModel.isApplicationInForeground\ub97c \ucc38\uc870\ud558\uace0 \uc788\uc74c\uc744 \uc54c \uc218 \uc788\ub2e4. \uadf8\ub9ac\uace0 \uac12\uc744 \uc124\uc815\ud558\ub294 \uacbd\uc6b0, TimerModel\uc758 updateNotification()\uc744 \ubd88\ub7ec\uc900\ub2e4. TimerModel\uc758 updateNotification()\uc744 \uc0b4\ud3b4\ubcf4\uba74, TimerModel\uc774 \uac00\uc9c0\uace0 \uc788\ub294 \ud0c0\uc774\uba38 \ubaa9\ub85d\uc778 mutableTimers\uc5d0\uc11c \uc2e4\ud589\uc911\uc774\uac70\ub098 \uc77c\uc2dc\uc815\uc9c0\ub41c \ud0c0\uc774\uba38\ub4e4\uc744 unexpired \ub9ac\uc2a4\ud2b8\uc5d0 \ucd94\uac00\ud55c\ub2e4. \uc989, \ud604\uc7ac \ub3d9\uc791\uc911\uc778 \ud0c0\uc774\uba38\ub4e4\uc744 \uac00\uc9c0\uace0 NotificationBuilder.build()\ub97c \uc774\uc6a9\ud558\uc5ec [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5,34],"tags":[186,311,38,207,283],"class_list":["post-1898","post","type-post","status-publish","format-standard","hentry","category-android","category-kotlin","tag-android-2","tag-deskclock","tag-kotlin","tag-notification","tag-timer"],"jetpack_featured_media_url":"","_links":{"self":[{"href":"http:\/\/batmask.net\/index.php\/wp-json\/wp\/v2\/posts\/1898","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/batmask.net\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/batmask.net\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/batmask.net\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/batmask.net\/index.php\/wp-json\/wp\/v2\/comments?post=1898"}],"version-history":[{"count":4,"href":"http:\/\/batmask.net\/index.php\/wp-json\/wp\/v2\/posts\/1898\/revisions"}],"predecessor-version":[{"id":3466,"href":"http:\/\/batmask.net\/index.php\/wp-json\/wp\/v2\/posts\/1898\/revisions\/3466"}],"wp:attachment":[{"href":"http:\/\/batmask.net\/index.php\/wp-json\/wp\/v2\/media?parent=1898"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/batmask.net\/index.php\/wp-json\/wp\/v2\/categories?post=1898"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/batmask.net\/index.php\/wp-json\/wp\/v2\/tags?post=1898"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}