mirror of https://github.com/M66B/FairEmail.git
156 lines
5.2 KiB
Kotlin
156 lines
5.2 KiB
Kotlin
package com.bugsnag.android
|
|
|
|
import android.content.BroadcastReceiver
|
|
import android.content.Context
|
|
import android.content.Intent
|
|
import android.content.IntentFilter
|
|
import android.net.ConnectivityManager
|
|
import android.net.Network
|
|
import android.net.NetworkCapabilities
|
|
import android.os.Build
|
|
import androidx.annotation.RequiresApi
|
|
|
|
internal typealias NetworkChangeCallback = (hasConnection: Boolean, networkState: String) -> Unit
|
|
|
|
internal interface Connectivity {
|
|
fun registerForNetworkChanges()
|
|
fun unregisterForNetworkChanges()
|
|
fun hasNetworkConnection(): Boolean
|
|
fun retrieveNetworkAccessState(): String
|
|
}
|
|
|
|
internal class ConnectivityCompat(
|
|
context: Context,
|
|
callback: NetworkChangeCallback?
|
|
) : Connectivity {
|
|
|
|
private val cm = context.getConnectivityManager()
|
|
|
|
private val connectivity: Connectivity =
|
|
when {
|
|
cm == null -> UnknownConnectivity
|
|
Build.VERSION.SDK_INT >= Build.VERSION_CODES.N -> ConnectivityApi24(cm, callback)
|
|
else -> ConnectivityLegacy(context, cm, callback)
|
|
}
|
|
|
|
override fun registerForNetworkChanges() {
|
|
runCatching { connectivity.registerForNetworkChanges() }
|
|
}
|
|
|
|
override fun hasNetworkConnection(): Boolean {
|
|
val result = runCatching { connectivity.hasNetworkConnection() }
|
|
return result.getOrElse { true } // allow network requests to be made if state unknown
|
|
}
|
|
|
|
override fun unregisterForNetworkChanges() {
|
|
runCatching { connectivity.unregisterForNetworkChanges() }
|
|
}
|
|
|
|
override fun retrieveNetworkAccessState(): String {
|
|
val result = runCatching { connectivity.retrieveNetworkAccessState() }
|
|
return result.getOrElse { "unknown" }
|
|
}
|
|
}
|
|
|
|
@Suppress("DEPRECATION")
|
|
internal class ConnectivityLegacy(
|
|
private val context: Context,
|
|
private val cm: ConnectivityManager,
|
|
callback: NetworkChangeCallback?
|
|
) : Connectivity {
|
|
|
|
private val changeReceiver = ConnectivityChangeReceiver(callback)
|
|
|
|
private val activeNetworkInfo: android.net.NetworkInfo?
|
|
get() = try {
|
|
cm.activeNetworkInfo
|
|
} catch (e: NullPointerException) {
|
|
// in some rare cases we get a remote NullPointerException via Parcel.readException
|
|
null
|
|
}
|
|
|
|
override fun registerForNetworkChanges() {
|
|
val intentFilter = IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)
|
|
context.registerReceiverSafe(changeReceiver, intentFilter)
|
|
}
|
|
|
|
override fun unregisterForNetworkChanges() = context.unregisterReceiverSafe(changeReceiver)
|
|
|
|
override fun hasNetworkConnection(): Boolean {
|
|
return activeNetworkInfo?.isConnectedOrConnecting ?: false
|
|
}
|
|
|
|
override fun retrieveNetworkAccessState(): String {
|
|
return when (activeNetworkInfo?.type) {
|
|
null -> "none"
|
|
ConnectivityManager.TYPE_WIFI -> "wifi"
|
|
ConnectivityManager.TYPE_ETHERNET -> "ethernet"
|
|
else -> "cellular" // all other types are cellular in some form
|
|
}
|
|
}
|
|
|
|
private inner class ConnectivityChangeReceiver(private val cb: NetworkChangeCallback?) :
|
|
BroadcastReceiver() {
|
|
override fun onReceive(context: Context, intent: Intent) {
|
|
cb?.invoke(hasNetworkConnection(), retrieveNetworkAccessState())
|
|
}
|
|
}
|
|
}
|
|
|
|
@RequiresApi(Build.VERSION_CODES.N)
|
|
internal class ConnectivityApi24(
|
|
private val cm: ConnectivityManager,
|
|
callback: NetworkChangeCallback?
|
|
) : Connectivity {
|
|
|
|
private val networkCallback = ConnectivityTrackerCallback(callback)
|
|
|
|
override fun registerForNetworkChanges() = cm.registerDefaultNetworkCallback(networkCallback)
|
|
override fun unregisterForNetworkChanges() = cm.unregisterNetworkCallback(networkCallback)
|
|
override fun hasNetworkConnection() = cm.activeNetwork != null
|
|
|
|
override fun retrieveNetworkAccessState(): String {
|
|
val network = cm.activeNetwork
|
|
val capabilities = if (network != null) cm.getNetworkCapabilities(network) else null
|
|
|
|
return when {
|
|
capabilities == null -> "none"
|
|
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) -> "wifi"
|
|
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> "ethernet"
|
|
capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) -> "cellular"
|
|
else -> "unknown"
|
|
}
|
|
}
|
|
|
|
private inner class ConnectivityTrackerCallback(private val cb: NetworkChangeCallback?) :
|
|
ConnectivityManager.NetworkCallback() {
|
|
override fun onUnavailable() {
|
|
super.onUnavailable()
|
|
cb?.invoke(false, retrieveNetworkAccessState())
|
|
}
|
|
|
|
override fun onAvailable(network: Network) {
|
|
super.onAvailable(network)
|
|
cb?.invoke(true, retrieveNetworkAccessState())
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Connectivity used in cases where we cannot access the system ConnectivityManager.
|
|
* We assume that there is some sort of network and do not attempt to report any network changes.
|
|
*/
|
|
internal object UnknownConnectivity : Connectivity {
|
|
override fun registerForNetworkChanges() {}
|
|
|
|
override fun unregisterForNetworkChanges() {}
|
|
|
|
override fun hasNetworkConnection(): Boolean {
|
|
return true
|
|
}
|
|
|
|
override fun retrieveNetworkAccessState(): String {
|
|
return "unknown"
|
|
}
|
|
}
|