Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix part of #3616: Migrate all non-test Android API deprecated references to the replacement versions with proper gating logic #5542

Open
wants to merge 16 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,12 @@ package org.oppia.android.testing.networking

import android.content.Context
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import android.net.NetworkInfo
import android.os.Build
import org.robolectric.Shadows.shadowOf
import org.robolectric.shadows.ShadowNetworkInfo
import org.robolectric.shadows.ShadowNetworkCapabilities
import javax.inject.Inject

/** Test utility to modify [ShadowNetworkInfo] in tests. */
Expand All @@ -15,6 +18,8 @@ class NetworkConnectionTestUtil @Inject constructor(private val context: Context
private val connectivityManager by lazy {
context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
}
private val networkCapabilities = ShadowNetworkCapabilities.newInstance()


/**
* Sets the [ShadowNetworkInfo] during the test.
Expand All @@ -23,14 +28,46 @@ class NetworkConnectionTestUtil @Inject constructor(private val context: Context
* @param networkState state of the network connection
*/
fun setNetworkInfo(status: Int, networkState: NetworkInfo.State) {
shadowOf(connectivityManager).setActiveNetworkInfo(
ShadowNetworkInfo.newInstance(
/* detailedState= */ null,
/* type= */ status,
/* subType= */ 0,
/* isAvailable= */ true,
/* state= */ networkState
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
// Use ShadowNetworkInfo for older devices (API < 23)
shadowOf(connectivityManager).setActiveNetworkInfo(
ShadowNetworkInfo.newInstance(
/* detailedState= */ null,
/* type= */ status,
/* subType= */ 0,
/* isAvailable= */ true,
/* state= */ networkState
)
)
)
} else {
// For newer devices, use NetworkCapabilities
val transportType = getTransportTypeFromStatus(status)
setNetworkCapabilities(networkState == NetworkInfo.State.CONNECTED, transportType)
}
}

/**
* Sets the [ShadowNetworkCapabilities] during the test for newer devices.
*
* @param isConnected whether the network is connected
* @param transportType the type of transport being used (e.g., WiFi, Cellular)
*/
private fun setNetworkCapabilities(isConnected: Boolean, transportType: Int) {
shadowOf(networkCapabilities).addCapability(transportType)
if (isConnected) {
shadowOf(networkCapabilities).addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
} else {
shadowOf(networkCapabilities).removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
}
}

private fun getTransportTypeFromStatus(status: Int): Int {
return when (status) {
ConnectivityManager.TYPE_WIFI -> NetworkCapabilities.TRANSPORT_WIFI
ConnectivityManager.TYPE_MOBILE -> NetworkCapabilities.TRANSPORT_CELLULAR
ConnectivityManager.TYPE_ETHERNET -> NetworkCapabilities.TRANSPORT_ETHERNET
ConnectivityManager.TYPE_WIMAX -> NetworkCapabilities.TRANSPORT_WIFI_AWARE
else -> throw IllegalArgumentException("Unsupported network type: $status")
}
}
}
1 change: 1 addition & 0 deletions utility/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.oppia.android.util">
<uses-sdk android:targetSdkVersion="33" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package org.oppia.android.util.networking

import android.content.Context
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
import android.os.Build
import org.oppia.android.util.networking.NetworkConnectionUtil.ProdConnectionStatus.CELLULAR
import org.oppia.android.util.networking.NetworkConnectionUtil.ProdConnectionStatus.LOCAL
import org.oppia.android.util.networking.NetworkConnectionUtil.ProdConnectionStatus.NONE
Expand All @@ -21,7 +23,36 @@ class NetworkConnectionUtilProdImpl @Inject constructor(
// TODO(#3616): Update to use correct methods according to the SDK version. We can use the
// older (current) method for SDK versions < 28 and the newer method for SDK versions >= 29 and
// use an if-statement to choose.
@Suppress("DEPRECATION") // The code is correct for targeted versions of Android.

return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
getConnectionStatusForNewerDevices(connectivityManager)
} else {
getConnectionStatusForOlderDevices(connectivityManager)
}
}

/** Uses NetworkCapabilities for SDK versions >= 23. */
private fun getConnectionStatusForNewerDevices(
connectivityManager: ConnectivityManager
): ConnectionStatus {
val network = connectivityManager.activeNetwork
val capabilities = connectivityManager.getNetworkCapabilities(network)
return capabilities?.let {
when {
it.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) ||
it.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET) -> LOCAL
it.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR) ||
it.hasTransport(NetworkCapabilities.TRANSPORT_WIFI_AWARE) -> CELLULAR
else -> NONE
}
} ?: NONE
}

/** Uses the older `activeNetworkInfo` for SDK versions < 23. */
@Suppress("DEPRECATION")
private fun getConnectionStatusForOlderDevices(
connectivityManager: ConnectivityManager
): ConnectionStatus {
return connectivityManager.activeNetworkInfo?.let { activeNetwork ->
val isConnected = activeNetwork.isConnected
val isLocal = activeNetwork.type ==
Expand Down
Loading