Skip to content

Commit

Permalink
update worker
Browse files Browse the repository at this point in the history
  • Loading branch information
hoc081098 committed Mar 7, 2019
1 parent 5623732 commit b564191
Show file tree
Hide file tree
Showing 13 changed files with 150 additions and 93 deletions.
Binary file modified app/build/outputs/apk/debug/app-debug.apk
Binary file not shown.
4 changes: 2 additions & 2 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,10 @@
android:name="preloaded_fonts"
android:resource="@array/preloaded_fonts" />
<!--
The API key for Google Maps-based APIs is defined as enqueueUpdateCurrentWeatherWorkRequestImmediately string resource.
The API key for Google Maps-based APIs is defined as enqueuePeriodic string resource.
(See the file "res/values/google_maps_api.xml").
Note that the API key is linked to the encryption key used to sign the APK.
You need enqueueUpdateCurrentWeatherWorkRequestImmediately different API key for each encryption key, including the release key that is used to
You need enqueuePeriodic different API key for each encryption key, including the release key that is used to
sign the APK for publishing.
You can define the keys for the debug and release targets in src/debug/ and src/release/.
-->
Expand Down
18 changes: 12 additions & 6 deletions app/src/main/java/com/hoc/weatherapp/App.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import com.hoc.weatherapp.koin.presenterModule
import com.hoc.weatherapp.koin.retrofitModule
import com.hoc.weatherapp.koin.sharePrefUtilModule
import com.hoc.weatherapp.utils.debug
import com.hoc.weatherapp.utils.toast
import com.hoc.weatherapp.worker.UpdateCurrentWeatherWorker
import com.hoc.weatherapp.worker.UpdateDailyWeatherWorker
import com.jakewharton.threetenabp.AndroidThreeTen
Expand Down Expand Up @@ -39,16 +40,21 @@ class App : Application() {
createNotificationChannel()

WorkManager.getInstance().run {
getWorkInfosByTagLiveData(UpdateDailyWeatherWorker.TAG)
getWorkInfosForUniqueWorkLiveData(UpdateDailyWeatherWorker.UNIQUE_WORK_NAME)
.observeForever {
debug("UpdateDailyWeatherWorker", "UpdateDailyWeatherWorker")
it.forEach { debug("info=$it", "UpdateDailyWeatherWorker") }
it.forEach {
debug("info=$it", "UpdateDailyWeatherWorker")
it.takeIf { it.state.isFinished }?.outputData?.getString("RESULT")?.let { toast(it) }
}
}

getWorkInfosByTagLiveData(UpdateCurrentWeatherWorker.TAG)

getWorkInfosForUniqueWorkLiveData(UpdateCurrentWeatherWorker.UNIQUE_WORK_NAME)
.observeForever {
debug("UpdateCurrentWeatherWorker", "UpdateCurrentWeatherWorker")
it.forEach { debug("info=$it", "UpdateCurrentWeatherWorker") }
it.forEach {
debug("info=$it", "UpdateCurrentWeatherWorker")
it.takeIf { it.state.isFinished }?.outputData?.getString("RESULT")?.let { toast(it) }
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ class CitiesPresenter(
.doOnSuccess { (cityAndCurrentWeather) ->
if (settingPreferences.autoUpdatePreference.value) {
WorkerUtil.enqueueUpdateCurrentWeatherWorkRequest()
WorkerUtil.enqueueUpdateDailyWeatherWorkWorkRequest()
WorkerUtil.enqueueUpdateDailyWeatherWorkRequest()
}
androidApplication.showNotificationIfEnabled(cityAndCurrentWeather, settingPreferences)
}
Expand Down Expand Up @@ -135,7 +135,7 @@ class CitiesPresenter(

if (settingPreferences.autoUpdatePreference.value) {
WorkerUtil.enqueueUpdateCurrentWeatherWorkRequest()
WorkerUtil.enqueueUpdateDailyWeatherWorkWorkRequest()
WorkerUtil.enqueueUpdateDailyWeatherWorkRequest()
}

androidApplication.showNotificationIfEnabled(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class DailyWeatherPresenter(
.refreshFiveDayForecastOfSelectedCity()
.doOnSuccess {
if (settingPreferences.autoUpdatePreference.value) {
WorkerUtil.enqueueUpdateDailyWeatherWorkWorkRequest()
WorkerUtil.enqueueUpdateDailyWeatherWorkRequest()
}
}
.doOnError {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import com.hoc.weatherapp.utils.*
import com.hoc.weatherapp.worker.WorkerUtil.cancelUpdateCurrentWeatherWorkRequest
import com.hoc.weatherapp.worker.WorkerUtil.cancelUpdateDailyWeatherWorkWorkRequest
import com.hoc.weatherapp.worker.WorkerUtil.enqueueUpdateCurrentWeatherWorkRequest
import com.hoc.weatherapp.worker.WorkerUtil.enqueueUpdateDailyWeatherWorkWorkRequest
import com.hoc.weatherapp.worker.WorkerUtil.enqueueUpdateDailyWeatherWorkRequest
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.CompositeDisposable
Expand Down Expand Up @@ -161,7 +161,7 @@ class SettingsActivity : AppCompatActivity() {
key == getString(R.string.key_auto_update) && newValue is Boolean -> {
settingPreferences.autoUpdatePreference.save(newValue)
if (newValue) {
enqueueUpdateDailyWeatherWorkWorkRequest()
enqueueUpdateDailyWeatherWorkRequest()
enqueueUpdateCurrentWeatherWorkRequest()
} else {
cancelUpdateCurrentWeatherWorkRequest()
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,36 +1,44 @@
package com.hoc.weatherapp.worker

import android.content.Context
import androidx.work.Worker
import androidx.work.RxWorker
import androidx.work.WorkerParameters
import androidx.work.workDataOf
import com.hoc.weatherapp.data.CurrentWeatherRepository
import com.hoc.weatherapp.data.NoSelectedCityException
import com.hoc.weatherapp.data.local.SettingPreferences
import com.hoc.weatherapp.utils.WEATHER_NOTIFICATION_ID
import com.hoc.weatherapp.utils.cancelNotificationById
import com.hoc.weatherapp.utils.debug
import com.hoc.weatherapp.utils.showNotificationIfEnabled
import io.reactivex.Single
import org.koin.standalone.KoinComponent
import org.koin.standalone.inject

class UpdateCurrentWeatherWorker(context: Context, workerParams: WorkerParameters) :
Worker(context, workerParams), KoinComponent {
RxWorker(context, workerParams), KoinComponent {
private val tag = "__current_worker__"
private val currentWeatherRepository by inject<CurrentWeatherRepository>()
private val settingPreferences by inject<SettingPreferences>()

override fun doWork(): Result {
return runCatching {
currentWeatherRepository
.refreshCurrentWeatherOfSelectedCity()
.blockingGet()
override fun createWork(): Single<Result> {
return currentWeatherRepository
.refreshCurrentWeatherOfSelectedCity()
.doOnSuccess {
debug("[SUCCESS] doWork $it", tag)

}.onSuccess {
applicationContext.showNotificationIfEnabled(it, settingPreferences)
}.onFailure {
if (it is NoSelectedCityException) {
applicationContext.cancelNotificationById(WEATHER_NOTIFICATION_ID)
WorkerUtil.cancelUpdateCurrentWeatherWorkRequest()
applicationContext.showNotificationIfEnabled(it, settingPreferences)
}
}.fold({ Result.success() }, { Result.failure() })
.doOnError {
debug("[FAILURE] doWork $it", tag)

if (it is NoSelectedCityException) {
applicationContext.cancelNotificationById(WEATHER_NOTIFICATION_ID)
WorkerUtil.cancelUpdateCurrentWeatherWorkRequest()
}
}
.map { Result.success(workDataOf("RESULT" to "Update current success")) }
.onErrorReturn { Result.failure(workDataOf("RESULT" to "Update current failure: ${it.message}")) }
}

companion object {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,30 +1,38 @@
package com.hoc.weatherapp.worker

import android.content.Context
import androidx.work.Worker
import androidx.work.RxWorker
import androidx.work.WorkerParameters
import androidx.work.workDataOf
import com.hoc.weatherapp.data.FiveDayForecastRepository
import com.hoc.weatherapp.data.NoSelectedCityException
import com.hoc.weatherapp.utils.WEATHER_NOTIFICATION_ID
import com.hoc.weatherapp.utils.cancelNotificationById
import com.hoc.weatherapp.utils.debug
import io.reactivex.Single
import org.koin.standalone.KoinComponent
import org.koin.standalone.inject

class UpdateDailyWeatherWorker(context: Context, workerParams: WorkerParameters) :
Worker(context, workerParams), KoinComponent {
RxWorker(context, workerParams), KoinComponent {
private val tag = "__daily_worker__"
private val fiveDayForecastRepository by inject<FiveDayForecastRepository>()

override fun doWork(): Result {
return runCatching {
fiveDayForecastRepository
.refreshFiveDayForecastOfSelectedCity()
.blockingGet()
}.onFailure {
if (it is NoSelectedCityException) {
applicationContext.cancelNotificationById(WEATHER_NOTIFICATION_ID)
WorkerUtil.cancelUpdateDailyWeatherWorkWorkRequest()
override fun createWork(): Single<Result> {
return fiveDayForecastRepository
.refreshFiveDayForecastOfSelectedCity()
.doOnSuccess {
debug("[SUCCESS] doWork $it", tag)
}
}.fold({ Result.success() }, { Result.failure() })
.doOnError {
if (it is NoSelectedCityException) {
applicationContext.cancelNotificationById(WEATHER_NOTIFICATION_ID)
WorkerUtil.cancelUpdateDailyWeatherWorkWorkRequest()
}
debug("[FAILURE] doWork $it", tag)
}
.map { Result.success(workDataOf("RESULT" to "Update daily success")) }
.onErrorReturn { Result.failure(workDataOf("RESULT" to "Update daily failure: ${it.message}")) }
}

companion object {
Expand Down
119 changes: 85 additions & 34 deletions app/src/main/java/com/hoc/weatherapp/worker/WorkerUtil.kt
Original file line number Diff line number Diff line change
@@ -1,16 +1,52 @@
package com.hoc.weatherapp.worker

import androidx.work.*
import android.content.Context
import androidx.work.ExistingPeriodicWorkPolicy
import androidx.work.ListenableWorker
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.Operation
import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkManager
import androidx.work.Worker
import androidx.work.WorkerParameters
import androidx.work.workDataOf
import com.hoc.weatherapp.utils.debug
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit

object WorkerUtil {
private val backgroundExecutor by lazy { Executors.newSingleThreadExecutor() }
private const val tag = "__worker__"
private val backgroundExecutor = Executors.newSingleThreadExecutor()

private fun enqueuePeriodicWorkRequestWithInitialDelay(tag: String): Operation {
/**
* Actual
*/
private inline fun <reified T : ListenableWorker> enqueuePeriodic(
tag: String,
uniqueName: String
): Operation {
val request = PeriodicWorkRequestBuilder<T>(
repeatInterval = 15,
repeatIntervalTimeUnit = TimeUnit.MINUTES
).addTag(tag).keepResultsForAtLeast(30, TimeUnit.MINUTES).build()

return WorkManager
.getInstance()
.enqueueUniquePeriodicWork(
uniqueName,
ExistingPeriodicWorkPolicy.REPLACE,
request
)
}

/**
* Enqueue initial delay one time work request, will trigger periodic work request
*/
private fun enqueue(tag: String): Operation {
val workRequest = OneTimeWorkRequestBuilder<InitialDelayEnqueueWorker>()
.setInitialDelay(15, TimeUnit.MINUTES)
.setInputData(workDataOf("TAG" to tag))
.keepResultsForAtLeast(30, TimeUnit.MINUTES)
.addTag(tag)
.build()

Expand All @@ -19,55 +55,70 @@ object WorkerUtil {
.enqueue(workRequest)
}

private fun cancelAllWorkByTag(tag: String): Operation = WorkManager
.getInstance()
.cancelAllWorkByTag(tag)

internal fun enqueueUpdateCurrentWeatherWorkRequestImmediately(): Operation {
val updateCurrentWeather = PeriodicWorkRequestBuilder<UpdateCurrentWeatherWorker>(
repeatInterval = 15,
repeatIntervalTimeUnit = TimeUnit.MINUTES
).addTag(UpdateCurrentWeatherWorker.TAG).build()

private fun cancelAllWorkByTag(tag: String): Operation {
return WorkManager
.getInstance()
.enqueueUniquePeriodicWork(
UpdateCurrentWeatherWorker.UNIQUE_WORK_NAME,
ExistingPeriodicWorkPolicy.REPLACE,
updateCurrentWeather
)
.cancelAllWorkByTag(tag)
}

internal fun enqueueUpdateDailyWeatherWorkRequestImmediately(): Operation {
val updateDailyWeathers = PeriodicWorkRequestBuilder<UpdateDailyWeatherWorker>(
repeatInterval = 15,
repeatIntervalTimeUnit = TimeUnit.MINUTES
).addTag(UpdateDailyWeatherWorker.TAG).build()

return WorkManager
.getInstance()
.enqueueUniquePeriodicWork(
UpdateDailyWeatherWorker.UNIQUE_WORK_NAME,
ExistingPeriodicWorkPolicy.REPLACE,
updateDailyWeathers
)
private class InitialDelayEnqueueWorker(context: Context, workerParams: WorkerParameters) :
Worker(context, workerParams) {
override fun doWork(): Result {
return when (inputData.getString("TAG")) {
UpdateDailyWeatherWorker.TAG -> {
Result
.success()
.also {
WorkerUtil.enqueuePeriodic<UpdateCurrentWeatherWorker>(
UpdateCurrentWeatherWorker.TAG,
UpdateCurrentWeatherWorker.UNIQUE_WORK_NAME
).result.get()
debug("[SUCCESS] enqueuePeriodic current", tag)
}
}
UpdateCurrentWeatherWorker.TAG -> {
Result
.success()
.also {
WorkerUtil.enqueuePeriodic<UpdateDailyWeatherWorker>(
UpdateDailyWeatherWorker.TAG,
UpdateDailyWeatherWorker.UNIQUE_WORK_NAME
).result.get()
debug("[SUCCESS] enqueuePeriodic daily", tag)
}
}
else -> Result.failure()
}
}
}

/**
*
*/

@JvmStatic
fun enqueueUpdateCurrentWeatherWorkRequest() {
cancelUpdateCurrentWeatherWorkRequest()
.result
.addListener(Runnable {
enqueuePeriodicWorkRequestWithInitialDelay(UpdateCurrentWeatherWorker.TAG)
enqueue(UpdateCurrentWeatherWorker.TAG)
.result
.addListener(Runnable {
debug("[SUCCESS] enqueue current", tag)
}, backgroundExecutor)
}, backgroundExecutor)
}

@JvmStatic
fun enqueueUpdateDailyWeatherWorkWorkRequest() {
fun enqueueUpdateDailyWeatherWorkRequest() {
cancelUpdateDailyWeatherWorkWorkRequest()
.result
.addListener(Runnable {
enqueuePeriodicWorkRequestWithInitialDelay(UpdateDailyWeatherWorker.TAG)
enqueue(UpdateDailyWeatherWorker.TAG)
.result
.addListener(Runnable {
debug("[SUCCESS] enqueue daily", tag)
}, backgroundExecutor)
}, backgroundExecutor)
}

Expand Down
8 changes: 4 additions & 4 deletions app/src/release/res/values/google_maps_api.xml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
<resources>
<!--
TODO: Before you release your application, you need enqueueUpdateCurrentWeatherWorkRequestImmediately Google Maps API key.
TODO: Before you release your application, you need enqueuePeriodic Google Maps API key.
To do this, you can either add your release key credentials to your existing
key, or create enqueueUpdateCurrentWeatherWorkRequestImmediately new key.
key, or create enqueuePeriodic new key.
Note that this file specifies the API key for the release build target.
If you have previously set up enqueueUpdateCurrentWeatherWorkRequestImmediately key for the debug target with the debug signing certificate,
you will also need to set up enqueueUpdateCurrentWeatherWorkRequestImmediately key for your release certificate.
If you have previously set up enqueuePeriodic key for the debug target with the debug signing certificate,
you will also need to set up enqueuePeriodic key for your release certificate.
Follow the directions here:
Expand Down
Binary file added screenshots/Screenshot_20190304-054656.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added screenshots/Screenshot_20190304-054704.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit b564191

Please sign in to comment.