-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: react to network availability (#20)
* feat: react to network availability * Add tests for network availability * More network tests and encapsulating Android details * Remove unusued class and fixed compilation issues
- Loading branch information
1 parent
320fb08
commit 9ddcb19
Showing
7 changed files
with
251 additions
and
48 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
<?xml version="1.0" encoding="utf-8"?> | ||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"> | ||
<uses-permission android:name="android.permission.INTERNET" /> | ||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> | ||
</manifest> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
87 changes: 87 additions & 0 deletions
87
unleashandroidsdk/src/main/java/io/getunleash/android/http/NetworkStatusHelper.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
package io.getunleash.android.http | ||
|
||
import android.content.Context | ||
import android.net.ConnectivityManager | ||
import android.net.Network | ||
import android.net.NetworkCapabilities | ||
import android.net.NetworkRequest | ||
import android.os.Build | ||
import android.util.Log | ||
|
||
interface NetworkListener { | ||
fun onAvailable() | ||
fun onLost() | ||
} | ||
|
||
class NetworkStatusHelper(val context: Context) { | ||
companion object { | ||
private const val TAG = "NetworkState" | ||
} | ||
|
||
private val networkCallbacks = mutableListOf<ConnectivityManager.NetworkCallback>() | ||
|
||
fun registerNetworkListener(listener: NetworkListener) { | ||
val connectivityManager = getConnectivityManager() ?: return | ||
val networkRequest = NetworkRequest.Builder() | ||
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) | ||
.build() | ||
|
||
// wrap the listener in a NetworkCallback so the listener doesn't have to know about Android specifics | ||
val networkCallback = object : ConnectivityManager.NetworkCallback() { | ||
override fun onAvailable(network: Network) { | ||
listener.onAvailable() | ||
} | ||
|
||
override fun onLost(network: Network) { | ||
listener.onLost() | ||
} | ||
} | ||
|
||
connectivityManager.registerNetworkCallback(networkRequest, networkCallback) | ||
networkCallbacks += networkCallback | ||
} | ||
|
||
fun close () { | ||
val connectivityManager = getConnectivityManager() ?: return | ||
networkCallbacks.forEach { | ||
connectivityManager.unregisterNetworkCallback(it) | ||
} | ||
} | ||
|
||
private fun isNetworkAvailable(): Boolean { | ||
val connectivityManager = getConnectivityManager() ?: return true | ||
|
||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { | ||
val activeNetwork = connectivityManager.activeNetwork ?: return false | ||
val capabilities = | ||
connectivityManager.getNetworkCapabilities(activeNetwork) ?: return false | ||
return capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) && | ||
capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED) | ||
} else { | ||
@Suppress("DEPRECATION") | ||
val networkInfo = connectivityManager.activeNetworkInfo ?: return false | ||
@Suppress("DEPRECATION") | ||
return networkInfo.isConnected | ||
} | ||
} | ||
|
||
private fun getConnectivityManager(): ConnectivityManager? { | ||
val connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) | ||
if (connectivityManager !is ConnectivityManager) { | ||
Log.w(TAG, "Failed to get ConnectivityManager assuming network is available") | ||
return null | ||
} | ||
return connectivityManager | ||
} | ||
|
||
private fun isAirplaneModeOn(): Boolean { | ||
return android.provider.Settings.System.getInt( | ||
context.contentResolver, | ||
android.provider.Settings.Global.AIRPLANE_MODE_ON, 0 | ||
) != 0 | ||
} | ||
|
||
fun isAvailable(): Boolean { | ||
return !isAirplaneModeOn() && isNetworkAvailable() | ||
} | ||
} |
18 changes: 0 additions & 18 deletions
18
unleashandroidsdk/src/main/java/io/getunleash/android/metrics/MetricsSenderWorker.kt
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
57 changes: 57 additions & 0 deletions
57
unleashandroidsdk/src/test/java/io/getunleash/android/http/NetworkStatusHelperTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package io.getunleash.android.http | ||
|
||
import android.content.Context | ||
import android.net.ConnectivityManager | ||
import android.net.Network | ||
import android.net.NetworkCapabilities | ||
import android.net.NetworkInfo | ||
|
||
import io.getunleash.android.BaseTest | ||
import org.assertj.core.api.Assertions.assertThat | ||
import org.junit.Test | ||
import org.mockito.ArgumentMatchers.anyInt | ||
import org.mockito.Mockito.mock | ||
import org.mockito.Mockito.times | ||
import org.mockito.Mockito.verify | ||
import org.mockito.Mockito.`when` | ||
import org.robolectric.annotation.Config | ||
|
||
@Suppress("DEPRECATION") | ||
class NetworkStatusHelperTest : BaseTest() { | ||
|
||
@Test | ||
fun `when connectivity service is not available assumes network is available`() { | ||
val networkStatusHelper = NetworkStatusHelper(mock(Context::class.java)) | ||
assertThat(networkStatusHelper.isAvailable()).isTrue() | ||
} | ||
|
||
@Test | ||
fun `when api version is 21 check active network info`() { | ||
val context = mock(Context::class.java) | ||
val connectivityManager = mock(ConnectivityManager::class.java) | ||
val activeNetwork = mock(NetworkInfo::class.java) | ||
`when`(context.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn(connectivityManager) | ||
`when`(connectivityManager.activeNetworkInfo).thenReturn(activeNetwork) | ||
`when`(activeNetwork.isConnected).thenReturn(true) | ||
val networkStatusHelper = NetworkStatusHelper(context) | ||
assertThat(networkStatusHelper.isAvailable()).isTrue() | ||
verify(activeNetwork).isConnected | ||
} | ||
|
||
@Test | ||
@Config(sdk = [23]) | ||
fun `when api version is 23 check active network info`() { | ||
val context = mock(Context::class.java) | ||
val connectivityManager = mock(ConnectivityManager::class.java) | ||
val activeNetwork = mock(Network::class.java) | ||
`when`(context.getSystemService(Context.CONNECTIVITY_SERVICE)).thenReturn(connectivityManager) | ||
`when`(connectivityManager.activeNetwork).thenReturn(activeNetwork) | ||
val networkCapabilities = mock(NetworkCapabilities::class.java) | ||
`when`(connectivityManager.getNetworkCapabilities(activeNetwork)).thenReturn(networkCapabilities) | ||
`when`(networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)).thenReturn(true) | ||
`when`(networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)).thenReturn(true) | ||
val networkStatusHelper = NetworkStatusHelper(context) | ||
assertThat(networkStatusHelper.isAvailable()).isTrue() | ||
verify(networkCapabilities, times(2)).hasCapability(anyInt()) | ||
} | ||
} |
Oops, something went wrong.