Skip to content

Commit 92fbcb8

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 92fbcb8

File tree

9 files changed

+137
-182
lines changed

9 files changed

+137
-182
lines changed

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

Lines changed: 35 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -17,35 +17,33 @@
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;
2625

2726
import com.github.pwittchen.reactivenetwork.library.rx2.info.NetworkState;
27+
import com.jakewharton.nopen.annotation.Open;
2828

2929
/**
3030
* Connectivity class represents current connectivity status. It wraps NetworkInfo object.
3131
*/
32-
@RequiresApi(api = Build.VERSION_CODES.CUPCAKE)
3332
public final class Connectivity {
3433
static final int UNKNOWN_TYPE = -1;
3534
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;
35+
@Nullable private NetworkInfo.State state; // NOPMD
36+
@Nullable private NetworkInfo.DetailedState detailedState; // NOPMD
37+
@Nullable @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) private NetworkState networkState;
38+
private final int type; // NOPMD
39+
private final int subType; // NOPMD
40+
private final boolean available; // NOPMD
41+
private final boolean failover; // NOPMD
42+
private final boolean roaming; // NOPMD
43+
private final String typeName; // NOPMD
44+
private final String subTypeName; // NOPMD
45+
private final String reason; // NOPMD
46+
private final String extraInfo; // NOPMD
4947

5048
public static Connectivity create() {
5149
return builder().build();
@@ -79,7 +77,8 @@ protected static Connectivity create(@NonNull Context context, ConnectivityManag
7977
}
8078

8179
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
82-
protected static Connectivity create(@NonNull Context context, ConnectivityManager manager, NetworkState networkState) {
80+
protected static Connectivity create(@NonNull Context context, ConnectivityManager manager,
81+
NetworkState networkState) {
8382
Preconditions.checkNotNull(context, "context == null");
8483

8584
if (manager == null) {
@@ -114,11 +113,17 @@ private static Connectivity create(NetworkState networkState) {
114113
}
115114

116115
private Connectivity(Builder builder) {
117-
if(Preconditions.isAtLeastAndroidLollipop()) {
118-
networkState = builder.networkState;
116+
if (Preconditions.isAtLeastAndroidLollipop()) {
117+
if (builder.networkState != null) {
118+
networkState = builder.networkState;
119+
}
119120
} else {
120-
state = builder.state;
121-
detailedState = builder.detailedState;
121+
if (builder.state != null) {
122+
state = builder.state;
123+
}
124+
if (builder.detailedState != null) {
125+
detailedState = builder.detailedState;
126+
}
122127
}
123128
type = builder.type;
124129
subType = builder.subType;
@@ -139,22 +144,28 @@ private static Builder builder() {
139144
return new Connectivity.Builder();
140145
}
141146

142-
public NetworkInfo.State state() {
147+
public @Nullable NetworkInfo.State state() {
143148
return state;
144149
}
145150

146151
public static Builder state(NetworkInfo.State state) {
147152
return builder().state(state);
148153
}
149154

150-
public NetworkInfo.DetailedState detailedState() {
155+
public @Nullable NetworkInfo.DetailedState detailedState() {
151156
return detailedState;
152157
}
153158

154159
public static Builder state(NetworkInfo.DetailedState detailedState) {
155160
return builder().detailedState(detailedState);
156161
}
157162

163+
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
164+
@Nullable
165+
public NetworkState getNetworkState() {
166+
return networkState;
167+
}
168+
158169
public int type() {
159170
return type;
160171
}
@@ -227,11 +238,6 @@ public static Builder extraInfo(String extraInfo) {
227238
return builder().extraInfo(extraInfo);
228239
}
229240

230-
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
231-
public NetworkState getNetworkState() {
232-
return networkState;
233-
}
234-
235241
@Override public boolean equals(Object o) {
236242
if (this == o) {
237243
return true;
@@ -277,7 +283,7 @@ public NetworkState getNetworkState() {
277283
}
278284

279285
@Override public int hashCode() {
280-
int result = state.hashCode();
286+
int result = state != null ? state.hashCode() : 0;
281287
result = 31 * result + (detailedState != null ? detailedState.hashCode() : 0);
282288
result = 31 * result + type;
283289
result = 31 * result + subType;

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

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@
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 {
1111
private boolean isConnected = false;
12-
private Network network = null;
13-
private NetworkCapabilities networkCapabilities = null;
14-
private LinkProperties linkProperties = null;
12+
@Nullable private Network network = null;
13+
@Nullable private NetworkCapabilities networkCapabilities = null;
14+
@Nullable private LinkProperties linkProperties = null;
1515

1616
public boolean isConnected() {
1717
return isConnected;
@@ -21,27 +21,27 @@ public void setConnected(boolean connected) {
2121
isConnected = connected;
2222
}
2323

24-
public Network getNetwork() {
24+
@Nullable public Network getNetwork() {
2525
return network;
2626
}
2727

28-
public void setNetwork(Network network) {
28+
public void setNetwork(@Nullable Network network) {
2929
this.network = network;
3030
}
3131

32-
public NetworkCapabilities getNetworkCapabilities() {
32+
@Nullable public NetworkCapabilities getNetworkCapabilities() {
3333
return networkCapabilities;
3434
}
3535

36-
public void setNetworkCapabilities(NetworkCapabilities networkCapabilities) {
36+
public void setNetworkCapabilities(@Nullable NetworkCapabilities networkCapabilities) {
3737
this.networkCapabilities = networkCapabilities;
3838
}
3939

40-
public LinkProperties getLinkProperties() {
40+
@Nullable public LinkProperties getLinkProperties() {
4141
return linkProperties;
4242
}
4343

44-
public void setLinkProperties(LinkProperties linkProperties) {
44+
public void setLinkProperties(@Nullable LinkProperties linkProperties) {
4545
this.linkProperties = linkProperties;
4646
}
4747
}

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

Lines changed: 39 additions & 14 deletions
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

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,13 @@
1818
import android.content.Context;
1919
import android.net.ConnectivityManager;
2020
import android.net.NetworkInfo;
21+
import android.os.Build;
2122
import io.reactivex.functions.Predicate;
2223
import org.junit.Test;
2324
import org.junit.runner.RunWith;
2425
import org.robolectric.RobolectricTestRunner;
2526
import org.robolectric.RuntimeEnvironment;
27+
import org.robolectric.annotation.Config;
2628

2729
import static com.google.common.truth.Truth.assertThat;
2830

@@ -32,7 +34,7 @@
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)