Skip to content

Commit 799b342

Browse files
authored
Merge pull request #68 from boostcampwm-2022/67-feature-background-alarm
[PR] ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์•Œ๋žŒ ๊ฐฑ์‹  ์ž‘์—…
2 parents 639f11f + 7d26037 commit 799b342

File tree

12 files changed

+259
-117
lines changed

12 files changed

+259
-117
lines changed

โ€Žpresentation/src/main/java/com/stop/AlarmFunctions.kt

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,19 @@ import android.app.AlarmManager
44
import android.app.PendingIntent
55
import android.content.Context
66
import android.content.Intent
7-
import java.text.ParseException
8-
import java.text.SimpleDateFormat
9-
import java.util.*
107

118
class AlarmFunctions(
129
private val context: Context
1310
) {
1411

1512
private lateinit var pendingIntent: PendingIntent
1613

17-
fun callAlarm(lastTime: String, alarmTime: Int, alarmCode: Int, alarmContent: String) {
14+
fun callAlarm(lastTime: String, alarmTime: Int, alarmCode: Int) {
1815
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
1916

2017
val receiverIntent = Intent(context, AlarmReceiver::class.java)
2118
receiverIntent.apply {
2219
putExtra("ALARM_CODE", alarmCode)
23-
putExtra("ALARM_CONTENT", alarmContent)
2420
}
2521

2622
val pendingIntent = if (isMoreThanSnow()) {
@@ -36,27 +32,6 @@ class AlarmFunctions(
3632
)
3733
}
3834

39-
private fun makeFullTime(lastTime: String): Calendar {
40-
val currentTime = System.currentTimeMillis()
41-
val currentFormat = SimpleDateFormat("yyyy:MM:dd", Locale.getDefault())
42-
val currentDateTime = currentFormat.format(currentTime)
43-
val fullTime = "$currentDateTime:$lastTime"
44-
45-
46-
val dateFormat = SimpleDateFormat("yyyy:MM:dd:HH:mm:ss", Locale.getDefault())
47-
var dateTime = Date()
48-
try {
49-
dateTime = dateFormat.parse(fullTime) as Date
50-
} catch (e: ParseException) {
51-
e.printStackTrace()
52-
}
53-
54-
val calendar = Calendar.getInstance()
55-
calendar.time = dateTime
56-
57-
return calendar
58-
}
59-
6035
fun cancelAlarm(alarmCode: Int) {
6136
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
6237
val intent = Intent(context, AlarmReceiver::class.java)

โ€Žpresentation/src/main/java/com/stop/AlarmReceiver.kt

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,24 @@ import android.content.BroadcastReceiver
77
import android.content.Context
88
import android.content.Intent
99
import androidx.core.app.NotificationCompat
10+
import com.stop.LastTimeCheckWorker.Companion.NOTIFICATION_ID
1011

1112
class AlarmReceiver : BroadcastReceiver() {
1213

1314
override fun onReceive(context: Context, intent: Intent) {
1415
val alarmCode = intent.extras?.getInt("ALARM_CODE") ?: -1
15-
val alarmContent = intent.extras?.getString("ALARM_CONTENT") ?: ""
1616

1717
val soundServiceIntent = Intent(context, SoundService::class.java)
1818

1919
if (isMoreThanOreo()) {
2020
context.startForegroundService(soundServiceIntent)
2121

22+
val id = context.getString(R.string.notification_channel_id)
23+
val name = context.getString(R.string.notification_channel_name)
24+
2225
val notificationManager = context.getSystemService(NotificationManager::class.java)
23-
if (notificationManager.getNotificationChannel(ALARM_RECEIVER_CHANNEL_ID) == null) {
24-
NotificationChannel(ALARM_RECEIVER_CHANNEL_ID, ALARM_RECEIVER_CHANNEL_NAME, NotificationManager.IMPORTANCE_HIGH).apply {
26+
if (notificationManager.getNotificationChannel(id) == null) {
27+
NotificationChannel(id, name, NotificationManager.IMPORTANCE_HIGH).apply {
2528
notificationManager.createNotificationChannel(this)
2629
}
2730
}
@@ -30,17 +33,20 @@ class AlarmReceiver : BroadcastReceiver() {
3033
putExtra("ALARM_CODE", alarmCode)
3134
}, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
3235

33-
val builder = NotificationCompat.Builder(context, ALARM_RECEIVER_CHANNEL_ID)
34-
.setSmallIcon(R.drawable.ic_baseline_alarm_on_24)
35-
.setContentTitle(LAST_TRANSPORT_NOTIFICATION_TITLE)
36-
.setContentText(alarmContent)
36+
val title = context.getString(R.string.notification_title)
37+
val content = context.getString(R.string.alarm_content_text)
38+
39+
val builder = NotificationCompat.Builder(context, id)
40+
.setSmallIcon(R.mipmap.ic_bus)
41+
.setContentTitle(title)
42+
.setContentText(content)
3743
.setAutoCancel(true)
3844
.setPriority(NotificationCompat.PRIORITY_HIGH)
3945
.setCategory(NotificationCompat.CATEGORY_ALARM)
4046
.setFullScreenIntent(pendingIntent, true)
4147

4248
try {
43-
notificationManager.notify(ALARM_NOTIFICATION_ID, builder.build())
49+
notificationManager.notify(NOTIFICATION_ID, builder.build())
4450
} catch (e: Exception) {
4551
e.printStackTrace()
4652
}
@@ -54,11 +60,4 @@ class AlarmReceiver : BroadcastReceiver() {
5460
}
5561
}
5662

57-
companion object {
58-
const val ALARM_RECEIVER_CHANNEL_ID = "ALARM_RECEIVER_CHANNEL_ID"
59-
const val ALARM_RECEIVER_CHANNEL_NAME = "ALARM_RECEIVER_CHANNEL_NAME"
60-
const val ALARM_NOTIFICATION_ID = 123
61-
private const val LAST_TRANSPORT_NOTIFICATION_TITLE = "๋ง‰์ฐจ ์•Œ๋ฆผ"
62-
}
63-
6463
}

โ€Žpresentation/src/main/java/com/stop/AlarmWorker.kt

Lines changed: 0 additions & 43 deletions
This file was deleted.
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
package com.stop
2+
3+
import android.app.NotificationChannel
4+
import android.app.NotificationManager
5+
import android.content.Context
6+
import androidx.core.app.NotificationCompat
7+
import androidx.hilt.work.HiltWorker
8+
import androidx.work.CoroutineWorker
9+
import androidx.work.ForegroundInfo
10+
import androidx.work.WorkManager
11+
import androidx.work.WorkerParameters
12+
import com.stop.domain.usecase.nearplace.GetNearPlacesUseCase
13+
import com.stop.ui.alarmsetting.AlarmSettingFragment.Companion.ALARM_CODE
14+
import com.stop.ui.alarmsetting.AlarmSettingFragment.Companion.ALARM_TIME
15+
import com.stop.ui.alarmsetting.AlarmSettingFragment.Companion.LAST_TIME
16+
import dagger.assisted.Assisted
17+
import dagger.assisted.AssistedInject
18+
import kotlinx.coroutines.delay
19+
20+
@HiltWorker
21+
class LastTimeCheckWorker @AssistedInject constructor(
22+
@Assisted context: Context,
23+
@Assisted workerParameters: WorkerParameters,
24+
private val getNearPlacesUseCase: GetNearPlacesUseCase,
25+
private val alarmFunctions: AlarmFunctions
26+
) : CoroutineWorker(context, workerParameters) {
27+
28+
private val notificationManager =
29+
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
30+
31+
private var lastTime = ""
32+
private val alarmTime by lazy {
33+
inputData.getInt(ALARM_TIME, 0)
34+
}
35+
36+
override suspend fun doWork(): Result {
37+
initData()
38+
setForeground(createForegroundInfo())
39+
checkLastTransportTime()
40+
41+
return Result.success()
42+
}
43+
44+
private fun initData(){
45+
lastTime = inputData.getString(LAST_TIME) ?: ""
46+
}
47+
48+
private fun createForegroundInfo(): ForegroundInfo {
49+
val id = applicationContext.getString(R.string.notification_channel_id)
50+
val title = applicationContext.getString(R.string.notification_title)
51+
val cancel = applicationContext.getString(R.string.alarm_cancel_text)
52+
53+
val intent = WorkManager.getInstance(applicationContext)
54+
.createCancelPendingIntent(getId())
55+
56+
createChannel(id)
57+
58+
val notification = NotificationCompat.Builder(applicationContext, id)
59+
.setContentTitle(title)
60+
.setTicker(title)
61+
.setContentText(NOTIFICATION_CONTENT)
62+
.setSmallIcon(R.mipmap.ic_bus)
63+
.setOngoing(true) // ์‚ฌ์šฉ์ž๊ฐ€ ์ง€์šฐ์ง€ ๋ชปํ•˜๋„๋ก ๋ง‰์Œ
64+
.addAction(android.R.drawable.ic_delete, cancel, intent)
65+
.build()
66+
67+
return ForegroundInfo(NOTIFICATION_ID, notification)
68+
}
69+
70+
private fun createChannel(id: String) {
71+
if (isMoreThanOreo()) {
72+
if (notificationManager.getNotificationChannel(id) == null) {
73+
val name = applicationContext.getString(R.string.notification_channel_name)
74+
NotificationChannel(id, name, NotificationManager.IMPORTANCE_DEFAULT).apply {
75+
notificationManager.createNotificationChannel(this)
76+
}
77+
}
78+
}
79+
}
80+
81+
private suspend fun checkLastTransportTime() {
82+
while (isStopped.not()) {
83+
//TODO ๋ง‰์ฐจ์‹œ๊ฐ„ ๊ฐ€์ ธ์˜ค๋Š” API๋กœ ๋ณ€๊ฒฝ ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.
84+
getNearPlacesUseCase.getNearPlaces(
85+
"์•„๋‚จํƒ€์›Œ",
86+
126.969652,
87+
37.553836
88+
)
89+
90+
val resultLastTime = "21:04:00"
91+
92+
if(lastTime != resultLastTime && resultLastTime != null){
93+
lastTime = resultLastTime
94+
alarmFunctions.cancelAlarm(ALARM_CODE)
95+
alarmFunctions.callAlarm(resultLastTime, alarmTime, ALARM_CODE)
96+
}
97+
98+
val delayTime = getDelayTime()
99+
if (delayTime == 0L) {
100+
this.onStopped()
101+
} else {
102+
delay(delayTime)
103+
}
104+
}
105+
}
106+
107+
private fun getDelayTime(): Long {
108+
val fullLastTimeMillis = makeFullTime(lastTime).timeInMillis
109+
val currentTimeMillis = System.currentTimeMillis()
110+
111+
return when (val diffTimeMillis =
112+
if (fullLastTimeMillis > currentTimeMillis) fullLastTimeMillis - currentTimeMillis
113+
else 0L
114+
) {
115+
in THIRTY_MINUTES until Long.MAX_VALUE -> diffTimeMillis - THIRTY_MINUTES
116+
in TWENTY_MINUTES until THIRTY_MINUTES -> FIVE_MINUTES
117+
in TEN_MINUTES until TWENTY_MINUTES -> TWO_MINUTES
118+
in 0 until TEN_MINUTES -> ONE_MINUTES
119+
else -> 0
120+
}
121+
}
122+
123+
companion object {
124+
const val NOTIFICATION_ID = 12
125+
private const val NOTIFICATION_CONTENT = "๋ง‰์ฐจ ์‹œ๊ฐ„์ด ๋ณ€๊ฒฝ๋˜๋Š”์ง€ ๊ณ„์† ์ถ”์ ์ค‘์ž…๋‹ˆ๋‹ค."
126+
private const val THIRTY_MINUTES = 1_800_000L
127+
private const val TWENTY_MINUTES = 1_200_000L
128+
private const val TEN_MINUTES = 600_000L
129+
private const val FIVE_MINUTES = 300_000L
130+
private const val TWO_MINUTES = 120_000L
131+
private const val ONE_MINUTES = 60_000L
132+
}
133+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.stop
2+
3+
import java.text.ParseException
4+
import java.text.SimpleDateFormat
5+
import java.util.*
6+
7+
fun makeFullTime(time: String): Calendar {
8+
val currentTime = System.currentTimeMillis()
9+
val currentFormat = SimpleDateFormat("yyyy:MM:dd", Locale.getDefault())
10+
val currentDateTime = currentFormat.format(currentTime)
11+
val fullTime = "$currentDateTime:$time"
12+
13+
14+
val dateFormat = SimpleDateFormat("yyyy:MM:dd:HH:mm:ss", Locale.getDefault())
15+
val dateTime = try {
16+
dateFormat.parse(fullTime) as Date
17+
} catch (e: ParseException) {
18+
e.printStackTrace()
19+
Date()
20+
}
21+
22+
val calendar = Calendar.getInstance()
23+
calendar.time = dateTime
24+
25+
return calendar
26+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.stop.di
2+
3+
import android.content.Context
4+
import androidx.work.WorkManager
5+
import com.stop.AlarmFunctions
6+
import dagger.Module
7+
import dagger.Provides
8+
import dagger.hilt.InstallIn
9+
import dagger.hilt.android.qualifiers.ApplicationContext
10+
import dagger.hilt.components.SingletonComponent
11+
import javax.inject.Singleton
12+
13+
@InstallIn(SingletonComponent::class)
14+
@Module
15+
object AlarmModule {
16+
17+
@Provides
18+
@Singleton
19+
fun provideWorkManager(
20+
@ApplicationContext context: Context
21+
) = WorkManager.getInstance(context)
22+
23+
@Provides
24+
@Singleton
25+
fun provideAlarmFunctions(
26+
@ApplicationContext context: Context
27+
) = AlarmFunctions(context)
28+
29+
}

0 commit comments

Comments
ย (0)