DownloadJob: Network check changes (#10242)

Mostly pulled from WorkManager
This commit is contained in:
Ivan Iskandar 2023-12-17 21:57:55 +07:00 committed by GitHub
parent 387159b5af
commit f9b57800b1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 101 additions and 19 deletions

View File

@ -13,13 +13,17 @@ import androidx.work.WorkManager
import androidx.work.WorkerParameters
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.notification.Notifications
import eu.kanade.tachiyomi.util.system.isConnectedToWifi
import eu.kanade.tachiyomi.util.system.isOnline
import eu.kanade.tachiyomi.util.system.NetworkState
import eu.kanade.tachiyomi.util.system.activeNetworkState
import eu.kanade.tachiyomi.util.system.networkStateFlow
import eu.kanade.tachiyomi.util.system.notificationBuilder
import eu.kanade.tachiyomi.util.system.setForegroundSafely
import kotlinx.coroutines.delay
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combineTransform
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import tachiyomi.domain.download.service.DownloadPreferences
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
@ -50,7 +54,11 @@ class DownloadJob(context: Context, workerParams: WorkerParameters) : CoroutineW
}
override suspend fun doWork(): Result {
var active = checkConnectivity() && downloadManager.downloaderStart()
var networkCheck = checkNetworkState(
applicationContext.activeNetworkState(),
downloadPreferences.downloadOnlyOverWifi().get(),
)
var active = networkCheck && downloadManager.downloaderStart()
if (!active) {
return Result.failure()
@ -58,19 +66,27 @@ class DownloadJob(context: Context, workerParams: WorkerParameters) : CoroutineW
setForegroundSafely()
coroutineScope {
combineTransform(
applicationContext.networkStateFlow(),
downloadPreferences.downloadOnlyOverWifi().changes(),
transform = { a, b -> emit(checkNetworkState(a, b)) },
)
.onEach { networkCheck = it }
.launchIn(this)
}
// Keep the worker running when needed
while (active) {
delay(100)
active = !isStopped && downloadManager.isRunning && checkConnectivity()
active = !isStopped && downloadManager.isRunning && networkCheck
}
return Result.success()
}
private fun checkConnectivity(): Boolean {
return with(applicationContext) {
if (isOnline()) {
val noWifi = downloadPreferences.downloadOnlyOverWifi().get() && !isConnectedToWifi()
private fun checkNetworkState(state: NetworkState, requireWifi: Boolean): Boolean {
return if (state.isOnline) {
val noWifi = requireWifi && !state.isWifi
if (noWifi) {
downloadManager.downloaderStop(
applicationContext.getString(R.string.download_notifier_text_only_wifi),
@ -82,7 +98,6 @@ class DownloadJob(context: Context, workerParams: WorkerParameters) : CoroutineW
false
}
}
}
companion object {
private const val TAG = "Downloader"

View File

@ -0,0 +1,67 @@
package eu.kanade.tachiyomi.util.system
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.net.ConnectivityManager
import android.net.ConnectivityManager.NetworkCallback
import android.net.Network
import android.net.NetworkCapabilities
import android.os.Build
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.callbackFlow
data class NetworkState(
val isConnected: Boolean,
val isValidated: Boolean,
val isWifi: Boolean,
) {
val isOnline = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
isConnected && isValidated
} else {
isConnected
}
}
@Suppress("DEPRECATION")
fun Context.activeNetworkState(): NetworkState {
val capabilities = connectivityManager.getNetworkCapabilities(connectivityManager.activeNetwork)
return NetworkState(
isConnected = connectivityManager.activeNetworkInfo?.isConnected ?: false,
isValidated = capabilities?.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) ?: false,
isWifi = wifiManager.isWifiEnabled && capabilities?.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) ?: false,
)
}
@Suppress("DEPRECATION")
fun Context.networkStateFlow() = callbackFlow {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
val networkCallback = object : NetworkCallback() {
override fun onCapabilitiesChanged(network: Network, networkCapabilities: NetworkCapabilities) {
trySend(activeNetworkState())
}
override fun onLost(network: Network) {
trySend(activeNetworkState())
}
}
connectivityManager.registerDefaultNetworkCallback(networkCallback)
awaitClose {
connectivityManager.unregisterNetworkCallback(networkCallback)
}
} else {
val receiver = object : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
if (intent.action == ConnectivityManager.CONNECTIVITY_ACTION) {
trySend(activeNetworkState())
}
}
}
registerReceiver(receiver, IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION))
awaitClose {
unregisterReceiver(receiver)
}
}
}