Skip to content

Commit 877455e

Browse files
authored
Merge pull request #59 from boostcampwm-2022/23-feature-alarm
[PR] μž„μ˜μ˜ κ°’μœΌλ‘œ μ•ŒλžŒ κ΅¬ν˜„μ™„λ£Œ
2 parents a147b43 + c9cae24 commit 877455e

File tree

17 files changed

+399
-23
lines changed

17 files changed

+399
-23
lines changed

β€Ždata/src/main/java/com/stop/data/local/model/Alarm.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ data class Alarm(
88
val startPosition: String,
99
val endPosition: String,
1010
val routes: List<String>,
11-
val lastTime: String,
12-
val alarmTime: String,
11+
val lastTime: String, // 막차 μ‹œκ°„ -> 23:30:15 μ‹œλΆ„μ΄ˆ
12+
val alarmTime: Int, // 10λΆ„ μ „ μ•ŒλžŒ μ„€μ • -> 10
13+
val alarmCode: Int, // μ•ŒλžŒμ„ μ‹λ³„ν•˜κΈ° μœ„ν•œ μ•ŒλžŒ ID
1314
val alarmMethod: Boolean,
1415
val isMission: Boolean,
1516
) {
@@ -20,6 +21,7 @@ data class Alarm(
2021
routes,
2122
lastTime,
2223
alarmTime,
24+
alarmCode,
2325
alarmMethod,
2426
isMission
2527
)

β€Ždata/src/main/java/com/stop/data/model/alarm/AlarmRepositoryItem.kt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ data class AlarmRepositoryItem(
77
val startPosition: String,
88
val endPosition: String,
99
val routes: List<String>,
10-
val lastTime: String,
11-
val alarmTime: String,
10+
val lastTime: String, // 막차 μ‹œκ°„ -> 23:30:15 μ‹œλΆ„μ΄ˆ
11+
val alarmTime: Int, // 10λΆ„ μ „ μ•ŒλžŒ μ„€μ • -> 10
12+
val alarmCode: Int, // μ•ŒλžŒμ„ μ‹λ³„ν•˜κΈ° μœ„ν•œ μ•ŒλžŒ ID
1213
val alarmMethod: Boolean,
1314
val isMission: Boolean,
1415
) {
@@ -19,6 +20,7 @@ data class AlarmRepositoryItem(
1920
routes,
2021
lastTime,
2122
alarmTime,
23+
alarmCode,
2224
alarmMethod,
2325
isMission
2426
)
@@ -29,6 +31,7 @@ data class AlarmRepositoryItem(
2931
routes,
3032
lastTime,
3133
alarmTime,
34+
alarmCode,
3235
alarmMethod,
3336
isMission
3437
)

β€Ždata/src/main/java/com/stop/data/repository/AlarmRepositoryImpl.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ internal class AlarmRepositoryImpl @Inject constructor(
2020
alarmUseCaseItem.routes,
2121
alarmUseCaseItem.lastTime,
2222
alarmUseCaseItem.alarmTime,
23+
alarmUseCaseItem.alarmCode,
2324
alarmUseCaseItem.alarmMethod,
2425
alarmUseCaseItem.isMission
2526
)

β€Ždomain/src/main/java/com/stop/domain/model/alarm/AlarmUseCaseItem.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ data class AlarmUseCaseItem(
44
val startPosition: String,
55
val endPosition: String,
66
val routes: List<String>,
7-
val lastTime: String,
8-
val alarmTime: String,
9-
val alarmMethod: Boolean,
7+
val lastTime: String, // 막차 μ‹œκ°„ -> 23:30:15 μ‹œλΆ„μ΄ˆ
8+
val alarmTime: Int, // 10λΆ„ μ „ μ•ŒλžŒ μ„€μ • -> 10
9+
val alarmCode: Int, // μ•ŒλžŒμ„ μ‹λ³„ν•˜κΈ° μœ„ν•œ μ•ŒλžŒ ID
10+
val alarmMethod: Boolean, // true μ†Œλ¦¬ false 진동
1011
val isMission: Boolean,
1112
)

β€Žpresentation/build.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,4 +80,7 @@ dependencies {
8080

8181
// Splash
8282
implementation 'androidx.core:core-splashscreen:1.0.0'
83+
84+
// LifeCycle Service
85+
implementation 'androidx.lifecycle:lifecycle-service:2.5.1'
8386
}

β€Žpresentation/src/main/AndroidManifest.xml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,13 @@
66
<uses-permission android:name="android.permission.INTERNET" />
77
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
88
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
9+
910
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
11+
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
12+
<uses-permission android:name="android.permission.WAKE_LOCK" />
13+
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
14+
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
15+
<uses-permission android:name="android.permission.VIBRATE" />
1016

1117
<application
1218
android:name=".TroubleShooterApplication"
@@ -21,6 +27,26 @@
2127
android:usesCleartextTraffic="true"
2228
tools:targetApi="31">
2329

30+
31+
<activity
32+
android:name=".TestActivity"
33+
android:excludeFromRecents="true"
34+
android:exported="true"
35+
android:launchMode="singleTop"
36+
android:showOnLockScreen="true">
37+
<intent-filter>
38+
<action android:name="android.intent.action.MAIN" />
39+
<category android:name="android.intent.category.DEFAULT" />
40+
</intent-filter>
41+
</activity>
42+
43+
<receiver
44+
android:name=".AlarmReceiver"
45+
android:enabled="true"/>
46+
47+
<service
48+
android:name=".SoundService"/>
49+
2450
<provider
2551
android:name="androidx.startup.InitializationProvider"
2652
android:authorities="${applicationId}.androidx-startup"
@@ -41,4 +67,5 @@
4167
android:value="" />
4268
</activity>
4369
</application>
70+
4471
</manifest>
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package com.stop
2+
3+
import android.app.AlarmManager
4+
import android.app.PendingIntent
5+
import android.content.Context
6+
import android.content.Intent
7+
import android.os.Build
8+
import java.text.ParseException
9+
import java.text.SimpleDateFormat
10+
import java.util.*
11+
12+
class AlarmFunctions(
13+
private val context: Context
14+
) {
15+
16+
private lateinit var pendingIntent: PendingIntent
17+
18+
fun callAlarm(lastTime: String, alarmTime: Int, alarmCode: Int, alarmContent: String) {
19+
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
20+
21+
val receiverIntent = Intent(context, AlarmReceiver::class.java)
22+
receiverIntent.apply {
23+
putExtra("ALARM_REQUEST_CODE", alarmCode)
24+
putExtra("ALARM_CONTENT", alarmContent)
25+
}
26+
27+
val pendingIntent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
28+
PendingIntent.getBroadcast(context, alarmCode, receiverIntent, PendingIntent.FLAG_IMMUTABLE)
29+
} else {
30+
PendingIntent.getBroadcast(context, alarmCode, receiverIntent, PendingIntent.FLAG_UPDATE_CURRENT)
31+
}
32+
33+
alarmManager.setExactAndAllowWhileIdle(
34+
AlarmManager.RTC_WAKEUP,
35+
makeFullTime(lastTime).timeInMillis - (alarmTime * 60 * 1000),
36+
pendingIntent
37+
)
38+
}
39+
40+
private fun makeFullTime(lastTime: String): Calendar {
41+
val currentTime = System.currentTimeMillis()
42+
val currentFormat = SimpleDateFormat("yyyy:MM:dd", Locale.getDefault())
43+
val currentDateTime = currentFormat.format(currentTime)
44+
val fullTime = "$currentDateTime:$lastTime"
45+
46+
47+
val dateFormat = SimpleDateFormat("yyyy:MM:dd:HH:mm:ss", Locale.getDefault())
48+
var dateTime = Date()
49+
try {
50+
dateTime = dateFormat.parse(fullTime) as Date
51+
} catch (e: ParseException) {
52+
e.printStackTrace()
53+
}
54+
55+
val calendar = Calendar.getInstance()
56+
calendar.time = dateTime
57+
58+
return calendar
59+
}
60+
61+
fun cancelAlarm(alarmCode: Int) {
62+
val alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager
63+
val intent = Intent(context, AlarmReceiver::class.java)
64+
65+
pendingIntent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
66+
PendingIntent.getBroadcast(context, alarmCode, intent, PendingIntent.FLAG_IMMUTABLE)
67+
} else {
68+
PendingIntent.getBroadcast(context, alarmCode, intent, PendingIntent.FLAG_UPDATE_CURRENT)
69+
}
70+
71+
alarmManager.cancel(pendingIntent)
72+
}
73+
74+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package com.stop
2+
3+
import android.app.NotificationChannel
4+
import android.app.NotificationManager
5+
import android.app.PendingIntent
6+
import android.content.BroadcastReceiver
7+
import android.content.Context
8+
import android.content.Intent
9+
import androidx.core.app.NotificationCompat
10+
11+
class AlarmReceiver : BroadcastReceiver() {
12+
13+
override fun onReceive(context: Context, intent: Intent) {
14+
val requestCode = intent.extras?.getInt("ALARM_REQUEST_CODE") ?: -1
15+
val alarmContent = intent.extras?.getString("ALARM_CONTENT") ?: ""
16+
17+
val soundServiceIntent = Intent(context, SoundService::class.java)
18+
19+
if (isMoreThanOreo()) {
20+
context.startForegroundService(soundServiceIntent)
21+
22+
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 {
25+
notificationManager.createNotificationChannel(this)
26+
}
27+
}
28+
29+
val pendingIntent = PendingIntent.getActivity(context, requestCode, Intent(context, TestActivity::class.java).apply {
30+
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
31+
}, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
32+
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)
37+
.setAutoCancel(true)
38+
.setPriority(NotificationCompat.PRIORITY_HIGH)
39+
.setCategory(NotificationCompat.CATEGORY_ALARM)
40+
.setFullScreenIntent(pendingIntent, true)
41+
42+
try {
43+
notificationManager.notify(ALARM_NOTIFICATION_ID, builder.build())
44+
} catch (e: Exception) {
45+
e.printStackTrace()
46+
}
47+
} else {
48+
context.startService(soundServiceIntent)
49+
50+
Intent(context, TestActivity::class.java).apply {
51+
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
52+
context.startActivity(this)
53+
}
54+
}
55+
}
56+
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+
64+
}

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

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ import androidx.work.workDataOf
1010
import com.stop.domain.usecase.nearplace.GetNearPlacesUseCase
1111
import dagger.assisted.Assisted
1212
import dagger.assisted.AssistedInject
13-
import kotlinx.coroutines.Dispatchers
14-
import kotlinx.coroutines.withContext
1513

1614
// 일단은 NearPlaceUseCase μ΄μš©ν•˜μ—¬μ„œ 데이터 κ°€μ Έμ˜€κΈ° κ΅¬ν˜„
1715

@@ -34,15 +32,12 @@ class AlarmWorker @AssistedInject constructor(
3432
}
3533

3634
private suspend fun callApi() {
37-
withContext(Dispatchers.IO) {
38-
val list = getNearPlacesUseCase.getNearPlaces(
39-
"μ•„λ‚¨νƒ€μ›Œ",
40-
126.969652,
41-
37.553836
42-
)
43-
Log.e("ABC", list.toString())
44-
}
45-
35+
val list = getNearPlacesUseCase.getNearPlaces(
36+
"μ•„λ‚¨νƒ€μ›Œ",
37+
126.969652,
38+
37.553836
39+
)
40+
Log.e("ABC", list.toString())
4641
}
4742

4843
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.stop
2+
3+
import android.os.Build
4+
5+
fun isMoreThanOreo(): Boolean =
6+
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
7+
8+
fun isMoreThanOreoMr1(): Boolean =
9+
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1
10+
11+
fun isUnderOreo(): Boolean =
12+
Build.VERSION.SDK_INT < Build.VERSION_CODES.O
13+
14+
fun isMoreThanOreoUnderRedVelVet(): Boolean =
15+
(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) and (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R)
16+
17+
fun isMoreThanSnow(): Boolean =
18+
Build.VERSION.SDK_INT >= Build.VERSION_CODES.S

0 commit comments

Comments
Β (0)