Skip to content

Instantly share code, notes, and snippets.

@clydebarrow
Last active March 5, 2021 02:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save clydebarrow/efae37c762aa951c79e4f7fb090f17ee to your computer and use it in GitHub Desktop.
Save clydebarrow/efae37c762aa951c79e4f7fb090f17ee to your computer and use it in GitHub Desktop.
Check network reachability on iOS using RoboVM in Kotlin
package com.controlj.framework
import com.controlj.rx.DisposedEmitter
import io.reactivex.rxjava3.core.Observable
import io.reactivex.rxjava3.core.ObservableEmitter
import io.reactivex.rxjava3.schedulers.Schedulers
import org.robovm.apple.dispatch.DispatchQueue
import org.robovm.apple.foundation.NSOperatingSystemVersion
import org.robovm.apple.foundation.NSProcessInfo
import org.robovm.apple.network.NWPathMonitor
import org.robovm.apple.network.NWPathStatus
import java.net.InetAddress
import java.util.concurrent.TimeUnit
object NetworkStatus {
val iOS13 = NSOperatingSystemVersion(13, 0, 0)
val iOS12 = NSOperatingSystemVersion(12, 0, 0)
val iOS11 = NSOperatingSystemVersion(11, 0, 0)
val iOS10 = NSOperatingSystemVersion(10, 0, 0)
fun isOSVersionOrLater(version: NSOperatingSystemVersion): Boolean {
return NSProcessInfo.getSharedProcessInfo().isOperatingSystemAtLeastVersion(version)
}
val isIos13 = isOSVersionOrLater(iOS13)
val isIos12 = isOSVersionOrLater(iOS12)
val isIos11 = isOSVersionOrLater(iOS11)
val isIos10 = isOSVersionOrLater(iOS10)
val isSimulator: Boolean by lazy {
NSProcessInfo.getSharedProcessInfo().environment.containsKey("SIMULATOR_DEVICE_NAME")
}
const val NETWORK_INTERVAL = 60L // check network this often if required.
val NETWORK_TIME_UNIT = TimeUnit.SECONDS
const val NETWORK_TARGET = "google.com"
var networkEmitter: ObservableEmitter<Boolean> = DisposedEmitter()
private set
var networkReady = true
/**
* Listen for changes in network status.
*/
val networkObserver = Observable.create<Boolean> {
networkEmitter = it
}.share()
init {
if (isIos12) {
try {
val monitor = NWPathMonitor()
monitor.setQueue(DispatchQueue.getMainQueue())
monitor.setUpdateHandler { path ->
networkReady = path.status == NWPathStatus.satisfied
networkEmitter.onNext(networkReady)
}
monitor.start()
} catch (ex: Throwable) {
//logException(ex)
}
}
}
/** Check network availability for the given target. This will emit on initial call, every 60 seconds,
* or when there is a change in network status. It queries both the platform network monitor and does
* a DNS lookup to confirm actual reachability.
*
*/
fun isNetworkAvailable(target: String = NETWORK_TARGET): Observable<Boolean> {
return Observable.merge(
networkObserver, Observable.interval(
0L,
NETWORK_INTERVAL,
NETWORK_TIME_UNIT,
Schedulers.io()
)
)
.map {
if (!networkReady)
false
else
try {
InetAddress.getByName(target)
true
} catch (ex: Exception) {
false
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment