Skip to content

Commit 727d61f

Browse files
committed
feat: Implement recurring work once a day given constraints
1 parent 4327ba3 commit 727d61f

File tree

3 files changed

+77
-0
lines changed

3 files changed

+77
-0
lines changed

app/src/main/java/com/example/android/devbyteviewer/DevByteApplication.kt

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,22 @@
1818
package com.example.android.devbyteviewer
1919

2020
import android.app.Application
21+
import androidx.work.*
22+
import androidx.work.impl.Schedulers
23+
import com.example.android.devbyteviewer.work.RefreshDataWork
24+
import kotlinx.coroutines.CoroutineScope
25+
import kotlinx.coroutines.Dispatchers
26+
import kotlinx.coroutines.launch
2127
import timber.log.Timber
28+
import java.util.concurrent.TimeUnit
2229

2330
/**
2431
* Override application to setup background work via WorkManager
2532
*/
2633
class DevByteApplication : Application() {
2734

35+
private val applicationScope = CoroutineScope(Dispatchers.Default)
36+
2837
/**
2938
* onCreate is called before the first screen is shown to the user.
3039
*
@@ -34,5 +43,31 @@ class DevByteApplication : Application() {
3443
override fun onCreate() {
3544
super.onCreate()
3645
Timber.plant(Timber.DebugTree())
46+
delayedInit()
47+
}
48+
49+
private fun delayedInit() {
50+
applicationScope.launch { setupRecurringWork() }
51+
}
52+
53+
private fun setupRecurringWork() {
54+
val constraints = Constraints.Builder()
55+
.setRequiredNetworkType(NetworkType.UNMETERED)
56+
.setRequiresBatteryNotLow(true)
57+
.setRequiresCharging(true)
58+
.apply {
59+
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
60+
setRequiresDeviceIdle(true)
61+
}
62+
}
63+
.build()
64+
val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWork>(1, TimeUnit.DAYS)
65+
.setConstraints(constraints)
66+
.build()
67+
WorkManager.getInstance(this).enqueueUniquePeriodicWork(
68+
RefreshDataWork.WORK_NAME,
69+
ExistingPeriodicWorkPolicy.KEEP,
70+
repeatingRequest
71+
)
3772
}
3873
}

app/src/main/java/com/example/android/devbyteviewer/repository/VideoRepository.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,15 @@ class VideoRepository(private val videoDao: VideoDao) {
4040
suspend fun refreshVideos() {
4141
withContext(Dispatchers.IO) {
4242
try {
43+
Timber.i("Refreshing videos")
4344
val playlist = Network.devbytes.getPlaylist()
45+
Timber.i("Videos were fetched from internet successfully")
4446
videoDao.insertAll(*playlist.asDatabaseModel())
47+
Timber.i("Videos were saved to local data store successfully")
4548
} catch (error: Exception) {
4649
Timber.e(error, "Failed to refresh videos")
50+
// TODO Log to Crashlytics/Bugsnag
51+
// TODO Show visual feedback
4752
}
4853
}
4954
}

app/src/main/java/com/example/android/devbyteviewer/work/RefreshDataWork.kt

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,40 @@
1616
*/
1717

1818
package com.example.android.devbyteviewer.work
19+
20+
import android.content.Context
21+
import androidx.work.CoroutineWorker
22+
import androidx.work.WorkerParameters
23+
import com.example.android.devbyteviewer.database.getDatabase
24+
import com.example.android.devbyteviewer.repository.VideoRepository
25+
import retrofit2.HttpException
26+
import timber.log.Timber
27+
28+
/**
29+
* Worker which uses [VideoRepository] to refresh data from the internet and cache data to the database.
30+
*/
31+
class RefreshDataWork(
32+
private val appContext: Context,
33+
params: WorkerParameters
34+
) : CoroutineWorker(appContext, params) {
35+
36+
override suspend fun doWork(): Result {
37+
val database = getDatabase(appContext)
38+
val repository = VideoRepository(database.videoDao)
39+
40+
return try {
41+
Timber.i("Starting refresh work")
42+
repository.refreshVideos()
43+
Timber.i("Refresh work done successfully")
44+
Result.success()
45+
} catch (error: HttpException) {
46+
Timber.e(error, "Failed to complete refresh work. Signalling to retry")
47+
Result.retry()
48+
// TODO Log to Crashlytics/Bugsnag
49+
}
50+
}
51+
52+
companion object {
53+
const val WORK_NAME = "RefreshDataWork"
54+
}
55+
}

0 commit comments

Comments
 (0)