mirror of
https://github.com/afollestad/nock-nock.git
synced 2025-08-06 16:08:39 +00:00
Ensure we have scheduled jobs when the system boots or when the app starts.
This commit is contained in:
parent
d1672a6c5e
commit
eeaa68dbe2
7 changed files with 100 additions and 1 deletions
|
@ -46,6 +46,13 @@
|
||||||
android:label="@string/check_service_name"
|
android:label="@string/check_service_name"
|
||||||
android:permission="android.permission.BIND_JOB_SERVICE"/>
|
android:permission="android.permission.BIND_JOB_SERVICE"/>
|
||||||
|
|
||||||
|
<receiver android:name=".engine.statuscheck.BootReceiver">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.BOOT_COMPLETED"/>
|
||||||
|
</intent-filter>
|
||||||
|
</receiver>
|
||||||
|
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|
|
@ -11,6 +11,7 @@ import android.app.job.JobScheduler
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import com.afollestad.nocknock.di.AppComponent
|
import com.afollestad.nocknock.di.AppComponent
|
||||||
import com.afollestad.nocknock.di.DaggerAppComponent
|
import com.afollestad.nocknock.di.DaggerAppComponent
|
||||||
|
import com.afollestad.nocknock.engine.statuscheck.BootReceiver
|
||||||
import com.afollestad.nocknock.engine.statuscheck.CheckStatusJob
|
import com.afollestad.nocknock.engine.statuscheck.CheckStatusJob
|
||||||
import com.afollestad.nocknock.ui.AddSiteActivity
|
import com.afollestad.nocknock.ui.AddSiteActivity
|
||||||
import com.afollestad.nocknock.ui.MainActivity
|
import com.afollestad.nocknock.ui.MainActivity
|
||||||
|
@ -51,6 +52,7 @@ class App : Application(), Injector {
|
||||||
is ViewSiteActivity -> appComponent.inject(target)
|
is ViewSiteActivity -> appComponent.inject(target)
|
||||||
is AddSiteActivity -> appComponent.inject(target)
|
is AddSiteActivity -> appComponent.inject(target)
|
||||||
is CheckStatusJob -> appComponent.inject(target)
|
is CheckStatusJob -> appComponent.inject(target)
|
||||||
|
is BootReceiver -> appComponent.inject(target)
|
||||||
else -> throw IllegalStateException("Can't inject into $target")
|
else -> throw IllegalStateException("Can't inject into $target")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import android.app.Application
|
||||||
import android.app.NotificationManager
|
import android.app.NotificationManager
|
||||||
import android.app.job.JobScheduler
|
import android.app.job.JobScheduler
|
||||||
import com.afollestad.nocknock.engine.EngineModule
|
import com.afollestad.nocknock.engine.EngineModule
|
||||||
|
import com.afollestad.nocknock.engine.statuscheck.BootReceiver
|
||||||
import com.afollestad.nocknock.engine.statuscheck.CheckStatusJob
|
import com.afollestad.nocknock.engine.statuscheck.CheckStatusJob
|
||||||
import com.afollestad.nocknock.notifications.NotificationsModule
|
import com.afollestad.nocknock.notifications.NotificationsModule
|
||||||
import com.afollestad.nocknock.ui.AddSiteActivity
|
import com.afollestad.nocknock.ui.AddSiteActivity
|
||||||
|
@ -40,6 +41,8 @@ interface AppComponent {
|
||||||
|
|
||||||
fun inject(job: CheckStatusJob)
|
fun inject(job: CheckStatusJob)
|
||||||
|
|
||||||
|
fun inject(bootReceiver: BootReceiver)
|
||||||
|
|
||||||
@Component.Builder
|
@Component.Builder
|
||||||
interface Builder {
|
interface Builder {
|
||||||
|
|
||||||
|
|
|
@ -112,7 +112,17 @@ class MainActivity : AppCompatActivity(), View.OnClickListener {
|
||||||
list.addItemDecoration(DividerItemDecoration(this, VERTICAL))
|
list.addItemDecoration(DividerItemDecoration(this, VERTICAL))
|
||||||
|
|
||||||
fab.setOnClickListener(this)
|
fab.setOnClickListener(this)
|
||||||
|
|
||||||
notificationManager.createChannels()
|
notificationManager.createChannels()
|
||||||
|
ensureCheckJobs()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun ensureCheckJobs() {
|
||||||
|
rootView.scopeWhileAttached(IO) {
|
||||||
|
launch(coroutineContext) {
|
||||||
|
checkStatusManager.ensureScheduledChecks()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* Licensed under Apache-2.0
|
||||||
|
*
|
||||||
|
* Designed and developed by Aidan Follestad (@afollestad)
|
||||||
|
*/
|
||||||
|
package com.afollestad.nocknock.engine.statuscheck
|
||||||
|
|
||||||
|
import android.content.BroadcastReceiver
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.Intent.ACTION_BOOT_COMPLETED
|
||||||
|
import android.util.Log
|
||||||
|
import com.afollestad.nocknock.engine.BuildConfig
|
||||||
|
import com.afollestad.nocknock.utilities.ext.injector
|
||||||
|
import kotlinx.coroutines.Dispatchers.IO
|
||||||
|
import kotlinx.coroutines.Dispatchers.Main
|
||||||
|
import kotlinx.coroutines.GlobalScope
|
||||||
|
import kotlinx.coroutines.async
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
/** @author Aidan Follestad (afollestad) */
|
||||||
|
class BootReceiver : BroadcastReceiver() {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private fun log(message: String) {
|
||||||
|
if (BuildConfig.DEBUG) {
|
||||||
|
Log.d("BootReceiver", message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject lateinit var checkStatusManager: CheckStatusManager
|
||||||
|
|
||||||
|
override fun onReceive(
|
||||||
|
context: Context,
|
||||||
|
intent: Intent
|
||||||
|
) {
|
||||||
|
require(ACTION_BOOT_COMPLETED == intent.action) {
|
||||||
|
"BootReceiver should only receive ACTION_BOOT_COMPLETED intents."
|
||||||
|
}
|
||||||
|
|
||||||
|
log("Received boot event! Let's go.")
|
||||||
|
context.injector()
|
||||||
|
.injectInto(this)
|
||||||
|
|
||||||
|
val pendingResult = goAsync()
|
||||||
|
GlobalScope.launch(Main) {
|
||||||
|
async(IO) { checkStatusManager.ensureScheduledChecks() }.await()
|
||||||
|
pendingResult.resultCode = 0
|
||||||
|
pendingResult.finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,6 +15,7 @@ import com.afollestad.nocknock.data.ServerModel
|
||||||
import com.afollestad.nocknock.data.ServerStatus.ERROR
|
import com.afollestad.nocknock.data.ServerStatus.ERROR
|
||||||
import com.afollestad.nocknock.data.ServerStatus.OK
|
import com.afollestad.nocknock.data.ServerStatus.OK
|
||||||
import com.afollestad.nocknock.engine.R
|
import com.afollestad.nocknock.engine.R
|
||||||
|
import com.afollestad.nocknock.engine.db.ServerModelStore
|
||||||
import com.afollestad.nocknock.engine.statuscheck.CheckStatusJob.Companion.KEY_SITE_ID
|
import com.afollestad.nocknock.engine.statuscheck.CheckStatusJob.Companion.KEY_SITE_ID
|
||||||
import com.afollestad.nocknock.utilities.BuildConfig
|
import com.afollestad.nocknock.utilities.BuildConfig
|
||||||
import com.afollestad.nocknock.utilities.providers.StringProvider
|
import com.afollestad.nocknock.utilities.providers.StringProvider
|
||||||
|
@ -33,6 +34,8 @@ data class CheckResult(
|
||||||
/** @author Aidan Follestad (afollestad) */
|
/** @author Aidan Follestad (afollestad) */
|
||||||
interface CheckStatusManager {
|
interface CheckStatusManager {
|
||||||
|
|
||||||
|
suspend fun ensureScheduledChecks()
|
||||||
|
|
||||||
fun scheduleCheck(
|
fun scheduleCheck(
|
||||||
site: ServerModel,
|
site: ServerModel,
|
||||||
rightNow: Boolean = false
|
rightNow: Boolean = false
|
||||||
|
@ -47,7 +50,8 @@ class RealCheckStatusManager @Inject constructor(
|
||||||
private val app: Application,
|
private val app: Application,
|
||||||
private val jobScheduler: JobScheduler,
|
private val jobScheduler: JobScheduler,
|
||||||
private val okHttpClient: OkHttpClient,
|
private val okHttpClient: OkHttpClient,
|
||||||
private val stringProvider: StringProvider
|
private val stringProvider: StringProvider,
|
||||||
|
private val siteStore: ServerModelStore
|
||||||
) : CheckStatusManager {
|
) : CheckStatusManager {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -59,6 +63,25 @@ class RealCheckStatusManager @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun ensureScheduledChecks() {
|
||||||
|
val sites = siteStore.get()
|
||||||
|
if (sites.isEmpty()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log("Ensuring sites have scheduled checks.")
|
||||||
|
|
||||||
|
sites.forEach { site ->
|
||||||
|
val existingJob = jobScheduler.allPendingJobs
|
||||||
|
.firstOrNull { job -> job.id == site.id }
|
||||||
|
if (existingJob == null) {
|
||||||
|
log("Site ${site.id} does NOT have a scheduled job, running one now.")
|
||||||
|
scheduleCheck(site, rightNow = true)
|
||||||
|
} else {
|
||||||
|
log("Site ${site.id} already has a scheduled job. Nothing to do.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun scheduleCheck(
|
override fun scheduleCheck(
|
||||||
site: ServerModel,
|
site: ServerModel,
|
||||||
rightNow: Boolean
|
rightNow: Boolean
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue