Commit 52d19d3e authored by topjohnwu's avatar topjohnwu

Roll our own NetworkObserver

parent 6348d0a6
...@@ -76,7 +76,6 @@ dependencies { ...@@ -76,7 +76,6 @@ dependencies {
implementation("com.github.topjohnwu:jtar:1.0.0") implementation("com.github.topjohnwu:jtar:1.0.0")
implementation("com.jakewharton.timber:timber:4.7.1") implementation("com.jakewharton.timber:timber:4.7.1")
implementation("com.github.pwittchen:reactivenetwork-rx2:3.0.8")
implementation("io.reactivex.rxjava2:rxjava:2.2.19") implementation("io.reactivex.rxjava2:rxjava:2.2.19")
implementation("io.reactivex.rxjava2:rxkotlin:2.4.0") implementation("io.reactivex.rxjava2:rxkotlin:2.4.0")
......
package com.topjohnwu.magisk.core package com.topjohnwu.magisk.core
import androidx.databinding.ObservableField import androidx.databinding.ObservableField
import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork
import com.topjohnwu.magisk.DynAPK import com.topjohnwu.magisk.DynAPK
import com.topjohnwu.magisk.core.model.UpdateInfo import com.topjohnwu.magisk.core.model.UpdateInfo
import com.topjohnwu.magisk.core.net.NetworkObserver
import com.topjohnwu.magisk.extensions.get import com.topjohnwu.magisk.extensions.get
import com.topjohnwu.magisk.extensions.subscribeK
import com.topjohnwu.magisk.extensions.value import com.topjohnwu.magisk.extensions.value
import com.topjohnwu.magisk.utils.CachedValue import com.topjohnwu.magisk.utils.CachedValue
import com.topjohnwu.superuser.Shell import com.topjohnwu.superuser.Shell
import com.topjohnwu.superuser.ShellUtils.fastCmd import com.topjohnwu.superuser.ShellUtils.fastCmd
import com.topjohnwu.superuser.internal.UiThreadHandler
import java.io.FileInputStream import java.io.FileInputStream
import java.io.IOException import java.io.IOException
...@@ -37,10 +37,9 @@ object Info { ...@@ -37,10 +37,9 @@ object Info {
val isConnected by lazy { val isConnected by lazy {
ObservableField(false).also { field -> ObservableField(false).also { field ->
ReactiveNetwork.observeNetworkConnectivity(get()) NetworkObserver.observe(get()) {
.subscribeK { UiThreadHandler.run { field.value = it.isAvailable }
field.value = it.available() }
}
} }
} }
......
package com.topjohnwu.magisk.core.net
import android.net.ConnectivityManager
import android.net.Network
import android.net.NetworkInfo
import android.net.NetworkInfo.DetailedState
import androidx.annotation.RequiresApi
// Recreate NetworkInfo with Kotlin data class
data class Connectivity(
val state : NetworkInfo.State = NetworkInfo.State.DISCONNECTED,
val detailedState : DetailedState = DetailedState.IDLE,
val type : Int = -1,
val subType : Int = -1,
val isAvailable : Boolean = false,
val isFailover : Boolean = false,
val isRoaming : Boolean = false,
val typeName : String = "NONE",
val subTypeName : String = "NONE",
val reason : String? = null,
val extraInfo : String? = null
) {
private constructor(info: NetworkInfo) : this(
info.state,
info.detailedState,
info.type,
info.subtype,
info.isAvailable,
info.isFailover,
info.isRoaming,
info.typeName,
info.subtypeName,
info.reason,
info.extraInfo
)
companion object {
fun create(manager: ConnectivityManager): Connectivity {
return manager.activeNetworkInfo?.let { Connectivity(it) } ?: Connectivity()
}
@RequiresApi(21)
fun create(manager: ConnectivityManager, network: Network): Connectivity {
return manager.getNetworkInfo(network)?.let { Connectivity(it) } ?: Connectivity()
}
}
}
package com.topjohnwu.magisk.core.net
import android.annotation.TargetApi
import android.content.Context
import android.net.ConnectivityManager
import android.net.Network
import android.net.NetworkCapabilities
import android.net.NetworkRequest
@TargetApi(21)
open class LollipopNetworkObserver(
context: Context,
callback: NetInfoCallback
): NetworkObserver(context, callback) {
private val networkCallback = NetCallback()
init {
val request = NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.build()
manager.registerNetworkCallback(request, networkCallback)
}
override fun stopObserving() {
manager.unregisterNetworkCallback(networkCallback)
}
private inner class NetCallback : ConnectivityManager.NetworkCallback() {
override fun onAvailable(network: Network) {
emit(Connectivity.create(manager, network))
}
override fun onLost(network: Network) {
emit(Connectivity.create(manager, network))
}
}
}
package com.topjohnwu.magisk.core.net
import android.annotation.TargetApi
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.net.NetworkInfo
import android.os.PowerManager
import androidx.core.content.getSystemService
@TargetApi(23)
class MarshmallowNetworkObserver(
context: Context,
callback: NetInfoCallback
): LollipopNetworkObserver(context, callback) {
private val idleReceiver = IdleBroadcastReceiver()
init {
val filter = IntentFilter(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED)
context.registerReceiver(idleReceiver, filter)
}
override fun stopObserving() {
super.stopObserving()
context.unregisterReceiver(idleReceiver)
}
override fun emit(current: Connectivity) {
val typeChanged = last.type != current.type
val wasConnected = last.state == NetworkInfo.State.CONNECTED
val isDisconnected = current.state == NetworkInfo.State.DISCONNECTED
val isNotIdle = current.detailedState != NetworkInfo.DetailedState.IDLE
if (typeChanged && wasConnected && isDisconnected && isNotIdle) {
super.emit(current)
super.emit(last)
last = current
} else {
super.emit(current)
}
}
private inner class IdleBroadcastReceiver: BroadcastReceiver() {
private fun isIdleMode(context: Context): Boolean {
val packageName = context.packageName
val manager = context.getSystemService<PowerManager>()!!
val isIgnoringOptimizations = manager.isIgnoringBatteryOptimizations(packageName)
return manager.isDeviceIdleMode && !isIgnoringOptimizations
}
override fun onReceive(context: Context, intent: Intent) {
if (isIdleMode(context)) {
emit(Connectivity())
} else {
emit(Connectivity.create(manager))
}
}
}
}
package com.topjohnwu.magisk.core.net
import android.content.Context
import android.net.ConnectivityManager
import android.os.Build
import androidx.core.content.getSystemService
typealias NetInfoCallback = (Connectivity) -> Unit
abstract class NetworkObserver protected constructor(
context: Context,
private val callback: NetInfoCallback
) {
protected val context = context.applicationContext
protected val manager = context.getSystemService<ConnectivityManager>()!!
protected var last = Connectivity.create(manager)
init {
callback(last)
}
protected open fun emit(current: Connectivity) {
if (last != current)
callback(current)
last = current
}
protected abstract fun stopObserving()
companion object {
fun observe(context: Context, callback: NetInfoCallback): NetworkObserver {
return when (Build.VERSION.SDK_INT) {
in 23 until Int.MAX_VALUE -> MarshmallowNetworkObserver(context, callback)
in 21 until 23 -> LollipopNetworkObserver(context, callback)
else -> PreLollipopNetworkObserver(context, callback)
}
}
}
}
package com.topjohnwu.magisk.core.net
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.net.ConnectivityManager
class PreLollipopNetworkObserver(
context: Context,
callback: NetInfoCallback
): NetworkObserver(context, callback) {
private val receiver = ConnectivityBroadcastReceiver()
init {
val filter = IntentFilter()
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION)
context.registerReceiver(receiver, filter)
}
override fun stopObserving() {
context.unregisterReceiver(receiver)
}
private inner class ConnectivityBroadcastReceiver: BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
emit(Connectivity.create(manager))
}
}
}
package com.topjohnwu.magisk.extensions
import io.reactivex.Observable
import io.reactivex.Scheduler
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.schedulers.Schedulers
fun <T> Observable<T>.applySchedulers(
subscribeOn: Scheduler = Schedulers.io(),
observeOn: Scheduler = AndroidSchedulers.mainThread()
): Observable<T> = this.subscribeOn(subscribeOn).observeOn(observeOn)
/*=== ALIASES FOR OBSERVABLES ===*/
typealias OnCompleteListener = () -> Unit
typealias OnSuccessListener<T> = (T) -> Unit
typealias OnErrorListener = (Throwable) -> Unit
/*=== ALIASES FOR OBSERVABLES ===*/
fun <T> Observable<T>.subscribeK(
onError: OnErrorListener = { it.printStackTrace() },
onComplete: OnCompleteListener = {},
onNext: OnSuccessListener<T> = {}
) = applySchedulers()
.subscribe(onNext, onError, onComplete)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment