Skip to content

Commit ed161c8

Browse files
committed
fixes in the logic of MarshmallowNetworkObservingStrategy and tests according to PR #455 related to utilization of the NetworkState class
1 parent 0bcd5fe commit ed161c8

12 files changed

+148
-198
lines changed

library/src/main/java/com/github/pwittchen/reactivenetwork/library/rx2/Connectivity.java

+43-33
Original file line numberDiff line numberDiff line change
@@ -17,45 +17,44 @@
1717

1818
import android.content.Context;
1919
import android.net.ConnectivityManager;
20-
import android.net.Network;
21-
import android.net.NetworkCapabilities;
2220
import android.net.NetworkInfo;
2321
import android.os.Build;
2422
import androidx.annotation.NonNull;
23+
import androidx.annotation.Nullable;
2524
import androidx.annotation.RequiresApi;
26-
2725
import com.github.pwittchen.reactivenetwork.library.rx2.info.NetworkState;
2826

2927
/**
3028
* Connectivity class represents current connectivity status. It wraps NetworkInfo object.
3129
*/
32-
@RequiresApi(api = Build.VERSION_CODES.CUPCAKE)
3330
public final class Connectivity {
3431
static final int UNKNOWN_TYPE = -1;
3532
static final int UNKNOWN_SUB_TYPE = -1;
36-
private NetworkInfo.State state; // NOPMD
37-
private NetworkInfo.DetailedState detailedState; // NOPMD
38-
private int type; // NOPMD
39-
private int subType; // NOPMD
40-
private boolean available; // NOPMD
41-
private boolean failover; // NOPMD
42-
private boolean roaming; // NOPMD
43-
private String typeName; // NOPMD
44-
private String subTypeName; // NOPMD
45-
private String reason; // NOPMD
46-
private String extraInfo; // NOPMD
47-
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
48-
private NetworkState networkState;
33+
@Nullable private NetworkInfo.State state; // NOPMD
34+
@Nullable private NetworkInfo.DetailedState detailedState; // NOPMD
35+
@Nullable @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
36+
private NetworkState networkState; // NOPMD
37+
private final int type; // NOPMD
38+
private final int subType; // NOPMD
39+
private final boolean available; // NOPMD
40+
private final boolean failover; // NOPMD
41+
private final boolean roaming; // NOPMD
42+
private final String typeName; // NOPMD
43+
private final String subTypeName; // NOPMD
44+
private final String reason; // NOPMD
45+
private final String extraInfo; // NOPMD
4946

5047
public static Connectivity create() {
5148
return builder().build();
5249
}
5350

51+
@SuppressWarnings("PMD")
5452
public static Connectivity create(@NonNull Context context) {
5553
Preconditions.checkNotNull(context, "context == null");
5654
return create(context, getConnectivityManager(context));
5755
}
5856

57+
@SuppressWarnings("PMD")
5958
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
6059
public static Connectivity create(@NonNull Context context, NetworkState networkState) {
6160
Preconditions.checkNotNull(context, "context == null");
@@ -67,6 +66,7 @@ private static ConnectivityManager getConnectivityManager(Context context) {
6766
return (ConnectivityManager) context.getSystemService(service);
6867
}
6968

69+
@SuppressWarnings("PMD")
7070
protected static Connectivity create(@NonNull Context context, ConnectivityManager manager) {
7171
Preconditions.checkNotNull(context, "context == null");
7272

@@ -78,8 +78,11 @@ protected static Connectivity create(@NonNull Context context, ConnectivityManag
7878
return (networkInfo == null) ? create() : create(networkInfo);
7979
}
8080

81+
@SuppressWarnings("PMD")
8182
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
82-
protected static Connectivity create(@NonNull Context context, ConnectivityManager manager, NetworkState networkState) {
83+
protected static Connectivity create(
84+
@NonNull Context context, ConnectivityManager manager, NetworkState networkState
85+
) {
8386
Preconditions.checkNotNull(context, "context == null");
8487

8588
if (manager == null) {
@@ -109,16 +112,22 @@ private static Connectivity create(NetworkInfo networkInfo) {
109112
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
110113
private static Connectivity create(NetworkState networkState) {
111114
return new Builder()
112-
.networkState(networkState)
113-
.build();
115+
.networkState(networkState)
116+
.build();
114117
}
115118

116119
private Connectivity(Builder builder) {
117-
if(Preconditions.isAtLeastAndroidLollipop()) {
118-
networkState = builder.networkState;
120+
if (Preconditions.isAtLeastAndroidLollipop()) {
121+
if (builder.networkState != null) {
122+
networkState = builder.networkState;
123+
}
119124
} else {
120-
state = builder.state;
121-
detailedState = builder.detailedState;
125+
if (builder.state != null) {
126+
state = builder.state;
127+
}
128+
if (builder.detailedState != null) {
129+
detailedState = builder.detailedState;
130+
}
122131
}
123132
type = builder.type;
124133
subType = builder.subType;
@@ -139,22 +148,28 @@ private static Builder builder() {
139148
return new Connectivity.Builder();
140149
}
141150

142-
public NetworkInfo.State state() {
151+
public @Nullable NetworkInfo.State state() {
143152
return state;
144153
}
145154

146155
public static Builder state(NetworkInfo.State state) {
147156
return builder().state(state);
148157
}
149158

150-
public NetworkInfo.DetailedState detailedState() {
159+
public @Nullable NetworkInfo.DetailedState detailedState() {
151160
return detailedState;
152161
}
153162

154163
public static Builder state(NetworkInfo.DetailedState detailedState) {
155164
return builder().detailedState(detailedState);
156165
}
157166

167+
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
168+
@Nullable
169+
public NetworkState getNetworkState() {
170+
return networkState;
171+
}
172+
158173
public int type() {
159174
return type;
160175
}
@@ -227,11 +242,6 @@ public static Builder extraInfo(String extraInfo) {
227242
return builder().extraInfo(extraInfo);
228243
}
229244

230-
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
231-
public NetworkState getNetworkState() {
232-
return networkState;
233-
}
234-
235245
@Override public boolean equals(Object o) {
236246
if (this == o) {
237247
return true;
@@ -277,7 +287,7 @@ public NetworkState getNetworkState() {
277287
}
278288

279289
@Override public int hashCode() {
280-
int result = state.hashCode();
290+
int result = state != null ? state.hashCode() : 0;
281291
result = 31 * result + (detailedState != null ? detailedState.hashCode() : 0);
282292
result = 31 * result + type;
283293
result = 31 * result + subType;
@@ -338,7 +348,7 @@ public final static class Builder {
338348
private String subTypeName = "NONE"; // NOPMD
339349
private String reason = ""; // NOPMD
340350
private String extraInfo = ""; // NOPMD
341-
private NetworkState networkState = new NetworkState();
351+
private NetworkState networkState = new NetworkState(); // NOPMD
342352

343353
public Builder state(NetworkInfo.State state) {
344354
this.state = state;

library/src/main/java/com/github/pwittchen/reactivenetwork/library/rx2/info/NetworkState.java

+14-13
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,17 @@
33
import android.net.LinkProperties;
44
import android.net.Network;
55
import android.net.NetworkCapabilities;
6+
import androidx.annotation.Nullable;
7+
import com.jakewharton.nopen.annotation.Open;
68

7-
/**
8-
* NetworkState data object
9-
*/
9+
@Open
1010
public class NetworkState {
11-
private boolean isConnected = false;
12-
private Network network = null;
13-
private NetworkCapabilities networkCapabilities = null;
14-
private LinkProperties linkProperties = null;
11+
@SuppressWarnings("PMD") private boolean isConnected = false;
12+
@Nullable private Network network = null;
13+
@Nullable private NetworkCapabilities networkCapabilities = null;
14+
@Nullable private LinkProperties linkProperties = null;
1515

16+
@SuppressWarnings("PMD")
1617
public boolean isConnected() {
1718
return isConnected;
1819
}
@@ -21,27 +22,27 @@ public void setConnected(boolean connected) {
2122
isConnected = connected;
2223
}
2324

24-
public Network getNetwork() {
25+
@Nullable public Network getNetwork() {
2526
return network;
2627
}
2728

28-
public void setNetwork(Network network) {
29+
public void setNetwork(@Nullable Network network) {
2930
this.network = network;
3031
}
3132

32-
public NetworkCapabilities getNetworkCapabilities() {
33+
@Nullable public NetworkCapabilities getNetworkCapabilities() {
3334
return networkCapabilities;
3435
}
3536

36-
public void setNetworkCapabilities(NetworkCapabilities networkCapabilities) {
37+
public void setNetworkCapabilities(@Nullable NetworkCapabilities networkCapabilities) {
3738
this.networkCapabilities = networkCapabilities;
3839
}
3940

40-
public LinkProperties getLinkProperties() {
41+
@Nullable public LinkProperties getLinkProperties() {
4142
return linkProperties;
4243
}
4344

44-
public void setLinkProperties(LinkProperties linkProperties) {
45+
public void setLinkProperties(@Nullable LinkProperties linkProperties) {
4546
this.linkProperties = linkProperties;
4647
}
4748
}

library/src/main/java/com/github/pwittchen/reactivenetwork/library/rx2/network/observing/strategy/MarshmallowNetworkObservingStrategy.java

+39-14
Original file line numberDiff line numberDiff line change
@@ -49,18 +49,19 @@
4949
* Network observing strategy for devices with Android Marshmallow (API 23) or higher.
5050
* Uses Network Callback API and handles Doze mode.
5151
*/
52-
@Open @TargetApi(23) public class MarshmallowNetworkObservingStrategy
53-
implements NetworkObservingStrategy {
52+
@Open
53+
@TargetApi(23)
54+
public class MarshmallowNetworkObservingStrategy implements NetworkObservingStrategy {
5455
protected static final String ERROR_MSG_NETWORK_CALLBACK =
5556
"could not unregister network callback";
5657
protected static final String ERROR_MSG_RECEIVER = "could not unregister receiver";
57-
5858
@SuppressWarnings("NullAway") // it has to be initialized in the Observable due to Context
5959
private ConnectivityManager.NetworkCallback networkCallback;
6060
private final Subject<Connectivity> connectivitySubject;
6161
private final BroadcastReceiver idleReceiver;
6262
private Connectivity lastConnectivity = Connectivity.create();
63-
private NetworkState networkState = new NetworkState();
63+
64+
@SuppressWarnings("FieldMayBeFinal") private NetworkState networkState = new NetworkState();
6465

6566
@SuppressWarnings("NullAway") // networkCallback cannot be initialized here
6667
public MarshmallowNetworkObservingStrategy() {
@@ -76,7 +77,9 @@ public MarshmallowNetworkObservingStrategy() {
7677
registerIdleReceiver(context);
7778

7879
final NetworkRequest request =
79-
new NetworkRequest.Builder().addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
80+
new NetworkRequest
81+
.Builder()
82+
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
8083
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
8184
.build();
8285

@@ -100,12 +103,32 @@ public Publisher<Connectivity> apply(final Connectivity connectivity) {
100103
}).startWith(Connectivity.create(context)).distinctUntilChanged().toObservable();
101104
}
102105

103-
protected Publisher<Connectivity> propagateAnyConnectedState(final Connectivity last,
104-
final Connectivity current) {
106+
@SuppressWarnings("NullAway")
107+
protected Publisher<Connectivity> propagateAnyConnectedState(
108+
final Connectivity last,
109+
final Connectivity current
110+
) {
111+
final boolean hasNetworkState
112+
= last.getNetworkState() != null
113+
&& current.getNetworkState() != null;
114+
105115
final boolean typeChanged = last.type() != current.type();
106-
final boolean wasConnected = last.state() == NetworkInfo.State.CONNECTED;
107-
final boolean isDisconnected = current.state() == NetworkInfo.State.DISCONNECTED;
108-
final boolean isNotIdle = current.detailedState() != NetworkInfo.DetailedState.IDLE;
116+
117+
boolean wasConnected;
118+
boolean isDisconnected;
119+
boolean isNotIdle;
120+
121+
if (hasNetworkState) {
122+
// handling new NetworkState API
123+
wasConnected = last.getNetworkState().isConnected();
124+
isDisconnected = !current.getNetworkState().isConnected();
125+
isNotIdle = true;
126+
} else {
127+
// handling legacy, deprecated NetworkInfo API
128+
wasConnected = last.state() == NetworkInfo.State.CONNECTED;
129+
isDisconnected = current.state() == NetworkInfo.State.DISCONNECTED;
130+
isNotIdle = current.detailedState() != NetworkInfo.DetailedState.IDLE;
131+
}
109132

110133
if (typeChanged && wasConnected && isDisconnected && isNotIdle) {
111134
return Flowable.fromArray(current, last);
@@ -161,26 +184,28 @@ protected void tryToUnregisterReceiver(Context context) {
161184
protected ConnectivityManager.NetworkCallback createNetworkCallback(final Context context) {
162185
return new ConnectivityManager.NetworkCallback() {
163186
@Override
164-
public void onCapabilitiesChanged(@NonNull Network network, @NonNull NetworkCapabilities networkCapabilities) {
187+
public void onCapabilitiesChanged(@NonNull Network network,
188+
@NonNull NetworkCapabilities networkCapabilities) {
165189
networkState.setNetwork(network);
166190
networkState.setNetworkCapabilities(networkCapabilities);
167191
onNext(Connectivity.create(context, networkState));
168192
}
169193

170194
@Override
171-
public void onLinkPropertiesChanged(@NonNull Network network, @NonNull LinkProperties linkProperties) {
195+
public void onLinkPropertiesChanged(@NonNull Network network,
196+
@NonNull LinkProperties linkProperties) {
172197
networkState.setNetwork(network);
173198
networkState.setLinkProperties(linkProperties);
174199
onNext(Connectivity.create(context, networkState));
175200
}
176201

177-
@Override public void onAvailable(Network network) {
202+
@Override public void onAvailable(@NonNull Network network) {
178203
networkState.setNetwork(network);
179204
networkState.setConnected(true);
180205
onNext(Connectivity.create(context, networkState));
181206
}
182207

183-
@Override public void onLost(Network network) {
208+
@Override public void onLost(@NonNull Network network) {
184209
networkState.setNetwork(network);
185210
networkState.setConnected(false);
186211
onNext(Connectivity.create(context, networkState));

library/src/test/java/com/github/pwittchen/reactivenetwork/library/rx2/ConnectivityTest.java

+11-6
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,18 @@
2323
import org.junit.runner.RunWith;
2424
import org.robolectric.RobolectricTestRunner;
2525
import org.robolectric.RuntimeEnvironment;
26+
import org.robolectric.annotation.Config;
2627

2728
import static com.google.common.truth.Truth.assertThat;
2829

2930
@RunWith(RobolectricTestRunner.class)
30-
@SuppressWarnings("NullAway") public class ConnectivityTest {
31+
@SuppressWarnings("NullAway")
32+
public class ConnectivityTest {
3133
private static final String TYPE_NAME_WIFI = "WIFI";
3234
private static final String TYPE_NAME_MOBILE = "MOBILE";
3335
private static final String TYPE_NAME_NONE = "NONE";
3436

35-
@Test public void shouldCreateConnectivity() {
37+
@Test @Config(sdk = 19) public void shouldCreateConnectivity() {
3638
// when
3739
Connectivity connectivity = Connectivity.create();
3840

@@ -66,7 +68,8 @@
6668
assertThat(shouldBeEqualToGivenStatus).isTrue();
6769
}
6870

69-
@Test public void stateShouldBeEqualToOneOfGivenMultipleValues() throws Exception {
71+
@Test @Config(sdk = 19)
72+
public void stateShouldBeEqualToOneOfGivenMultipleValues() throws Exception {
7073
// given
7174
final Connectivity connectivity = Connectivity.state(NetworkInfo.State.CONNECTING)
7275
.type(ConnectivityManager.TYPE_WIFI)
@@ -174,7 +177,7 @@ public void createShouldThrowAnExceptionWhenContextIsNull() {
174177
// an exception is thrown
175178
}
176179

177-
@Test public void shouldReturnProperToStringValue() {
180+
@Test @Config(sdk = 19) public void shouldReturnProperToStringValue() {
178181
// given
179182
final String expectedToString = "Connectivity{"
180183
+ "state=DISCONNECTED, "
@@ -247,7 +250,8 @@ public void shouldAppendUnknownTypeWhileFilteringNetworkTypesInsidePredicateForE
247250
assertThat(outputTypes).isEqualTo(expectedOutputTypes);
248251
}
249252

250-
@Test public void shouldCreateConnectivityWithBuilder() {
253+
@Test @Config(sdk = 19)
254+
public void shouldCreateConnectivityWithBuilder() {
251255
// given
252256
NetworkInfo.State state = NetworkInfo.State.CONNECTED;
253257
NetworkInfo.DetailedState detailedState = NetworkInfo.DetailedState.CONNECTED;
@@ -321,7 +325,8 @@ public void shouldAppendUnknownTypeWhileFilteringNetworkTypesInsidePredicateForE
321325
assertThat(isAnotherConnectivityTheSame).isFalse();
322326
}
323327

324-
@Test public void shouldCreateDefaultConnectivityWhenConnectivityManagerIsNull() {
328+
@Test @Config(sdk = 19)
329+
public void shouldCreateDefaultConnectivityWhenConnectivityManagerIsNull() {
325330
// given
326331
final Context context = RuntimeEnvironment.getApplication().getApplicationContext();
327332
final ConnectivityManager connectivityManager = null;

0 commit comments

Comments
 (0)