From 25c8bc8aad3efe5003bede43b6148b1157c91a15 Mon Sep 17 00:00:00 2001 From: Chaesung Yoon Date: Thu, 17 Sep 2020 14:51:24 +0900 Subject: [PATCH 1/7] Changed to not use NetworkInfo class for Lollipop and above --- .../library/rx2/Connectivity.java | 52 ++++++++++++++++++- .../library/rx2/info/NetworkState.java | 47 +++++++++++++++++ .../LollipopNetworkObservingStrategy.java | 29 ++++++++++- .../MarshmallowNetworkObservingStrategy.java | 25 ++++++++- 4 files changed, 147 insertions(+), 6 deletions(-) create mode 100644 library/src/main/java/com/github/pwittchen/reactivenetwork/library/rx2/info/NetworkState.java diff --git a/library/src/main/java/com/github/pwittchen/reactivenetwork/library/rx2/Connectivity.java b/library/src/main/java/com/github/pwittchen/reactivenetwork/library/rx2/Connectivity.java index c3c70483..dbed4b20 100644 --- a/library/src/main/java/com/github/pwittchen/reactivenetwork/library/rx2/Connectivity.java +++ b/library/src/main/java/com/github/pwittchen/reactivenetwork/library/rx2/Connectivity.java @@ -17,11 +17,15 @@ import android.content.Context; import android.net.ConnectivityManager; +import android.net.Network; +import android.net.NetworkCapabilities; import android.net.NetworkInfo; import android.os.Build; import androidx.annotation.NonNull; import androidx.annotation.RequiresApi; +import com.github.pwittchen.reactivenetwork.library.rx2.info.NetworkState; + /** * Connectivity class represents current connectivity status. It wraps NetworkInfo object. */ @@ -40,6 +44,8 @@ public final class Connectivity { private String subTypeName; // NOPMD private String reason; // NOPMD private String extraInfo; // NOPMD + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + private NetworkState networkState; public static Connectivity create() { return builder().build(); @@ -50,6 +56,12 @@ public static Connectivity create(@NonNull Context context) { return create(context, getConnectivityManager(context)); } + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + public static Connectivity create(@NonNull Context context, NetworkState networkState) { + Preconditions.checkNotNull(context, "context == null"); + return create(context, getConnectivityManager(context), networkState); + } + private static ConnectivityManager getConnectivityManager(Context context) { final String service = Context.CONNECTIVITY_SERVICE; return (ConnectivityManager) context.getSystemService(service); @@ -66,6 +78,18 @@ protected static Connectivity create(@NonNull Context context, ConnectivityManag return (networkInfo == null) ? create() : create(networkInfo); } + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + protected static Connectivity create(@NonNull Context context, ConnectivityManager manager, NetworkState networkState) { + Preconditions.checkNotNull(context, "context == null"); + + if (manager == null) { + return create(); + } + networkState.setNetworkCapabilities(manager.getNetworkCapabilities(networkState.getNetwork())); + networkState.setLinkProperties(manager.getLinkProperties(networkState.getNetwork())); + return create(networkState); + } + private static Connectivity create(NetworkInfo networkInfo) { return new Builder() .state(networkInfo.getState()) @@ -82,9 +106,20 @@ private static Connectivity create(NetworkInfo networkInfo) { .build(); } + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + private static Connectivity create(NetworkState networkState) { + return new Builder() + .networkState(networkState) + .build(); + } + private Connectivity(Builder builder) { - state = builder.state; - detailedState = builder.detailedState; + if(Preconditions.isAtLeastAndroidLollipop()) { + networkState = builder.networkState; + } else { + state = builder.state; + detailedState = builder.detailedState; + } type = builder.type; subType = builder.subType; available = builder.available; @@ -192,6 +227,11 @@ public static Builder extraInfo(String extraInfo) { return builder().extraInfo(extraInfo); } + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + public NetworkState getNetworkState() { + return networkState; + } + @Override public boolean equals(Object o) { if (this == o) { return true; @@ -298,14 +338,17 @@ public final static class Builder { private String subTypeName = "NONE"; // NOPMD private String reason = ""; // NOPMD private String extraInfo = ""; // NOPMD + private NetworkState networkState = new NetworkState(); public Builder state(NetworkInfo.State state) { this.state = state; + this.networkState.setConnected(state == NetworkInfo.State.CONNECTED); return this; } public Builder detailedState(NetworkInfo.DetailedState detailedState) { this.detailedState = detailedState; + this.networkState.setConnected(detailedState == NetworkInfo.DetailedState.CONNECTED); return this; } @@ -354,6 +397,11 @@ public Builder extraInfo(String extraInfo) { return this; } + public Builder networkState(NetworkState networkState) { + this.networkState = networkState; + return this; + } + public Connectivity build() { return new Connectivity(this); } diff --git a/library/src/main/java/com/github/pwittchen/reactivenetwork/library/rx2/info/NetworkState.java b/library/src/main/java/com/github/pwittchen/reactivenetwork/library/rx2/info/NetworkState.java new file mode 100644 index 00000000..668d7334 --- /dev/null +++ b/library/src/main/java/com/github/pwittchen/reactivenetwork/library/rx2/info/NetworkState.java @@ -0,0 +1,47 @@ +package com.github.pwittchen.reactivenetwork.library.rx2.info; + +import android.net.LinkProperties; +import android.net.Network; +import android.net.NetworkCapabilities; + +/** + * NetworkState data object + */ +public class NetworkState { + private boolean isConnected = false; + private Network network = null; + private NetworkCapabilities networkCapabilities = null; + private LinkProperties linkProperties = null; + + public boolean isConnected() { + return isConnected; + } + + public void setConnected(boolean connected) { + isConnected = connected; + } + + public Network getNetwork() { + return network; + } + + public void setNetwork(Network network) { + this.network = network; + } + + public NetworkCapabilities getNetworkCapabilities() { + return networkCapabilities; + } + + public void setNetworkCapabilities(NetworkCapabilities networkCapabilities) { + this.networkCapabilities = networkCapabilities; + } + + public LinkProperties getLinkProperties() { + return linkProperties; + } + + public void setLinkProperties(LinkProperties linkProperties) { + this.linkProperties = linkProperties; + } +} diff --git a/library/src/main/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/strategy/LollipopNetworkObservingStrategy.java b/library/src/main/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/strategy/LollipopNetworkObservingStrategy.java index 429b60ac..3346cdf4 100644 --- a/library/src/main/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/strategy/LollipopNetworkObservingStrategy.java +++ b/library/src/main/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/strategy/LollipopNetworkObservingStrategy.java @@ -19,10 +19,16 @@ import android.content.Context; import android.net.ConnectivityManager; import android.net.ConnectivityManager.NetworkCallback; +import android.net.LinkProperties; import android.net.Network; +import android.net.NetworkCapabilities; import android.net.NetworkRequest; import android.util.Log; + +import androidx.annotation.NonNull; + import com.github.pwittchen.reactivenetwork.library.rx2.Connectivity; +import com.github.pwittchen.reactivenetwork.library.rx2.info.NetworkState; import com.github.pwittchen.reactivenetwork.library.rx2.network.observing.NetworkObservingStrategy; import com.jakewharton.nopen.annotation.Open; import io.reactivex.Observable; @@ -40,6 +46,7 @@ implements NetworkObservingStrategy { @SuppressWarnings("NullAway") // it has to be initialized in the Observable due to Context private NetworkCallback networkCallback; + private NetworkState networkState = new NetworkState(); @Override public Observable observeNetworkConnectivity(final Context context) { final String service = Context.CONNECTIVITY_SERVICE; @@ -73,12 +80,30 @@ private void tryToUnregisterCallback(final ConnectivityManager manager) { private NetworkCallback createNetworkCallback(final ObservableEmitter subscriber, final Context context) { return new ConnectivityManager.NetworkCallback() { + @Override + public void onCapabilitiesChanged(@NonNull Network network, @NonNull NetworkCapabilities networkCapabilities) { + networkState.setNetwork(network); + networkState.setNetworkCapabilities(networkCapabilities); + subscriber.onNext(Connectivity.create(context, networkState)); + } + + @Override + public void onLinkPropertiesChanged(@NonNull Network network, @NonNull LinkProperties linkProperties) { + networkState.setNetwork(network); + networkState.setLinkProperties(linkProperties); + subscriber.onNext(Connectivity.create(context, networkState)); + } + @Override public void onAvailable(Network network) { - subscriber.onNext(Connectivity.create(context)); + networkState.setNetwork(network); + networkState.setConnected(true); + subscriber.onNext(Connectivity.create(context, networkState)); } @Override public void onLost(Network network) { - subscriber.onNext(Connectivity.create(context)); + networkState.setNetwork(network); + networkState.setConnected(false); + subscriber.onNext(Connectivity.create(context, networkState)); } }; } diff --git a/library/src/main/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/strategy/MarshmallowNetworkObservingStrategy.java b/library/src/main/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/strategy/MarshmallowNetworkObservingStrategy.java index c60b0d38..934ca9d0 100644 --- a/library/src/main/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/strategy/MarshmallowNetworkObservingStrategy.java +++ b/library/src/main/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/strategy/MarshmallowNetworkObservingStrategy.java @@ -21,6 +21,7 @@ import android.content.Intent; import android.content.IntentFilter; import android.net.ConnectivityManager; +import android.net.LinkProperties; import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkInfo; @@ -29,6 +30,7 @@ import android.util.Log; import androidx.annotation.NonNull; import com.github.pwittchen.reactivenetwork.library.rx2.Connectivity; +import com.github.pwittchen.reactivenetwork.library.rx2.info.NetworkState; import com.github.pwittchen.reactivenetwork.library.rx2.network.observing.NetworkObservingStrategy; import com.jakewharton.nopen.annotation.Open; import io.reactivex.BackpressureStrategy; @@ -58,6 +60,7 @@ private final Subject connectivitySubject; private final BroadcastReceiver idleReceiver; private Connectivity lastConnectivity = Connectivity.create(); + private NetworkState networkState = new NetworkState(); @SuppressWarnings("NullAway") // networkCallback cannot be initialized here public MarshmallowNetworkObservingStrategy() { @@ -157,12 +160,30 @@ protected void tryToUnregisterReceiver(Context context) { protected ConnectivityManager.NetworkCallback createNetworkCallback(final Context context) { return new ConnectivityManager.NetworkCallback() { + @Override + public void onCapabilitiesChanged(@NonNull Network network, @NonNull NetworkCapabilities networkCapabilities) { + networkState.setNetwork(network); + networkState.setNetworkCapabilities(networkCapabilities); + onNext(Connectivity.create(context, networkState)); + } + + @Override + public void onLinkPropertiesChanged(@NonNull Network network, @NonNull LinkProperties linkProperties) { + networkState.setNetwork(network); + networkState.setLinkProperties(linkProperties); + onNext(Connectivity.create(context, networkState)); + } + @Override public void onAvailable(Network network) { - onNext(Connectivity.create(context)); + networkState.setNetwork(network); + networkState.setConnected(true); + onNext(Connectivity.create(context, networkState)); } @Override public void onLost(Network network) { - onNext(Connectivity.create(context)); + networkState.setNetwork(network); + networkState.setConnected(false); + onNext(Connectivity.create(context, networkState)); } }; } From 0dc63eeb5c189e76a67c6b802f3e0fc18cdde255 Mon Sep 17 00:00:00 2001 From: Piotr Wittchen Date: Sun, 4 Dec 2022 20:48:17 +0100 Subject: [PATCH 2/7] fixes in the logic of MarshmallowNetworkObservingStrategy and tests according to PR #455 related to utilization of the NetworkState class --- .../reactivenetwork/kotlinapp/MainActivity.kt | 7 +- .../reactivenetwork/app/MainActivity.java | 22 ++++-- .../library/rx2/Connectivity.java | 77 +++++++++++-------- .../library/rx2/info/NetworkState.java | 27 +++---- .../MarshmallowNetworkObservingStrategy.java | 66 ++++++++++++---- .../library/rx2/ConnectivityTest.java | 17 ++-- .../library/rx2/ReactiveNetworkTest.java | 18 ++--- .../error/DefaultErrorHandlerTest.java | 3 +- .../SocketInternetObservingStrategyTest.java | 3 +- ...edGardenInternetObservingStrategyTest.java | 3 +- .../NetworkObservingStrategyTest.java | 65 ---------------- .../LollipopNetworkObservingStrategyTest.java | 9 ++- ...rshmallowNetworkObservingStrategyTest.java | 45 ++++------- ...eLollipopNetworkObservingStrategyTest.java | 27 ++----- 14 files changed, 183 insertions(+), 206 deletions(-) delete mode 100644 library/src/test/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/NetworkObservingStrategyTest.java diff --git a/app-kotlin/src/main/kotlin/com/github/pwittchen/reactivenetwork/kotlinapp/MainActivity.kt b/app-kotlin/src/main/kotlin/com/github/pwittchen/reactivenetwork/kotlinapp/MainActivity.kt index c2674382..61805454 100644 --- a/app-kotlin/src/main/kotlin/com/github/pwittchen/reactivenetwork/kotlinapp/MainActivity.kt +++ b/app-kotlin/src/main/kotlin/com/github/pwittchen/reactivenetwork/kotlinapp/MainActivity.kt @@ -46,9 +46,10 @@ class MainActivity : Activity() { .observeOn(AndroidSchedulers.mainThread()) .subscribe { connectivity -> Log.d(TAG, connectivity.toString()) - val state = connectivity.state() - val name = connectivity.typeName() - connectivity_status.text = String.format("state: %s, typeName: %s", state, name) + val state = connectivity.networkState() + val capabilities = connectivity.networkState()!!.networkCapabilities + val isConnected = state!!.isConnected + connectivity_status.text = String.format("connected: %s, capabilities: %s", isConnected, capabilities) } internetDisposable = ReactiveNetwork.observeInternetConnectivity() diff --git a/app/src/main/java/com/github/pwittchen/reactivenetwork/app/MainActivity.java b/app/src/main/java/com/github/pwittchen/reactivenetwork/app/MainActivity.java index 834c267a..29557325 100644 --- a/app/src/main/java/com/github/pwittchen/reactivenetwork/app/MainActivity.java +++ b/app/src/main/java/com/github/pwittchen/reactivenetwork/app/MainActivity.java @@ -16,11 +16,15 @@ package com.github.pwittchen.reactivenetwork.app; import android.app.Activity; -import android.net.NetworkInfo; +import android.net.NetworkCapabilities; +import android.net.TransportInfo; +import android.os.Build; import android.os.Bundle; import android.util.Log; import android.widget.TextView; +import androidx.annotation.RequiresApi; import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork; +import com.github.pwittchen.reactivenetwork.library.rx2.info.NetworkState; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.Disposable; import io.reactivex.schedulers.Schedulers; @@ -39,7 +43,10 @@ public class MainActivity extends Activity { tvInternetStatus = (TextView) findViewById(R.id.internet_status); } - @Override protected void onResume() { + @SuppressWarnings("ConstantConditions") + @RequiresApi(api = Build.VERSION_CODES.Q) + @Override + protected void onResume() { super.onResume(); networkDisposable = ReactiveNetwork.observeNetworkConnectivity(getApplicationContext()) @@ -47,9 +54,14 @@ public class MainActivity extends Activity { .observeOn(AndroidSchedulers.mainThread()) .subscribe(connectivity -> { Log.d(TAG, connectivity.toString()); - final NetworkInfo.State state = connectivity.state(); - final String name = connectivity.typeName(); - tvConnectivityStatus.setText(String.format("state: %s, typeName: %s", state, name)); + + NetworkState state = connectivity.networkState(); + NetworkCapabilities capabilities = connectivity.networkState().getNetworkCapabilities(); + boolean isConnected = state.isConnected(); + + tvConnectivityStatus.setText(String.format( + "connected: %s, capabilities: %s", isConnected, capabilities + )); }); internetDisposable = ReactiveNetwork.observeInternetConnectivity() diff --git a/library/src/main/java/com/github/pwittchen/reactivenetwork/library/rx2/Connectivity.java b/library/src/main/java/com/github/pwittchen/reactivenetwork/library/rx2/Connectivity.java index dbed4b20..acc07de3 100644 --- a/library/src/main/java/com/github/pwittchen/reactivenetwork/library/rx2/Connectivity.java +++ b/library/src/main/java/com/github/pwittchen/reactivenetwork/library/rx2/Connectivity.java @@ -17,45 +17,44 @@ import android.content.Context; import android.net.ConnectivityManager; -import android.net.Network; -import android.net.NetworkCapabilities; import android.net.NetworkInfo; import android.os.Build; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; - import com.github.pwittchen.reactivenetwork.library.rx2.info.NetworkState; /** * Connectivity class represents current connectivity status. It wraps NetworkInfo object. */ -@RequiresApi(api = Build.VERSION_CODES.CUPCAKE) public final class Connectivity { static final int UNKNOWN_TYPE = -1; static final int UNKNOWN_SUB_TYPE = -1; - private NetworkInfo.State state; // NOPMD - private NetworkInfo.DetailedState detailedState; // NOPMD - private int type; // NOPMD - private int subType; // NOPMD - private boolean available; // NOPMD - private boolean failover; // NOPMD - private boolean roaming; // NOPMD - private String typeName; // NOPMD - private String subTypeName; // NOPMD - private String reason; // NOPMD - private String extraInfo; // NOPMD - @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) - private NetworkState networkState; + @Nullable private NetworkInfo.State state; // NOPMD + @Nullable private NetworkInfo.DetailedState detailedState; // NOPMD + @Nullable @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + private NetworkState networkState; // NOPMD + private final int type; // NOPMD + private final int subType; // NOPMD + private final boolean available; // NOPMD + private final boolean failover; // NOPMD + private final boolean roaming; // NOPMD + private final String typeName; // NOPMD + private final String subTypeName; // NOPMD + private final String reason; // NOPMD + private final String extraInfo; // NOPMD public static Connectivity create() { return builder().build(); } + @SuppressWarnings("PMD") public static Connectivity create(@NonNull Context context) { Preconditions.checkNotNull(context, "context == null"); return create(context, getConnectivityManager(context)); } + @SuppressWarnings("PMD") @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) public static Connectivity create(@NonNull Context context, NetworkState networkState) { Preconditions.checkNotNull(context, "context == null"); @@ -67,6 +66,7 @@ private static ConnectivityManager getConnectivityManager(Context context) { return (ConnectivityManager) context.getSystemService(service); } + @SuppressWarnings("PMD") protected static Connectivity create(@NonNull Context context, ConnectivityManager manager) { Preconditions.checkNotNull(context, "context == null"); @@ -78,8 +78,11 @@ protected static Connectivity create(@NonNull Context context, ConnectivityManag return (networkInfo == null) ? create() : create(networkInfo); } + @SuppressWarnings("PMD") @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) - protected static Connectivity create(@NonNull Context context, ConnectivityManager manager, NetworkState networkState) { + protected static Connectivity create( + @NonNull Context context, ConnectivityManager manager, NetworkState networkState + ) { Preconditions.checkNotNull(context, "context == null"); if (manager == null) { @@ -109,16 +112,22 @@ private static Connectivity create(NetworkInfo networkInfo) { @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) private static Connectivity create(NetworkState networkState) { return new Builder() - .networkState(networkState) - .build(); + .networkState(networkState) + .build(); } private Connectivity(Builder builder) { - if(Preconditions.isAtLeastAndroidLollipop()) { - networkState = builder.networkState; + if (Preconditions.isAtLeastAndroidLollipop()) { + if (builder.networkState != null) { + networkState = builder.networkState; + } } else { - state = builder.state; - detailedState = builder.detailedState; + if (builder.state != null) { + state = builder.state; + } + if (builder.detailedState != null) { + detailedState = builder.detailedState; + } } type = builder.type; subType = builder.subType; @@ -139,7 +148,7 @@ private static Builder builder() { return new Connectivity.Builder(); } - public NetworkInfo.State state() { + public @Nullable NetworkInfo.State state() { return state; } @@ -147,7 +156,7 @@ public static Builder state(NetworkInfo.State state) { return builder().state(state); } - public NetworkInfo.DetailedState detailedState() { + public @Nullable NetworkInfo.DetailedState detailedState() { return detailedState; } @@ -155,6 +164,13 @@ public static Builder state(NetworkInfo.DetailedState detailedState) { return builder().detailedState(detailedState); } + @Nullable + @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) + @SuppressWarnings("PMD") + public NetworkState networkState() { + return networkState; + } + public int type() { return type; } @@ -227,11 +243,6 @@ public static Builder extraInfo(String extraInfo) { return builder().extraInfo(extraInfo); } - @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) - public NetworkState getNetworkState() { - return networkState; - } - @Override public boolean equals(Object o) { if (this == o) { return true; @@ -277,7 +288,7 @@ public NetworkState getNetworkState() { } @Override public int hashCode() { - int result = state.hashCode(); + int result = state != null ? state.hashCode() : 0; result = 31 * result + (detailedState != null ? detailedState.hashCode() : 0); result = 31 * result + type; result = 31 * result + subType; @@ -338,7 +349,7 @@ public final static class Builder { private String subTypeName = "NONE"; // NOPMD private String reason = ""; // NOPMD private String extraInfo = ""; // NOPMD - private NetworkState networkState = new NetworkState(); + private NetworkState networkState = new NetworkState(); // NOPMD public Builder state(NetworkInfo.State state) { this.state = state; diff --git a/library/src/main/java/com/github/pwittchen/reactivenetwork/library/rx2/info/NetworkState.java b/library/src/main/java/com/github/pwittchen/reactivenetwork/library/rx2/info/NetworkState.java index 668d7334..8ecfa43e 100644 --- a/library/src/main/java/com/github/pwittchen/reactivenetwork/library/rx2/info/NetworkState.java +++ b/library/src/main/java/com/github/pwittchen/reactivenetwork/library/rx2/info/NetworkState.java @@ -3,16 +3,17 @@ import android.net.LinkProperties; import android.net.Network; import android.net.NetworkCapabilities; +import androidx.annotation.Nullable; +import com.jakewharton.nopen.annotation.Open; -/** - * NetworkState data object - */ +@Open public class NetworkState { - private boolean isConnected = false; - private Network network = null; - private NetworkCapabilities networkCapabilities = null; - private LinkProperties linkProperties = null; + @SuppressWarnings("PMD") private boolean isConnected = false; + @Nullable private Network network = null; + @Nullable private NetworkCapabilities networkCapabilities = null; + @Nullable private LinkProperties linkProperties = null; + @SuppressWarnings("PMD") public boolean isConnected() { return isConnected; } @@ -21,27 +22,27 @@ public void setConnected(boolean connected) { isConnected = connected; } - public Network getNetwork() { + @Nullable public Network getNetwork() { return network; } - public void setNetwork(Network network) { + public void setNetwork(@Nullable Network network) { this.network = network; } - public NetworkCapabilities getNetworkCapabilities() { + @Nullable public NetworkCapabilities getNetworkCapabilities() { return networkCapabilities; } - public void setNetworkCapabilities(NetworkCapabilities networkCapabilities) { + public void setNetworkCapabilities(@Nullable NetworkCapabilities networkCapabilities) { this.networkCapabilities = networkCapabilities; } - public LinkProperties getLinkProperties() { + @Nullable public LinkProperties getLinkProperties() { return linkProperties; } - public void setLinkProperties(LinkProperties linkProperties) { + public void setLinkProperties(@Nullable LinkProperties linkProperties) { this.linkProperties = linkProperties; } } diff --git a/library/src/main/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/strategy/MarshmallowNetworkObservingStrategy.java b/library/src/main/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/strategy/MarshmallowNetworkObservingStrategy.java index 934ca9d0..fd510939 100644 --- a/library/src/main/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/strategy/MarshmallowNetworkObservingStrategy.java +++ b/library/src/main/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/strategy/MarshmallowNetworkObservingStrategy.java @@ -49,18 +49,19 @@ * Network observing strategy for devices with Android Marshmallow (API 23) or higher. * Uses Network Callback API and handles Doze mode. */ -@Open @TargetApi(23) public class MarshmallowNetworkObservingStrategy - implements NetworkObservingStrategy { +@Open +@TargetApi(23) +public class MarshmallowNetworkObservingStrategy implements NetworkObservingStrategy { protected static final String ERROR_MSG_NETWORK_CALLBACK = "could not unregister network callback"; protected static final String ERROR_MSG_RECEIVER = "could not unregister receiver"; - @SuppressWarnings("NullAway") // it has to be initialized in the Observable due to Context private ConnectivityManager.NetworkCallback networkCallback; private final Subject connectivitySubject; private final BroadcastReceiver idleReceiver; private Connectivity lastConnectivity = Connectivity.create(); - private NetworkState networkState = new NetworkState(); + + @SuppressWarnings("FieldMayBeFinal") private NetworkState networkState = new NetworkState(); @SuppressWarnings("NullAway") // networkCallback cannot be initialized here public MarshmallowNetworkObservingStrategy() { @@ -76,12 +77,16 @@ public MarshmallowNetworkObservingStrategy() { registerIdleReceiver(context); final NetworkRequest request = - new NetworkRequest.Builder().addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) + new NetworkRequest + .Builder() + .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET) .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED) .build(); manager.registerNetworkCallback(request, networkCallback); + //todo: fix logic of the stream below for the network state + return connectivitySubject.toFlowable(BackpressureStrategy.LATEST).doOnCancel(new Action() { @Override public void run() { tryToUnregisterCallback(manager); @@ -100,12 +105,33 @@ public Publisher apply(final Connectivity connectivity) { }).startWith(Connectivity.create(context)).distinctUntilChanged().toObservable(); } - protected Publisher propagateAnyConnectedState(final Connectivity last, - final Connectivity current) { + //todo: fix logic of this method for the network state + @SuppressWarnings("NullAway") + protected Publisher propagateAnyConnectedState( + final Connectivity last, + final Connectivity current + ) { + final boolean hasNetworkState + = last.networkState() != null + && current.networkState() != null; + final boolean typeChanged = last.type() != current.type(); - final boolean wasConnected = last.state() == NetworkInfo.State.CONNECTED; - final boolean isDisconnected = current.state() == NetworkInfo.State.DISCONNECTED; - final boolean isNotIdle = current.detailedState() != NetworkInfo.DetailedState.IDLE; + + boolean wasConnected; + boolean isDisconnected; + boolean isNotIdle; + + if (hasNetworkState) { + // handling new NetworkState API + wasConnected = last.networkState().isConnected(); + isDisconnected = !current.networkState().isConnected(); + isNotIdle = true; + } else { + // handling legacy, deprecated NetworkInfo API + wasConnected = last.state() == NetworkInfo.State.CONNECTED; + isDisconnected = current.state() == NetworkInfo.State.DISCONNECTED; + isNotIdle = current.detailedState() != NetworkInfo.DetailedState.IDLE; + } if (typeChanged && wasConnected && isDisconnected && isNotIdle) { return Flowable.fromArray(current, last); @@ -161,30 +187,42 @@ protected void tryToUnregisterReceiver(Context context) { protected ConnectivityManager.NetworkCallback createNetworkCallback(final Context context) { return new ConnectivityManager.NetworkCallback() { @Override - public void onCapabilitiesChanged(@NonNull Network network, @NonNull NetworkCapabilities networkCapabilities) { + public void onCapabilitiesChanged( + @NonNull Network network, + @NonNull NetworkCapabilities networkCapabilities + ) { networkState.setNetwork(network); networkState.setNetworkCapabilities(networkCapabilities); onNext(Connectivity.create(context, networkState)); } @Override - public void onLinkPropertiesChanged(@NonNull Network network, @NonNull LinkProperties linkProperties) { + public void onLinkPropertiesChanged( + @NonNull Network network, + @NonNull LinkProperties linkProperties + ) { networkState.setNetwork(network); networkState.setLinkProperties(linkProperties); onNext(Connectivity.create(context, networkState)); } - @Override public void onAvailable(Network network) { + @Override public void onAvailable(@NonNull Network network) { networkState.setNetwork(network); networkState.setConnected(true); onNext(Connectivity.create(context, networkState)); } - @Override public void onLost(Network network) { + @Override public void onLost(@NonNull Network network) { networkState.setNetwork(network); networkState.setConnected(false); onNext(Connectivity.create(context, networkState)); } + + @Override public void onUnavailable() { + super.onUnavailable(); + networkState.setConnected(false); + onNext(Connectivity.create(context, networkState)); + } }; } diff --git a/library/src/test/java/com/github/pwittchen/reactivenetwork/library/rx2/ConnectivityTest.java b/library/src/test/java/com/github/pwittchen/reactivenetwork/library/rx2/ConnectivityTest.java index 4cc6c45e..67dbfe0f 100644 --- a/library/src/test/java/com/github/pwittchen/reactivenetwork/library/rx2/ConnectivityTest.java +++ b/library/src/test/java/com/github/pwittchen/reactivenetwork/library/rx2/ConnectivityTest.java @@ -23,16 +23,18 @@ import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; import static com.google.common.truth.Truth.assertThat; @RunWith(RobolectricTestRunner.class) -@SuppressWarnings("NullAway") public class ConnectivityTest { +@SuppressWarnings("NullAway") +public class ConnectivityTest { private static final String TYPE_NAME_WIFI = "WIFI"; private static final String TYPE_NAME_MOBILE = "MOBILE"; private static final String TYPE_NAME_NONE = "NONE"; - @Test public void shouldCreateConnectivity() { + @Test @Config(sdk = 19) public void shouldCreateConnectivity() { // when Connectivity connectivity = Connectivity.create(); @@ -66,7 +68,8 @@ assertThat(shouldBeEqualToGivenStatus).isTrue(); } - @Test public void stateShouldBeEqualToOneOfGivenMultipleValues() throws Exception { + @Test @Config(sdk = 19) + public void stateShouldBeEqualToOneOfGivenMultipleValues() throws Exception { // given final Connectivity connectivity = Connectivity.state(NetworkInfo.State.CONNECTING) .type(ConnectivityManager.TYPE_WIFI) @@ -174,7 +177,7 @@ public void createShouldThrowAnExceptionWhenContextIsNull() { // an exception is thrown } - @Test public void shouldReturnProperToStringValue() { + @Test @Config(sdk = 19) public void shouldReturnProperToStringValue() { // given final String expectedToString = "Connectivity{" + "state=DISCONNECTED, " @@ -247,7 +250,8 @@ public void shouldAppendUnknownTypeWhileFilteringNetworkTypesInsidePredicateForE assertThat(outputTypes).isEqualTo(expectedOutputTypes); } - @Test public void shouldCreateConnectivityWithBuilder() { + @Test @Config(sdk = 19) + public void shouldCreateConnectivityWithBuilder() { // given NetworkInfo.State state = NetworkInfo.State.CONNECTED; NetworkInfo.DetailedState detailedState = NetworkInfo.DetailedState.CONNECTED; @@ -321,7 +325,8 @@ public void shouldAppendUnknownTypeWhileFilteringNetworkTypesInsidePredicateForE assertThat(isAnotherConnectivityTheSame).isFalse(); } - @Test public void shouldCreateDefaultConnectivityWhenConnectivityManagerIsNull() { + @Test @Config(sdk = 19) + public void shouldCreateDefaultConnectivityWhenConnectivityManagerIsNull() { // given final Context context = RuntimeEnvironment.getApplication().getApplicationContext(); final ConnectivityManager connectivityManager = null; diff --git a/library/src/test/java/com/github/pwittchen/reactivenetwork/library/rx2/ReactiveNetworkTest.java b/library/src/test/java/com/github/pwittchen/reactivenetwork/library/rx2/ReactiveNetworkTest.java index a420745b..37bbc951 100644 --- a/library/src/test/java/com/github/pwittchen/reactivenetwork/library/rx2/ReactiveNetworkTest.java +++ b/library/src/test/java/com/github/pwittchen/reactivenetwork/library/rx2/ReactiveNetworkTest.java @@ -17,7 +17,6 @@ import android.app.Application; import android.content.Context; -import android.net.NetworkInfo; import androidx.annotation.NonNull; import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingSettings; import com.github.pwittchen.reactivenetwork.library.rx2.internet.observing.InternetObservingStrategy; @@ -34,13 +33,12 @@ import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; -import org.robolectric.shadows.ShadowConnectivityManager; import static com.google.common.truth.Truth.assertThat; @RunWith(RobolectricTestRunner.class) -@Config(shadows = ShadowConnectivityManager.class) -@SuppressWarnings("NullAway") public class ReactiveNetworkTest { +@SuppressWarnings("NullAway") +public class ReactiveNetworkTest { private static final String TEST_VALID_HOST = "www.test.com"; private static final int TEST_VALID_PORT = 80; @@ -77,10 +75,6 @@ private void networkConnectivityObservableShouldNotBeNull() { // given final Application context = RuntimeEnvironment.getApplication(); - //final ConnectivityManager connectivityManagerMock = (ConnectivityManager) context - // .getSystemService(Context.CONNECTIVITY_SERVICE); - // - //shadowOf(connectivityManagerMock); // when Observable observable; @@ -115,7 +109,8 @@ private void networkConnectivityObservableShouldNotBeNull() { assertThat(observable).isNotNull(); } - @Test public void observeNetworkConnectivityShouldBeConnectedOnStartWhenNetworkIsAvailable() { + @Test + public void observeNetworkConnectivityShouldBeConnectedOnStartWhenNetworkIsAvailable() { // given final Application context = RuntimeEnvironment.getApplication(); @@ -123,7 +118,8 @@ private void networkConnectivityObservableShouldNotBeNull() { Connectivity connectivity = ReactiveNetwork.observeNetworkConnectivity(context).blockingFirst(); // then - assertThat(connectivity.state()).isEqualTo(NetworkInfo.State.CONNECTED); + assertThat(connectivity.networkState()).isNotNull(); + assertThat(connectivity.networkState().isConnected()).isTrue(); } @Test(expected = IllegalArgumentException.class) @@ -142,7 +138,7 @@ public void observeNetworkConnectivityShouldThrowAnExceptionForNullContext() { @Test(expected = IllegalArgumentException.class) public void observeNetworkConnectivityShouldThrowAnExceptionForNullStrategy() { // given - final Context context = RuntimeEnvironment.application; + final Context context = RuntimeEnvironment.getApplication(); final NetworkObservingStrategy strategy = null; // when diff --git a/library/src/test/java/com/github/pwittchen/reactivenetwork/library/rx2/internet/observing/error/DefaultErrorHandlerTest.java b/library/src/test/java/com/github/pwittchen/reactivenetwork/library/rx2/internet/observing/error/DefaultErrorHandlerTest.java index e71f8c40..0c6065b5 100644 --- a/library/src/test/java/com/github/pwittchen/reactivenetwork/library/rx2/internet/observing/error/DefaultErrorHandlerTest.java +++ b/library/src/test/java/com/github/pwittchen/reactivenetwork/library/rx2/internet/observing/error/DefaultErrorHandlerTest.java @@ -27,7 +27,8 @@ import static org.mockito.Mockito.verify; @RunWith(RobolectricTestRunner.class) -@SuppressWarnings("NullAway") public class DefaultErrorHandlerTest { +@SuppressWarnings("NullAway") +public class DefaultErrorHandlerTest { @Rule public MockitoRule rule = MockitoJUnit.rule(); @Spy private DefaultErrorHandler handler = new DefaultErrorHandler(); diff --git a/library/src/test/java/com/github/pwittchen/reactivenetwork/library/rx2/internet/observing/strategy/SocketInternetObservingStrategyTest.java b/library/src/test/java/com/github/pwittchen/reactivenetwork/library/rx2/internet/observing/strategy/SocketInternetObservingStrategyTest.java index dfedc7a8..a8ba4f92 100644 --- a/library/src/test/java/com/github/pwittchen/reactivenetwork/library/rx2/internet/observing/strategy/SocketInternetObservingStrategyTest.java +++ b/library/src/test/java/com/github/pwittchen/reactivenetwork/library/rx2/internet/observing/strategy/SocketInternetObservingStrategyTest.java @@ -37,7 +37,8 @@ import static org.mockito.Mockito.when; @RunWith(RobolectricTestRunner.class) -@SuppressWarnings({ "PMD", "NullAway" }) public class SocketInternetObservingStrategyTest { +@SuppressWarnings({ "PMD", "NullAway" }) +public class SocketInternetObservingStrategyTest { private static final int INITIAL_INTERVAL_IN_MS = 0; private static final int INTERVAL_IN_MS = 2000; diff --git a/library/src/test/java/com/github/pwittchen/reactivenetwork/library/rx2/internet/observing/strategy/WalledGardenInternetObservingStrategyTest.java b/library/src/test/java/com/github/pwittchen/reactivenetwork/library/rx2/internet/observing/strategy/WalledGardenInternetObservingStrategyTest.java index db42cada..4545bd94 100644 --- a/library/src/test/java/com/github/pwittchen/reactivenetwork/library/rx2/internet/observing/strategy/WalledGardenInternetObservingStrategyTest.java +++ b/library/src/test/java/com/github/pwittchen/reactivenetwork/library/rx2/internet/observing/strategy/WalledGardenInternetObservingStrategyTest.java @@ -36,7 +36,8 @@ @Config(manifest = Config.NONE) @RunWith(RobolectricTestRunner.class) -@SuppressWarnings("NullAway") public class WalledGardenInternetObservingStrategyTest { +@SuppressWarnings("NullAway") +public class WalledGardenInternetObservingStrategyTest { private static final int INITIAL_INTERVAL_IN_MS = 0; private static final int INTERVAL_IN_MS = 2000; diff --git a/library/src/test/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/NetworkObservingStrategyTest.java b/library/src/test/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/NetworkObservingStrategyTest.java deleted file mode 100644 index a48ec808..00000000 --- a/library/src/test/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/NetworkObservingStrategyTest.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2016 Piotr Wittchen - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.github.pwittchen.reactivenetwork.library.rx2.network.observing; - -import android.annotation.SuppressLint; -import android.content.Context; -import android.net.NetworkInfo; -import com.github.pwittchen.reactivenetwork.library.rx2.Connectivity; -import com.github.pwittchen.reactivenetwork.library.rx2.network.observing.strategy.LollipopNetworkObservingStrategy; -import com.github.pwittchen.reactivenetwork.library.rx2.network.observing.strategy.PreLollipopNetworkObservingStrategy; -import io.reactivex.disposables.Disposable; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.RuntimeEnvironment; -import static com.google.common.truth.Truth.assertThat; - -@RunWith(RobolectricTestRunner.class) -@SuppressWarnings("NullAway") public class NetworkObservingStrategyTest { - - @Test public void lollipopObserveNetworkConnectivityShouldBeConnectedWhenNetworkIsAvailable() { - // given - final NetworkObservingStrategy strategy = new LollipopNetworkObservingStrategy(); - - // when - assertThatIsConnected(strategy); - } - - @Test public void preLollipopObserveNetworkConnectivityShouldBeConnectedWhenNetworkIsAvailable() { - // given - final NetworkObservingStrategy strategy = new PreLollipopNetworkObservingStrategy(); - - // when - assertThatIsConnected(strategy); - } - - @SuppressLint("CheckResult") - private void assertThatIsConnected(NetworkObservingStrategy strategy) { - // given - final Context context = RuntimeEnvironment.getApplication().getApplicationContext(); - - //when - Disposable disposable = strategy.observeNetworkConnectivity(context) - .subscribe( - (@SuppressLint("CheckResult") Connectivity connectivity) -> { - // then - assertThat(connectivity.state()).isEqualTo(NetworkInfo.State.CONNECTED); - }); - - disposable.dispose(); - } -} diff --git a/library/src/test/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/strategy/LollipopNetworkObservingStrategyTest.java b/library/src/test/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/strategy/LollipopNetworkObservingStrategyTest.java index 6860ed16..ad02bce3 100644 --- a/library/src/test/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/strategy/LollipopNetworkObservingStrategyTest.java +++ b/library/src/test/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/strategy/LollipopNetworkObservingStrategyTest.java @@ -17,7 +17,6 @@ import android.app.Application; import android.content.Context; -import android.net.NetworkInfo; import com.github.pwittchen.reactivenetwork.library.rx2.Connectivity; import com.github.pwittchen.reactivenetwork.library.rx2.network.observing.NetworkObservingStrategy; import io.reactivex.Observable; @@ -30,13 +29,16 @@ import org.mockito.junit.MockitoRule; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @RunWith(RobolectricTestRunner.class) -@SuppressWarnings("NullAway") public class LollipopNetworkObservingStrategyTest { +@SuppressWarnings("NullAway") +@Config(sdk = 21) +public class LollipopNetworkObservingStrategyTest { @Rule public MockitoRule rule = MockitoJUnit.rule(); @Spy private NetworkObservingStrategy strategy = new LollipopNetworkObservingStrategy(); @@ -50,7 +52,8 @@ Connectivity connectivity = strategy.observeNetworkConnectivity(context).blockingFirst(); // then - assertThat(connectivity.state()).isEqualTo(NetworkInfo.State.CONNECTED); + assertThat(connectivity.networkState()).isNotNull(); + assertThat(connectivity.networkState().isConnected()).isTrue(); } @Test public void shouldStopObservingConnectivity() { diff --git a/library/src/test/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/strategy/MarshmallowNetworkObservingStrategyTest.java b/library/src/test/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/strategy/MarshmallowNetworkObservingStrategyTest.java index 9a161dfc..4b1f8fd4 100644 --- a/library/src/test/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/strategy/MarshmallowNetworkObservingStrategyTest.java +++ b/library/src/test/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/strategy/MarshmallowNetworkObservingStrategyTest.java @@ -40,6 +40,7 @@ import org.reactivestreams.Publisher; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; @@ -50,7 +51,9 @@ // we're suppressing PMD warnings because we want static imports in tests @RunWith(RobolectricTestRunner.class) -@SuppressWarnings({ "PMD", "NullAway" }) public class MarshmallowNetworkObservingStrategyTest { +@SuppressWarnings({ "PMD", "NullAway" }) +@Config(sdk = 23) +public class MarshmallowNetworkObservingStrategyTest { @Rule public MockitoRule rule = MockitoJUnit.rule(); @Spy private MarshmallowNetworkObservingStrategy strategy = @@ -75,7 +78,8 @@ Connectivity connectivity = strategy.observeNetworkConnectivity(context).blockingFirst(); // then - assertThat(connectivity.state()).isEqualTo(NetworkInfo.State.CONNECTED); + assertThat(connectivity.networkState()).isNotNull(); + assertThat(connectivity.networkState().isConnected()).isTrue(); } @Test public void shouldStopObservingConnectivity() { @@ -269,32 +273,34 @@ public void shouldHandleErrorWhileTryingToUnregisterCallback() { verify(strategy).onError(MarshmallowNetworkObservingStrategy.ERROR_MSG_RECEIVER, exception); } - @Test public void shouldPropagateCurrentAndLastConnectivityWhenSwitchingFromWifiToMobile() { + @Test @Config(sdk = 23) + public void shouldPropagateCurrentAndLastConnectivityWhenSwitchingFromWifiToMobileApi23() { final int lastType = ConnectivityManager.TYPE_WIFI; final int currentType = ConnectivityManager.TYPE_MOBILE; - assertThatConnectivityIsPropagatedDuringChange(lastType, currentType); } - @Test public void shouldPropagateCurrentAndLastConnectivityWhenSwitchingFromMobileToWifi() { + @Test @Config(sdk = 23) + public void shouldPropagateCurrentAndLastConnectivityWhenSwitchingFromMobileToWifiApi23() { final int lastType = ConnectivityManager.TYPE_MOBILE; final int currentType = ConnectivityManager.TYPE_WIFI; - assertThatConnectivityIsPropagatedDuringChange(lastType, currentType); } private void assertThatConnectivityIsPropagatedDuringChange( - final int lastType, final int currentType) { + final int lastType, final int currentType + ) { // given final Connectivity last = new Connectivity.Builder() .type(lastType) .state(NetworkInfo.State.CONNECTED) + .detailedState(NetworkInfo.DetailedState.CONNECTED) .build(); final Connectivity current = new Connectivity.Builder() .type(currentType) .state(NetworkInfo.State.DISCONNECTED) - .detailedState(NetworkInfo.DetailedState.CONNECTED) + .detailedState(NetworkInfo.DetailedState.DISCONNECTED) .build(); // when @@ -377,27 +383,4 @@ private void assertThatConnectivityIsPropagatedDuringChange( testSubscriber.assertValueCount(1); testSubscriber.assertValues(current); } - - @Test public void shouldNotPropagateLastConnectivityWhenIsIdle() { - // given - final Connectivity last = new Connectivity.Builder() - .type(ConnectivityManager.TYPE_WIFI) - .state(NetworkInfo.State.CONNECTED) - .build(); - - final Connectivity current = new Connectivity.Builder() - .type(ConnectivityManager.TYPE_MOBILE) - .state(NetworkInfo.State.DISCONNECTED) - .detailedState(NetworkInfo.DetailedState.IDLE) - .build(); - - // when - final Publisher publisher = strategy.propagateAnyConnectedState(last, current); - - // then - final TestSubscriber testSubscriber = new TestSubscriber<>(); - publisher.subscribe(testSubscriber); - testSubscriber.assertValueCount(1); - testSubscriber.assertValues(current); - } } diff --git a/library/src/test/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/strategy/PreLollipopNetworkObservingStrategyTest.java b/library/src/test/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/strategy/PreLollipopNetworkObservingStrategyTest.java index f087b9bb..80e1d18d 100644 --- a/library/src/test/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/strategy/PreLollipopNetworkObservingStrategyTest.java +++ b/library/src/test/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/strategy/PreLollipopNetworkObservingStrategyTest.java @@ -15,11 +15,9 @@ */ package com.github.pwittchen.reactivenetwork.library.rx2.network.observing.strategy; -import android.annotation.SuppressLint; import android.app.Application; import android.content.BroadcastReceiver; import android.content.Context; -import android.net.NetworkInfo; import com.github.pwittchen.reactivenetwork.library.rx2.Connectivity; import com.github.pwittchen.reactivenetwork.library.rx2.network.observing.NetworkObservingStrategy; import io.reactivex.Observable; @@ -33,6 +31,8 @@ import org.mockito.junit.MockitoRule; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; + import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; @@ -42,30 +42,19 @@ // We are suppressing PMD here because we want static imports in unit tests @RunWith(RobolectricTestRunner.class) -@SuppressWarnings({ "PMD", "NullAway" }) public class PreLollipopNetworkObservingStrategyTest { +@Config(sdk = 19) +@SuppressWarnings({ "PMD", "NullAway" }) +public class PreLollipopNetworkObservingStrategyTest { @Rule public MockitoRule rule = MockitoJUnit.rule(); - @Spy private PreLollipopNetworkObservingStrategy strategy = - new PreLollipopNetworkObservingStrategy(); + @Spy private PreLollipopNetworkObservingStrategy strategy + = new PreLollipopNetworkObservingStrategy(); @Mock private BroadcastReceiver broadcastReceiver; - @SuppressLint("CheckResult") @Test @SuppressWarnings("CheckReturnValue") - public void shouldObserveConnectivity() { - // given - final NetworkObservingStrategy strategy = new PreLollipopNetworkObservingStrategy(); - final Context context = RuntimeEnvironment.application.getApplicationContext(); - - // when - strategy.observeNetworkConnectivity(context).subscribe(connectivity -> { - // then - assertThat(connectivity.state()).isEqualTo(NetworkInfo.State.CONNECTED); - }); - } - @Test public void shouldStopObservingConnectivity() { // given final NetworkObservingStrategy strategy = new PreLollipopNetworkObservingStrategy(); - final Context context = RuntimeEnvironment.application.getApplicationContext(); + final Context context = RuntimeEnvironment.getApplication().getApplicationContext(); final Observable observable = strategy.observeNetworkConnectivity(context); final TestObserver observer = new TestObserver<>(); From 8208f5e0723f8fdb73383b59c1532dabd7ecf6ee Mon Sep 17 00:00:00 2001 From: Piotr Wittchen Date: Mon, 5 Dec 2022 00:42:42 +0100 Subject: [PATCH 3/7] [WIP] commented-out old logic in MarshmallowNetworkObservingStrategy and added todo comments (2 tests are failing now) --- .../MarshmallowNetworkObservingStrategy.java | 103 ++++++++++-------- 1 file changed, 59 insertions(+), 44 deletions(-) diff --git a/library/src/main/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/strategy/MarshmallowNetworkObservingStrategy.java b/library/src/main/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/strategy/MarshmallowNetworkObservingStrategy.java index fd510939..25edb569 100644 --- a/library/src/main/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/strategy/MarshmallowNetworkObservingStrategy.java +++ b/library/src/main/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/strategy/MarshmallowNetworkObservingStrategy.java @@ -87,22 +87,29 @@ public MarshmallowNetworkObservingStrategy() { //todo: fix logic of the stream below for the network state - return connectivitySubject.toFlowable(BackpressureStrategy.LATEST).doOnCancel(new Action() { - @Override public void run() { - tryToUnregisterCallback(manager); - tryToUnregisterReceiver(context); - } - }).doAfterNext(new Consumer() { - @Override - public void accept(final Connectivity connectivity) { - lastConnectivity = connectivity; - } - }).flatMap(new Function>() { - @Override - public Publisher apply(final Connectivity connectivity) { - return propagateAnyConnectedState(lastConnectivity, connectivity); - } - }).startWith(Connectivity.create(context)).distinctUntilChanged().toObservable(); + return connectivitySubject + .toFlowable(BackpressureStrategy.LATEST) + .doOnCancel(new Action() { + @Override public void run() { + tryToUnregisterCallback(manager); + tryToUnregisterReceiver(context); + } + }) + .doAfterNext(new Consumer() { + @Override + public void accept(final Connectivity connectivity) { + lastConnectivity = connectivity; + } + }) + .flatMap(new Function>() { + @Override + public Publisher apply(final Connectivity connectivity) { + return propagateAnyConnectedState(lastConnectivity, connectivity); + } + }) + .startWith(Connectivity.create(context)) + //.distinctUntilChanged() + .toObservable(); } //todo: fix logic of this method for the network state @@ -111,33 +118,42 @@ protected Publisher propagateAnyConnectedState( final Connectivity last, final Connectivity current ) { - final boolean hasNetworkState - = last.networkState() != null - && current.networkState() != null; - - final boolean typeChanged = last.type() != current.type(); - - boolean wasConnected; - boolean isDisconnected; - boolean isNotIdle; - - if (hasNetworkState) { - // handling new NetworkState API - wasConnected = last.networkState().isConnected(); - isDisconnected = !current.networkState().isConnected(); - isNotIdle = true; - } else { - // handling legacy, deprecated NetworkInfo API - wasConnected = last.state() == NetworkInfo.State.CONNECTED; - isDisconnected = current.state() == NetworkInfo.State.DISCONNECTED; - isNotIdle = current.detailedState() != NetworkInfo.DetailedState.IDLE; - } - - if (typeChanged && wasConnected && isDisconnected && isNotIdle) { - return Flowable.fromArray(current, last); - } else { - return Flowable.fromArray(current); - } + //final boolean hasNetworkState + // = last.networkState() != null + // && current.networkState() != null; + // + //final boolean typeChanged = last.type() != current.type(); + // + //boolean wasConnected; + //boolean isDisconnected; + //boolean isNotIdle; + // + //if (hasNetworkState) { + // // handling new NetworkState API + // wasConnected = last.networkState().isConnected(); + // isDisconnected = !current.networkState().isConnected(); + // isNotIdle = true; + //} else { + // // handling legacy, deprecated NetworkInfo API + // wasConnected = last.state() == NetworkInfo.State.CONNECTED; + // isDisconnected = current.state() == NetworkInfo.State.DISCONNECTED; + // isNotIdle = current.detailedState() != NetworkInfo.DetailedState.IDLE; + //} + // + //if (typeChanged && wasConnected && isDisconnected && isNotIdle) { + // return Flowable.fromArray(current, last); + //} else { + // return Flowable.fromArray(current); + //} + + //todo: Use value below to verify if at least one connection is active. + // Consider storing it in a hashmap with current state and then use it for the future logic. + // We may receive onLost event for one type of network, while another one is connected, + // what may produce false-positive that network is lost. In such case, we need to produce + // onAvailable event for the remaining connected network(s). + //current.networkState().getNetwork().getNetworkHandle(); + + return Flowable.fromArray(current); } protected void registerIdleReceiver(final Context context) { @@ -219,7 +235,6 @@ public void onLinkPropertiesChanged( } @Override public void onUnavailable() { - super.onUnavailable(); networkState.setConnected(false); onNext(Connectivity.create(context, networkState)); } From 20b68b9401d6bb1e6af91edcff80dcc473c6ea28 Mon Sep 17 00:00:00 2001 From: Piotr Wittchen Date: Sun, 11 Dec 2022 00:45:55 +0100 Subject: [PATCH 4/7] [WIP] fixed handling state in MarshMallowNetworkObservingStrategy --- .../library/rx2/info/NetworkState.java | 89 +++++++----- .../MarshmallowNetworkObservingStrategy.java | 137 ++++++++---------- 2 files changed, 109 insertions(+), 117 deletions(-) diff --git a/library/src/main/java/com/github/pwittchen/reactivenetwork/library/rx2/info/NetworkState.java b/library/src/main/java/com/github/pwittchen/reactivenetwork/library/rx2/info/NetworkState.java index 8ecfa43e..89dae609 100644 --- a/library/src/main/java/com/github/pwittchen/reactivenetwork/library/rx2/info/NetworkState.java +++ b/library/src/main/java/com/github/pwittchen/reactivenetwork/library/rx2/info/NetworkState.java @@ -1,3 +1,18 @@ +/* + * Copyright (C) 2022 Piotr Wittchen + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package com.github.pwittchen.reactivenetwork.library.rx2.info; import android.net.LinkProperties; @@ -8,41 +23,41 @@ @Open public class NetworkState { - @SuppressWarnings("PMD") private boolean isConnected = false; - @Nullable private Network network = null; - @Nullable private NetworkCapabilities networkCapabilities = null; - @Nullable private LinkProperties linkProperties = null; - - @SuppressWarnings("PMD") - public boolean isConnected() { - return isConnected; - } - - public void setConnected(boolean connected) { - isConnected = connected; - } - - @Nullable public Network getNetwork() { - return network; - } - - public void setNetwork(@Nullable Network network) { - this.network = network; - } - - @Nullable public NetworkCapabilities getNetworkCapabilities() { - return networkCapabilities; - } - - public void setNetworkCapabilities(@Nullable NetworkCapabilities networkCapabilities) { - this.networkCapabilities = networkCapabilities; - } - - @Nullable public LinkProperties getLinkProperties() { - return linkProperties; - } - - public void setLinkProperties(@Nullable LinkProperties linkProperties) { - this.linkProperties = linkProperties; - } + @SuppressWarnings("PMD") private boolean isConnected = false; + @Nullable private Network network = null; + @Nullable private NetworkCapabilities networkCapabilities = null; + @Nullable private LinkProperties linkProperties = null; + + @SuppressWarnings("PMD") + public boolean isConnected() { + return isConnected; + } + + public void setConnected(boolean connected) { + isConnected = connected; + } + + @Nullable public Network getNetwork() { + return network; + } + + public void setNetwork(@Nullable Network network) { + this.network = network; + } + + @Nullable public NetworkCapabilities getNetworkCapabilities() { + return networkCapabilities; + } + + public void setNetworkCapabilities(@Nullable NetworkCapabilities networkCapabilities) { + this.networkCapabilities = networkCapabilities; + } + + @Nullable public LinkProperties getLinkProperties() { + return linkProperties; + } + + public void setLinkProperties(@Nullable LinkProperties linkProperties) { + this.linkProperties = linkProperties; + } } diff --git a/library/src/main/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/strategy/MarshmallowNetworkObservingStrategy.java b/library/src/main/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/strategy/MarshmallowNetworkObservingStrategy.java index 25edb569..dfc37a4d 100644 --- a/library/src/main/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/strategy/MarshmallowNetworkObservingStrategy.java +++ b/library/src/main/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/strategy/MarshmallowNetworkObservingStrategy.java @@ -24,27 +24,25 @@ import android.net.LinkProperties; import android.net.Network; import android.net.NetworkCapabilities; -import android.net.NetworkInfo; import android.net.NetworkRequest; import android.os.PowerManager; import android.util.Log; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import com.github.pwittchen.reactivenetwork.library.rx2.Connectivity; import com.github.pwittchen.reactivenetwork.library.rx2.info.NetworkState; import com.github.pwittchen.reactivenetwork.library.rx2.network.observing.NetworkObservingStrategy; import com.jakewharton.nopen.annotation.Open; import io.reactivex.BackpressureStrategy; -import io.reactivex.Flowable; import io.reactivex.Observable; -import io.reactivex.functions.Action; -import io.reactivex.functions.Consumer; -import io.reactivex.functions.Function; import io.reactivex.subjects.PublishSubject; import io.reactivex.subjects.Subject; -import org.reactivestreams.Publisher; - +import java.util.HashMap; +import java.util.Map; import static com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork.LOG_TAG; +//todo: move this code to the new QObservingStrategy and keep this unchanged (like in the RxJava2.x branch) + /** * Network observing strategy for devices with Android Marshmallow (API 23) or higher. * Uses Network Callback API and handles Doze mode. @@ -52,16 +50,13 @@ @Open @TargetApi(23) public class MarshmallowNetworkObservingStrategy implements NetworkObservingStrategy { - protected static final String ERROR_MSG_NETWORK_CALLBACK = - "could not unregister network callback"; + protected static final String ERROR_MSG_NETWORK_CALLBACK = "could not unregister network callback"; protected static final String ERROR_MSG_RECEIVER = "could not unregister receiver"; @SuppressWarnings("NullAway") // it has to be initialized in the Observable due to Context private ConnectivityManager.NetworkCallback networkCallback; private final Subject connectivitySubject; private final BroadcastReceiver idleReceiver; - private Connectivity lastConnectivity = Connectivity.create(); - - @SuppressWarnings("FieldMayBeFinal") private NetworkState networkState = new NetworkState(); + private final Map availableNetworks = new HashMap<>(); @SuppressWarnings("NullAway") // networkCallback cannot be initialized here public MarshmallowNetworkObservingStrategy() { @@ -85,77 +80,16 @@ public MarshmallowNetworkObservingStrategy() { manager.registerNetworkCallback(request, networkCallback); - //todo: fix logic of the stream below for the network state - return connectivitySubject .toFlowable(BackpressureStrategy.LATEST) - .doOnCancel(new Action() { - @Override public void run() { - tryToUnregisterCallback(manager); - tryToUnregisterReceiver(context); - } - }) - .doAfterNext(new Consumer() { - @Override - public void accept(final Connectivity connectivity) { - lastConnectivity = connectivity; - } - }) - .flatMap(new Function>() { - @Override - public Publisher apply(final Connectivity connectivity) { - return propagateAnyConnectedState(lastConnectivity, connectivity); - } + .doOnCancel(() -> { + tryToUnregisterCallback(manager); + tryToUnregisterReceiver(context); }) .startWith(Connectivity.create(context)) - //.distinctUntilChanged() .toObservable(); } - //todo: fix logic of this method for the network state - @SuppressWarnings("NullAway") - protected Publisher propagateAnyConnectedState( - final Connectivity last, - final Connectivity current - ) { - //final boolean hasNetworkState - // = last.networkState() != null - // && current.networkState() != null; - // - //final boolean typeChanged = last.type() != current.type(); - // - //boolean wasConnected; - //boolean isDisconnected; - //boolean isNotIdle; - // - //if (hasNetworkState) { - // // handling new NetworkState API - // wasConnected = last.networkState().isConnected(); - // isDisconnected = !current.networkState().isConnected(); - // isNotIdle = true; - //} else { - // // handling legacy, deprecated NetworkInfo API - // wasConnected = last.state() == NetworkInfo.State.CONNECTED; - // isDisconnected = current.state() == NetworkInfo.State.DISCONNECTED; - // isNotIdle = current.detailedState() != NetworkInfo.DetailedState.IDLE; - //} - // - //if (typeChanged && wasConnected && isDisconnected && isNotIdle) { - // return Flowable.fromArray(current, last); - //} else { - // return Flowable.fromArray(current); - //} - - //todo: Use value below to verify if at least one connection is active. - // Consider storing it in a hashmap with current state and then use it for the future logic. - // We may receive onLost event for one type of network, while another one is connected, - // what may produce false-positive that network is lost. In such case, we need to produce - // onAvailable event for the remaining connected network(s). - //current.networkState().getNetwork().getNetworkHandle(); - - return Flowable.fromArray(current); - } - protected void registerIdleReceiver(final Context context) { final IntentFilter filter = new IntentFilter(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED); context.registerReceiver(idleReceiver, filter); @@ -207,8 +141,10 @@ public void onCapabilitiesChanged( @NonNull Network network, @NonNull NetworkCapabilities networkCapabilities ) { + final NetworkState networkState = getOrCreateState(network); networkState.setNetwork(network); networkState.setNetworkCapabilities(networkCapabilities); + saveState(network, networkState); onNext(Connectivity.create(context, networkState)); } @@ -217,26 +153,67 @@ public void onLinkPropertiesChanged( @NonNull Network network, @NonNull LinkProperties linkProperties ) { + final NetworkState networkState = getOrCreateState(network); networkState.setNetwork(network); networkState.setLinkProperties(linkProperties); + saveState(network, networkState); onNext(Connectivity.create(context, networkState)); } @Override public void onAvailable(@NonNull Network network) { + final NetworkState networkState = getOrCreateState(network); networkState.setNetwork(network); networkState.setConnected(true); + saveState(network, networkState); onNext(Connectivity.create(context, networkState)); } @Override public void onLost(@NonNull Network network) { - networkState.setNetwork(network); - networkState.setConnected(false); - onNext(Connectivity.create(context, networkState)); + removeState(network); + onNext(Connectivity.create(context, createDisconnectedState())); + + final NetworkState lastAvailableState = getLastAvailableStateIfExists(); + if (lastAvailableState != null) { + onNext(Connectivity.create(context, lastAvailableState)); + } } @Override public void onUnavailable() { + onNext(Connectivity.create(context, createDisconnectedState())); + } + + @NonNull private NetworkState getOrCreateState(@NonNull final Network network) { + NetworkState networkState = availableNetworks.get(network.toString()); + if (networkState == null) { + networkState = new NetworkState(); + } + return networkState; + } + + @NonNull private NetworkState createDisconnectedState() { + final NetworkState networkState = new NetworkState(); + networkState.setNetwork(null); networkState.setConnected(false); - onNext(Connectivity.create(context, networkState)); + networkState.setLinkProperties(null); + networkState.setNetworkCapabilities(null); + return networkState; + } + + @Nullable private NetworkState getLastAvailableStateIfExists() { + if (!availableNetworks.isEmpty()) { + for (Map.Entry entry : availableNetworks.entrySet()) { + return entry.getValue(); + } + } + return null; + } + + private void saveState(@NonNull Network network, NetworkState networkState) { + availableNetworks.put(network.toString(), networkState); + } + + private void removeState(@NonNull Network network) { + availableNetworks.remove(network.toString()); } }; } From f7ed3f07d72c3c9904da2a68d4e0929c45227a3d Mon Sep 17 00:00:00 2001 From: Piotr Wittchen Date: Sun, 11 Dec 2022 01:00:47 +0100 Subject: [PATCH 5/7] added comment in the code with explanation of using state, because it may not be clear at the first look --- .../strategy/MarshmallowNetworkObservingStrategy.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/library/src/main/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/strategy/MarshmallowNetworkObservingStrategy.java b/library/src/main/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/strategy/MarshmallowNetworkObservingStrategy.java index dfc37a4d..23b06611 100644 --- a/library/src/main/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/strategy/MarshmallowNetworkObservingStrategy.java +++ b/library/src/main/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/strategy/MarshmallowNetworkObservingStrategy.java @@ -56,6 +56,12 @@ public class MarshmallowNetworkObservingStrategy implements NetworkObservingStra private ConnectivityManager.NetworkCallback networkCallback; private final Subject connectivitySubject; private final BroadcastReceiver idleReceiver; + + // PLEASE NOTE: State of available networks is required to handle cases when user is connected to multiple networks, + // but looses connection with one of them. In such case, only onLost event is generated by the NetworkCallback, + // so we need to manually propagate event with the available connected network down the stream in onLost event. + // With this approach user will always receive an information about connectivity, if there is any. + // This behavior is consistent with the remaining NetworkObservingStrategies private final Map availableNetworks = new HashMap<>(); @SuppressWarnings("NullAway") // networkCallback cannot be initialized here From b6bc8e79b0d7fa9cba86b0b6d9fe2dd6c8875557 Mon Sep 17 00:00:00 2001 From: Piotr Wittchen Date: Sun, 11 Dec 2022 01:03:28 +0100 Subject: [PATCH 6/7] temporarily commenting-out a few tests in MarshmallowNetworkObservingStrategyTest to compile and run other tests --- ...rshmallowNetworkObservingStrategyTest.java | 230 +++++++++--------- 1 file changed, 120 insertions(+), 110 deletions(-) diff --git a/library/src/test/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/strategy/MarshmallowNetworkObservingStrategyTest.java b/library/src/test/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/strategy/MarshmallowNetworkObservingStrategyTest.java index 4b1f8fd4..d08f5c34 100644 --- a/library/src/test/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/strategy/MarshmallowNetworkObservingStrategyTest.java +++ b/library/src/test/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/strategy/MarshmallowNetworkObservingStrategyTest.java @@ -273,114 +273,124 @@ public void shouldHandleErrorWhileTryingToUnregisterCallback() { verify(strategy).onError(MarshmallowNetworkObservingStrategy.ERROR_MSG_RECEIVER, exception); } - @Test @Config(sdk = 23) - public void shouldPropagateCurrentAndLastConnectivityWhenSwitchingFromWifiToMobileApi23() { - final int lastType = ConnectivityManager.TYPE_WIFI; - final int currentType = ConnectivityManager.TYPE_MOBILE; - assertThatConnectivityIsPropagatedDuringChange(lastType, currentType); - } - - @Test @Config(sdk = 23) - public void shouldPropagateCurrentAndLastConnectivityWhenSwitchingFromMobileToWifiApi23() { - final int lastType = ConnectivityManager.TYPE_MOBILE; - final int currentType = ConnectivityManager.TYPE_WIFI; - assertThatConnectivityIsPropagatedDuringChange(lastType, currentType); - } - - private void assertThatConnectivityIsPropagatedDuringChange( - final int lastType, final int currentType - ) { - // given - final Connectivity last = new Connectivity.Builder() - .type(lastType) - .state(NetworkInfo.State.CONNECTED) - .detailedState(NetworkInfo.DetailedState.CONNECTED) - .build(); - - final Connectivity current = new Connectivity.Builder() - .type(currentType) - .state(NetworkInfo.State.DISCONNECTED) - .detailedState(NetworkInfo.DetailedState.DISCONNECTED) - .build(); - - // when - final Publisher publisher = strategy.propagateAnyConnectedState(last, current); - - // then - final TestSubscriber testSubscriber = new TestSubscriber<>(); - publisher.subscribe(testSubscriber); - testSubscriber.assertValueCount(2); - testSubscriber.assertValues(current, last); - testSubscriber.assertValueAt(0, current); - testSubscriber.assertValueAt(1, last); - } - - @Test public void shouldNotPropagateLastConnectivityEventWhenTypeIsNotChanged() { - // given - final Connectivity last = new Connectivity.Builder() - .type(ConnectivityManager.TYPE_WIFI) - .state(NetworkInfo.State.CONNECTED) - .build(); - - final Connectivity current = new Connectivity.Builder() - .type(ConnectivityManager.TYPE_WIFI) - .state(NetworkInfo.State.DISCONNECTED) - .detailedState(NetworkInfo.DetailedState.CONNECTED) - .build(); - - // when - final Publisher publisher = strategy.propagateAnyConnectedState(last, current); - - // then - final TestSubscriber testSubscriber = new TestSubscriber<>(); - publisher.subscribe(testSubscriber); - testSubscriber.assertValueCount(1); - testSubscriber.assertValues(current); - } - - @Test public void shouldNotPropagateLastConnectivityWhenWasNotConnected() { - // given - final Connectivity last = new Connectivity.Builder() - .type(ConnectivityManager.TYPE_WIFI) - .state(NetworkInfo.State.DISCONNECTED) - .build(); - - final Connectivity current = new Connectivity.Builder() - .type(ConnectivityManager.TYPE_MOBILE) - .state(NetworkInfo.State.CONNECTED) - .detailedState(NetworkInfo.DetailedState.CONNECTED) - .build(); - - // when - final Publisher publisher = strategy.propagateAnyConnectedState(last, current); - - // then - final TestSubscriber testSubscriber = new TestSubscriber<>(); - publisher.subscribe(testSubscriber); - testSubscriber.assertValueCount(1); - testSubscriber.assertValues(current); - } - - @Test public void shouldNotPropagateLastConnectivityWhenIsConnected() { - // given - final Connectivity last = new Connectivity.Builder() - .type(ConnectivityManager.TYPE_WIFI) - .state(NetworkInfo.State.CONNECTED) - .build(); - - final Connectivity current = new Connectivity.Builder() - .type(ConnectivityManager.TYPE_MOBILE) - .state(NetworkInfo.State.CONNECTED) - .detailedState(NetworkInfo.DetailedState.CONNECTED) - .build(); - - // when - final Publisher publisher = strategy.propagateAnyConnectedState(last, current); - - // then - final TestSubscriber testSubscriber = new TestSubscriber<>(); - publisher.subscribe(testSubscriber); - testSubscriber.assertValueCount(1); - testSubscriber.assertValues(current); - } + //@Test @Config(sdk = 23) + //public void shouldPropagateCurrentAndLastConnectivityWhenSwitchingFromWifiToMobileApi23() { + // //todo: fix this test + // final int lastType = ConnectivityManager.TYPE_WIFI; + // final int currentType = ConnectivityManager.TYPE_MOBILE; + // assertThatConnectivityIsPropagatedDuringChange(lastType, currentType); + //} + + //@Test @Config(sdk = 23) + //public void shouldPropagateCurrentAndLastConnectivityWhenSwitchingFromMobileToWifiApi23() { + // //todo: fix this test + // final int lastType = ConnectivityManager.TYPE_MOBILE; + // final int currentType = ConnectivityManager.TYPE_WIFI; + // assertThatConnectivityIsPropagatedDuringChange(lastType, currentType); + //} + + //private void assertThatConnectivityIsPropagatedDuringChange( + // final int lastType, final int currentType + //) { + // //todo: fix this assertion + // + // // given + // final Connectivity last = new Connectivity.Builder() + // .type(lastType) + // .state(NetworkInfo.State.CONNECTED) + // .detailedState(NetworkInfo.DetailedState.CONNECTED) + // .build(); + // + // final Connectivity current = new Connectivity.Builder() + // .type(currentType) + // .state(NetworkInfo.State.DISCONNECTED) + // .detailedState(NetworkInfo.DetailedState.DISCONNECTED) + // .build(); + // + // // when + // final Publisher publisher = strategy.propagateAnyConnectedState(last, current); + // + // // then + // final TestSubscriber testSubscriber = new TestSubscriber<>(); + // publisher.subscribe(testSubscriber); + // testSubscriber.assertValueCount(2); + // testSubscriber.assertValues(current, last); + // testSubscriber.assertValueAt(0, current); + // testSubscriber.assertValueAt(1, last); + //} + + //@Test public void shouldNotPropagateLastConnectivityEventWhenTypeIsNotChanged() { + // //todo: fix this test + // + // // given + // final Connectivity last = new Connectivity.Builder() + // .type(ConnectivityManager.TYPE_WIFI) + // .state(NetworkInfo.State.CONNECTED) + // .build(); + // + // final Connectivity current = new Connectivity.Builder() + // .type(ConnectivityManager.TYPE_WIFI) + // .state(NetworkInfo.State.DISCONNECTED) + // .detailedState(NetworkInfo.DetailedState.CONNECTED) + // .build(); + // + // // when + // final Publisher publisher = strategy.propagateAnyConnectedState(last, current); + // + // // then + // final TestSubscriber testSubscriber = new TestSubscriber<>(); + // publisher.subscribe(testSubscriber); + // testSubscriber.assertValueCount(1); + // testSubscriber.assertValues(current); + //} + + //@Test public void shouldNotPropagateLastConnectivityWhenWasNotConnected() { + // //todo: fix this test + // + // // given + // final Connectivity last = new Connectivity.Builder() + // .type(ConnectivityManager.TYPE_WIFI) + // .state(NetworkInfo.State.DISCONNECTED) + // .build(); + // + // final Connectivity current = new Connectivity.Builder() + // .type(ConnectivityManager.TYPE_MOBILE) + // .state(NetworkInfo.State.CONNECTED) + // .detailedState(NetworkInfo.DetailedState.CONNECTED) + // .build(); + // + // // when + // final Publisher publisher = strategy.propagateAnyConnectedState(last, current); + // + // // then + // final TestSubscriber testSubscriber = new TestSubscriber<>(); + // publisher.subscribe(testSubscriber); + // testSubscriber.assertValueCount(1); + // testSubscriber.assertValues(current); + //} + + //@Test public void shouldNotPropagateLastConnectivityWhenIsConnected() { + // //todo: fix this test + // + // // given + // final Connectivity last = new Connectivity.Builder() + // .type(ConnectivityManager.TYPE_WIFI) + // .state(NetworkInfo.State.CONNECTED) + // .build(); + // + // final Connectivity current = new Connectivity.Builder() + // .type(ConnectivityManager.TYPE_MOBILE) + // .state(NetworkInfo.State.CONNECTED) + // .detailedState(NetworkInfo.DetailedState.CONNECTED) + // .build(); + // + // // when + // final Publisher publisher = strategy.propagateAnyConnectedState(last, current); + // + // // then + // final TestSubscriber testSubscriber = new TestSubscriber<>(); + // publisher.subscribe(testSubscriber); + // testSubscriber.assertValueCount(1); + // testSubscriber.assertValues(current); + //} } From 96925e756f546f6d6a8cf9515ab963ccc9f68fad Mon Sep 17 00:00:00 2001 From: Piotr Wittchen Date: Sun, 11 Dec 2022 01:05:55 +0100 Subject: [PATCH 7/7] updating code formatting in tests --- .../MarshmallowNetworkObservingStrategyTest.java | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/library/src/test/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/strategy/MarshmallowNetworkObservingStrategyTest.java b/library/src/test/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/strategy/MarshmallowNetworkObservingStrategyTest.java index d08f5c34..6fc27767 100644 --- a/library/src/test/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/strategy/MarshmallowNetworkObservingStrategyTest.java +++ b/library/src/test/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/strategy/MarshmallowNetworkObservingStrategyTest.java @@ -54,11 +54,8 @@ @SuppressWarnings({ "PMD", "NullAway" }) @Config(sdk = 23) public class MarshmallowNetworkObservingStrategyTest { - @Rule public MockitoRule rule = MockitoJUnit.rule(); - @Spy private MarshmallowNetworkObservingStrategy strategy = - new MarshmallowNetworkObservingStrategy(); - + @Spy private MarshmallowNetworkObservingStrategy strategy = new MarshmallowNetworkObservingStrategy(); @Mock private PowerManager powerManager; @Mock private ConnectivityManager connectivityManager; @Mock private Context contextMock; @@ -249,15 +246,15 @@ public void shouldHandleErrorWhileTryingToUnregisterCallback() { // given strategy.observeNetworkConnectivity(context); final IllegalArgumentException exception = new IllegalArgumentException(); - doThrow(exception).when(connectivityManager) - .unregisterNetworkCallback(any(ConnectivityManager.NetworkCallback.class)); + doThrow(exception).when(connectivityManager).unregisterNetworkCallback( + any(ConnectivityManager.NetworkCallback.class) + ); // when strategy.tryToUnregisterCallback(connectivityManager); // then - verify(strategy).onError(MarshmallowNetworkObservingStrategy.ERROR_MSG_NETWORK_CALLBACK, - exception); + verify(strategy).onError(MarshmallowNetworkObservingStrategy.ERROR_MSG_NETWORK_CALLBACK, exception); } @Test public void shouldHandleErrorWhileTryingToUnregisterReceiver() {