Skip to content

Commit e852488

Browse files
authored
Merge pull request #53 from boostcampwm-2022/21-feature-background
[PR] Workmanager를 주기적 백그라운드 네트워크 요청
2 parents 5736858 + 9420f81 commit e852488

File tree

10 files changed

+187
-18
lines changed

10 files changed

+187
-18
lines changed

data/src/main/java/com/stop/data/local/source/alarm/AlarmLocalDataSourceImpl.kt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,11 @@ internal class AlarmLocalDataSourceImpl @Inject constructor(
3535
override suspend fun getAlarm(): Flow<AlarmRepositoryItem?> {
3636
return context.datastore.data.map { preferences ->
3737
val jsonString = preferences[ALARM] ?: ""
38-
val elements = adapter.fromJson(jsonString)?.toRepositoryModel()
39-
elements
38+
if (jsonString.isNotBlank()) {
39+
adapter.fromJson(jsonString)?.toRepositoryModel()
40+
} else {
41+
null
42+
}
4043
}
4144
}
4245

presentation/build.gradle

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,15 @@ dependencies {
6262
implementation files('libs/vsm-tmap-sdk-v2-android-1.6.60.aar')
6363
implementation files('libs/tmap-sdk-1.1.aar')
6464

65-
//Hilt
65+
// Hilt
6666
implementation 'com.google.dagger:hilt-android:2.44'
67-
kapt 'com.google.dagger:hilt-compiler:2.44'
67+
kapt 'com.google.dagger:hilt-android-compiler:2.44'
68+
implementation 'androidx.hilt:hilt-work:1.0.0'
69+
kapt 'androidx.hilt:hilt-compiler:1.0.0'
70+
71+
// WorkManager
72+
implementation 'androidx.work:work-runtime:2.7.1'
73+
implementation 'androidx.work:work-runtime-ktx:2.7.1'
6874

6975
// LiveData
7076
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.5.1'

presentation/src/main/AndroidManifest.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
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+
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
910

1011
<application
1112
android:name=".TroubleShooterApplication"
@@ -19,6 +20,10 @@
1920
android:theme="@style/Theme.PlzStop"
2021
android:usesCleartextTraffic="true"
2122
tools:targetApi="31">
23+
<provider
24+
android:name="androidx.startup.InitializationProvider"
25+
android:authorities="${applicationId}.androidx-startup"
26+
tools:node="remove" />
2227
<activity
2328
android:name=".MainActivity"
2429
android:exported="true">
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package com.stop
2+
3+
import android.content.Context
4+
import android.util.Log
5+
import androidx.hilt.work.HiltWorker
6+
import androidx.work.CoroutineWorker
7+
import androidx.work.Data
8+
import androidx.work.WorkerParameters
9+
import androidx.work.workDataOf
10+
import com.stop.domain.model.nearplace.Place
11+
import com.stop.domain.usecase.nearplace.GetNearPlacesUseCase
12+
import dagger.assisted.Assisted
13+
import dagger.assisted.AssistedInject
14+
import kotlinx.coroutines.Dispatchers
15+
import kotlinx.coroutines.flow.collectLatest
16+
import kotlinx.coroutines.withContext
17+
18+
// 일단은 NearPlaceUseCase 이용하여서 데이터 가져오기 구현
19+
20+
@HiltWorker
21+
class AlarmWorker @AssistedInject constructor(
22+
@Assisted context: Context,
23+
@Assisted workerParameters: WorkerParameters,
24+
private val getNearPlacesUseCase: GetNearPlacesUseCase
25+
) : CoroutineWorker(context, workerParameters) {
26+
27+
lateinit var resultList: List<Place>
28+
29+
override suspend fun doWork(): Result {
30+
return try {
31+
callApi()
32+
val output: Data = workDataOf("WORK_RESULT" to resultList.toString())
33+
Result.success(output)
34+
} catch (e: Exception) {
35+
Log.e("ABC", e.toString())
36+
Result.failure()
37+
}
38+
}
39+
40+
private suspend fun callApi() {
41+
withContext(Dispatchers.IO) {
42+
getNearPlacesUseCase.getNearPlaces(
43+
1,
44+
"아남타워",
45+
126.969652,
46+
37.553836,
47+
BuildConfig.TMAP_APP_KEY
48+
).collectLatest {
49+
resultList = it
50+
}
51+
}
52+
53+
}
54+
55+
}
Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,20 @@
11
package com.stop
22

33
import android.app.Application
4+
import androidx.hilt.work.HiltWorkerFactory
5+
import androidx.work.Configuration
46
import dagger.hilt.android.HiltAndroidApp
7+
import javax.inject.Inject
58

69
@HiltAndroidApp
7-
class TroubleShooterApplication : Application()
10+
class TroubleShooterApplication : Application(), Configuration.Provider{
11+
12+
@Inject
13+
lateinit var workerFactory : HiltWorkerFactory
14+
15+
override fun getWorkManagerConfiguration(): Configuration =
16+
Configuration.Builder()
17+
.setWorkerFactory(workerFactory)
18+
.build()
19+
20+
}

presentation/src/main/java/com/stop/ui/alarmsetting/AlarmSettingFragment.kt

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,14 @@ import android.view.View
99
import android.view.ViewGroup
1010
import androidx.fragment.app.Fragment
1111
import androidx.fragment.app.viewModels
12-
import androidx.lifecycle.lifecycleScope
12+
import androidx.navigation.findNavController
13+
import androidx.work.PeriodicWorkRequestBuilder
14+
import androidx.work.WorkManager
15+
import com.stop.AlarmWorker
1316
import com.stop.R
1417
import com.stop.databinding.FragmentAlarmSettingBinding
15-
import com.stop.domain.model.alarm.AlarmUseCaseItem
1618
import dagger.hilt.android.AndroidEntryPoint
17-
import kotlinx.coroutines.flow.collectLatest
18-
import kotlinx.coroutines.launch
19+
import java.util.concurrent.TimeUnit
1920

2021
@AndroidEntryPoint
2122
class AlarmSettingFragment : Fragment() {
@@ -41,22 +42,27 @@ class AlarmSettingFragment : Fragment() {
4142

4243
initView()
4344
setButtonListener()
45+
setToggleListener()
4446
}
4547

46-
private fun initBinding(){
48+
private fun initBinding() {
4749
binding.apply {
4850
lifecycleOwner = viewLifecycleOwner
4951
viewModel = alarmSettingViewModel
52+
fragment = this@AlarmSettingFragment
5053
}
5154
}
5255

5356
private fun initView() {
54-
with(binding){
57+
with(binding) {
5558
textViewLastTime.text = getString(R.string.last_transport_arrival_time, 23, 30)
5659
textViewWalk.text = getString(R.string.last_transport_walking_time, 10)
5760

5861
numberPickerAlarmTime.minValue = 0
5962
numberPickerAlarmTime.maxValue = 60
63+
64+
buttonSound.isCheckable = true
65+
buttonMissionOn.isCheckable = true
6066
}
6167
}
6268

@@ -90,6 +96,46 @@ class AlarmSettingFragment : Fragment() {
9096
}
9197
}
9298

99+
private fun setToggleListener() {
100+
with(binding) {
101+
toggleGroupAlarm.addOnButtonCheckedListener { _, checkedId, isChecked ->
102+
if (isChecked) {
103+
when (checkedId) {
104+
R.id.button_sound -> alarmSettingViewModel.alarmMethod = true
105+
else -> alarmSettingViewModel.alarmMethod = false
106+
}
107+
}
108+
}
109+
110+
toggleGroupMission.addOnButtonCheckedListener { _, checkedId, isChecked ->
111+
if (isChecked) {
112+
when (checkedId) {
113+
R.id.button_mission_on -> alarmSettingViewModel.isMission = true
114+
else -> alarmSettingViewModel.isMission = false
115+
}
116+
}
117+
}
118+
}
119+
}
120+
121+
fun setAlarmRegisterListener() {
122+
alarmSettingViewModel.saveAlarm()
123+
makeAlarmWorker()
124+
binding.root.findNavController().navigate(R.id.action_alarmSetting_to_mapFragment)
125+
}
126+
127+
private fun makeAlarmWorker() {
128+
val periodicWorkRequest = PeriodicWorkRequestBuilder<AlarmWorker>(15, TimeUnit.MINUTES)
129+
.build()
130+
val workManager = WorkManager.getInstance(requireContext())
131+
workManager.enqueue(periodicWorkRequest)
132+
workManager.getWorkInfoByIdLiveData(periodicWorkRequest.id)
133+
.observe(viewLifecycleOwner) { info ->
134+
val outPutData = info.outputData.getString("WORK_RESULT")
135+
Log.e("ABC", outPutData.toString())
136+
}
137+
}
138+
93139
override fun onDestroyView() {
94140
_binding = null
95141
super.onDestroyView()
Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
package com.stop.ui.alarmsetting
22

3+
import androidx.lifecycle.LiveData
34
import androidx.lifecycle.MutableLiveData
45
import androidx.lifecycle.ViewModel
6+
import androidx.lifecycle.viewModelScope
57
import com.stop.domain.model.alarm.AlarmUseCaseItem
68
import com.stop.domain.usecase.alarm.GetAlarmUseCase
79
import com.stop.domain.usecase.alarm.SaveAlarmUseCase
810
import dagger.hilt.android.lifecycle.HiltViewModel
11+
import kotlinx.coroutines.Dispatchers
12+
import kotlinx.coroutines.flow.collectLatest
13+
import kotlinx.coroutines.launch
914
import javax.inject.Inject
1015

1116
@HiltViewModel
@@ -16,11 +21,36 @@ class AlarmSettingViewModel @Inject constructor(
1621

1722
val alarmTime = MutableLiveData(0)
1823

19-
suspend fun save(alarmUseCaseItem: AlarmUseCaseItem){
20-
saveAlarmUseCase.saveAlarm(alarmUseCaseItem)
24+
//TODO TEST 코드
25+
private val _alarmUseCaseItem = MutableLiveData<AlarmUseCaseItem?>()
26+
val alarmUseCaseItem: LiveData<AlarmUseCaseItem?> = _alarmUseCaseItem
27+
28+
var alarmMethod = true
29+
var isMission = true
30+
31+
fun saveAlarm() {
32+
val alarmUseCaseItem = AlarmUseCaseItem(
33+
"쑥고개로 2다길 1",
34+
"현대 아남타워",
35+
listOf("도보", "버스5517", "신림역", "선릉역", "도보"),
36+
"23:30",
37+
alarmTime.value.toString(),
38+
alarmMethod,
39+
isMission
40+
)
41+
42+
viewModelScope.launch(Dispatchers.IO) {
43+
saveAlarmUseCase.saveAlarm(alarmUseCaseItem)
44+
}
2145
}
2246

23-
suspend fun get() =
24-
getAlarmUseCase.getAlarm()
47+
// TODO TEST 코드
48+
fun getAlarm() {
49+
viewModelScope.launch(Dispatchers.IO) {
50+
getAlarmUseCase.getAlarm().collectLatest {
51+
_alarmUseCaseItem.postValue(it)
52+
}
53+
}
54+
}
2555

2656
}

presentation/src/main/res/layout/fragment_alarm_setting.xml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@
99
name="viewModel"
1010
type="com.stop.ui.alarmsetting.AlarmSettingViewModel" />
1111

12+
<variable
13+
name="fragment"
14+
type="com.stop.ui.alarmsetting.AlarmSettingFragment" />
15+
1216
</data>
1317

1418
<androidx.constraintlayout.widget.ConstraintLayout
@@ -174,6 +178,7 @@
174178
android:layout_height="wrap_content"
175179
android:layout_marginStart="12dp"
176180
android:layout_marginBottom="9dp"
181+
app:checkedButton="@id/button_sound"
177182
app:layout_constraintBottom_toTopOf="@id/toggle_group_mission"
178183
app:layout_constraintEnd_toEndOf="parent"
179184
app:layout_constraintStart_toEndOf="@id/text_view_alarm_method"
@@ -217,6 +222,7 @@
217222
android:layout_height="wrap_content"
218223
android:layout_marginStart="12dp"
219224
android:layout_marginTop="9dp"
225+
app:checkedButton="@id/button_mission_on"
220226
app:layout_constraintBottom_toTopOf="@id/text_view_register_alarm"
221227
app:layout_constraintEnd_toEndOf="parent"
222228
app:layout_constraintStart_toEndOf="@id/text_view_mission_toggle"
@@ -246,10 +252,11 @@
246252
android:layout_marginBottom="24dp"
247253
android:background="@drawable/background_gray_d9_8"
248254
android:gravity="center"
249-
android:textSize="16sp"
255+
android:onClick="@{() -> fragment.setAlarmRegisterListener()}"
250256
android:paddingVertical="8dp"
251257
android:text="@string/register_alarm_text"
252258
android:textColor="@color/black"
259+
android:textSize="16sp"
253260
android:textStyle="bold"
254261
app:layout_constraintBottom_toBottomOf="parent"
255262
app:layout_constraintEnd_toEndOf="@id/guide_line_end"

presentation/src/main/res/navigation/nav_graph.xml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,11 @@
4949
android:id="@+id/alarmSetting"
5050
android:name="com.stop.ui.alarmsetting.AlarmSettingFragment"
5151
android:label="fragment_alarm_setting"
52-
tools:layout="@layout/fragment_alarm_setting" />
52+
tools:layout="@layout/fragment_alarm_setting" >
53+
<action
54+
android:id="@+id/action_alarmSetting_to_mapFragment"
55+
app:destination="@id/mapFragment" />
56+
</fragment>
5357
<fragment
5458
android:id="@+id/bookMarkFragment"
5559
android:name="com.stop.ui.bookmark.BookMarkFragment"

presentation/src/main/res/values/themes.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<resources xmlns:tools="http://schemas.android.com/tools">
22
<!-- Base application theme. -->
3-
<style name="Theme.PlzStop" parent="Theme.Material3.DayNight.NoActionBar">
3+
<style name="Theme.PlzStop" parent="Theme.Material3.Light.NoActionBar">
44
<!-- Primary brand color. -->
55
<item name="colorPrimary">@color/purple_500</item>
66
<item name="colorPrimaryVariant">@color/purple_700</item>

0 commit comments

Comments
 (0)