Roll our own NetworkObserver
This commit is contained in:
parent
6348d0a6fb
commit
52d19d3ea2
@ -76,7 +76,6 @@ dependencies {
|
||||
|
||||
implementation("com.github.topjohnwu:jtar:1.0.0")
|
||||
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:rxkotlin:2.4.0")
|
||||
|
@ -1,15 +1,15 @@
|
||||
package com.topjohnwu.magisk.core
|
||||
|
||||
import androidx.databinding.ObservableField
|
||||
import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork
|
||||
import com.topjohnwu.magisk.DynAPK
|
||||
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.subscribeK
|
||||
import com.topjohnwu.magisk.extensions.value
|
||||
import com.topjohnwu.magisk.utils.CachedValue
|
||||
import com.topjohnwu.superuser.Shell
|
||||
import com.topjohnwu.superuser.ShellUtils.fastCmd
|
||||
import com.topjohnwu.superuser.internal.UiThreadHandler
|
||||
import java.io.FileInputStream
|
||||
import java.io.IOException
|
||||
|
||||
@ -37,9 +37,8 @@ object Info {
|
||||
|
||||
val isConnected by lazy {
|
||||
ObservableField(false).also { field ->
|
||||
ReactiveNetwork.observeNetworkConnectivity(get())
|
||||
.subscribeK {
|
||||
field.value = it.available()
|
||||
NetworkObserver.observe(get()) {
|
||||
UiThreadHandler.run { field.value = it.isAvailable }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,47 @@
|
||||
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()
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
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))
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
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))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
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)
|
||||
|
Loading…
Reference in New Issue
Block a user