From 9e1fe4bb7c692626c9aa336bebcb6c26ca49ea48 Mon Sep 17 00:00:00 2001 From: Allan Wang Date: Mon, 24 Dec 2018 17:27:43 -0500 Subject: Convert notification service to coroutines --- .../frost/services/NotificationService.kt | 88 ++++++++++++---------- .../com/pitchedapps/frost/utils/AdBlocker.kt | 7 +- 2 files changed, 51 insertions(+), 44 deletions(-) diff --git a/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationService.kt b/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationService.kt index 4ede5163..ea215b5c 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationService.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationService.kt @@ -27,8 +27,13 @@ import com.pitchedapps.frost.dbflow.loadFbCookiesSync import com.pitchedapps.frost.utils.L import com.pitchedapps.frost.utils.Prefs import com.pitchedapps.frost.utils.frostEvent -import org.jetbrains.anko.doAsync -import java.util.concurrent.Future +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.async +import kotlinx.coroutines.launch +import kotlinx.coroutines.suspendCancellableCoroutine +import kotlin.coroutines.CoroutineContext /** * Created by Allan Wang on 2017-06-14. @@ -38,68 +43,69 @@ import java.util.concurrent.Future * * All fetching is done through parsers */ -class NotificationService : JobService() { +class NotificationService : JobService(), CoroutineScope { - private var future: Future? = null + private lateinit var job: Job + override val coroutineContext: CoroutineContext + get() = Dispatchers.Main + job private val startTime = System.currentTimeMillis() override fun onStopJob(params: JobParameters?): Boolean { - val time = System.currentTimeMillis() - startTime - L.d { "Notification service has finished abruptly in $time ms" } - frostEvent( - "NotificationTime", - "Type" to "Service force stop", - "IM Included" to Prefs.notificationsInstantMessages, - "Duration" to time - ) - future?.cancel(true) - future = null + prepareFinish(true) return false } - fun finish(params: JobParameters?) { + private fun prepareFinish(abrupt: Boolean) { val time = System.currentTimeMillis() - startTime - L.i { "Notification service has finished in $time ms" } + L.i { "Notification service has ${if (abrupt) "finished abruptly" else "finished"} in $time ms" } frostEvent( "NotificationTime", - "Type" to "Service", + "Type" to (if (abrupt) "Service force stop" else "Service"), "IM Included" to Prefs.notificationsInstantMessages, "Duration" to time ) - jobFinished(params, false) - future?.cancel(true) - future = null + job.cancel() } override fun onStartJob(params: JobParameters?): Boolean { L.i { "Fetching notifications" } - future = doAsync { - val currentId = Prefs.userId - val cookies = loadFbCookiesSync() - val jobId = params?.extras?.getInt(NOTIFICATION_PARAM_ID, -1) ?: -1 - var notifCount = 0 - cookies.forEach { - val current = it.id == currentId - if (Prefs.notificationsGeneral && - (current || Prefs.notificationAllAccounts) - ) - notifCount += fetch(jobId, NotificationType.GENERAL, it) - if (Prefs.notificationsInstantMessages && - (current || Prefs.notificationsImAllAccounts) - ) - notifCount += fetch(jobId, NotificationType.MESSAGE, it) + job = Job() + launch { + try { + async { sendNotifications(params) }.await() + } finally { + prepareFinish(false) + jobFinished(params, false) } - - L.i { "Sent $notifCount notifications" } - if (notifCount == 0 && jobId == NOTIFICATION_JOB_NOW) - generalNotification(665, R.string.no_new_notifications, BuildConfig.DEBUG) - - finish(params) } return true } + private suspend fun sendNotifications(params: JobParameters?): Unit = suspendCancellableCoroutine { cont -> + val currentId = Prefs.userId + val cookies = loadFbCookiesSync() + if (cont.isCancelled) return@suspendCancellableCoroutine + val jobId = params?.extras?.getInt(NOTIFICATION_PARAM_ID, -1) ?: -1 + var notifCount = 0 + for (cookie in cookies) { + if (cont.isCancelled) break + val current = cookie.id == currentId + if (Prefs.notificationsGeneral && + (current || Prefs.notificationAllAccounts) + ) + notifCount += fetch(jobId, NotificationType.GENERAL, cookie) + if (Prefs.notificationsInstantMessages && + (current || Prefs.notificationsImAllAccounts) + ) + notifCount += fetch(jobId, NotificationType.MESSAGE, cookie) + } + + L.i { "Sent $notifCount notifications" } + if (notifCount == 0 && jobId == NOTIFICATION_JOB_NOW) + generalNotification(665, R.string.no_new_notifications, BuildConfig.DEBUG) + } + /** * Implemented fetch to also notify when an error occurs * Also normalized the output to return the number of notifications received diff --git a/app/src/main/kotlin/com/pitchedapps/frost/utils/AdBlocker.kt b/app/src/main/kotlin/com/pitchedapps/frost/utils/AdBlocker.kt index 61a90024..d14c6cd3 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/utils/AdBlocker.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/AdBlocker.kt @@ -19,8 +19,9 @@ package com.pitchedapps.frost.utils import android.content.Context import android.text.TextUtils import ca.allanwang.kau.utils.use +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch import okhttp3.HttpUrl -import org.jetbrains.anko.doAsync /** * Created by Allan Wang on 2017-09-24. @@ -38,7 +39,7 @@ open class AdBlocker(val assetPath: String) { val data: MutableSet = mutableSetOf() fun init(context: Context) { - doAsync { + GlobalScope.launch { val content = context.assets.open(assetPath).bufferedReader().use { f -> f.readLines().filter { !it.startsWith("#") } } @@ -58,7 +59,7 @@ open class AdBlocker(val assetPath: String) { return false val index = host.indexOf(".") if (index < 0 || index + 1 < host.length) return false - if (host.contains(host)) return true + if (data.contains(host)) return true return isAdHost(host.substring(index + 1)) } } -- cgit v1.2.3