Skip to content

Commit

Permalink
Merge pull request #90 from Kisty/add_check_internet_connectivity_imm…
Browse files Browse the repository at this point in the history
…ediately

Add check internet connectivity immediately
  • Loading branch information
Piotr Wittchen committed Oct 15, 2016
2 parents 9fb03cc + b22b44e commit 154cac0
Show file tree
Hide file tree
Showing 5 changed files with 193 additions and 24 deletions.
24 changes: 16 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,12 @@ Usage
Library has the following RxJava Observables available in the public API:

```java
Observable<Connectivity> observeNetworkConnectivity(final Context context)
Observable<Connectivity> observeNetworkConnectivity(final Context context, final NetworkObservingStrategy strategy)
Observable<Connectivity> observeNetworkConnectivity(Context context)
Observable<Connectivity> observeNetworkConnectivity(Context context, NetworkObservingStrategy strategy)
Observable<Boolean> observeInternetConnectivity()
Observable<Boolean> observeInternetConnectivity(final int interval, final String host, final int port, final int timeout)
Observable<Boolean> observeInternetConnectivityImmediately()
Observable<Boolean> observeInternetConnectivity(int intervalInMs, String host, int port, int timeout)
Observable<Boolean> observeInternetConnectivity(int initialIntervalInMs, int intervalInMs, String host, int port, int timeout)
```

**Please note**: Due to memory leak in `WifiManager` reported
Expand All @@ -70,7 +72,7 @@ ReactiveNetwork.observeNetworkConnectivity(context)

When `Connectivity` changes, subscriber will be notified. `Connectivity` can change its state or type.

We can react on a concrete state, states, type or types changes with the `filter(...)` method from RxJava, `hasState(final NetworkInfo.State... states)` and `hasType(final int... types)` methods located in `Connectivity` class.
We can react on a concrete state, states, type or types changes with the `filter(...)` method from RxJava, `hasState(NetworkInfo.State... states)` and `hasType(int... types)` methods located in `Connectivity` class.

```java
ReactiveNetwork.observeNetworkConnectivity(context)
Expand All @@ -91,7 +93,7 @@ ReactiveNetwork.observeNetworkConnectivity(context)
You can also use method:

```java
Observable<Connectivity> observeNetworkConnectivity(final Context context, final NetworkObservingStrategy strategy)
Observable<Connectivity> observeNetworkConnectivity(Context context, NetworkObservingStrategy strategy)
```

This method allows you to apply your own network observing strategy and is used by the library under the hood to determine appropriate strategy depending on the version of Android system.
Expand All @@ -114,8 +116,8 @@ boolean isDefault()
String toString()

// helper methods for filter(...) method from RxJava
Func1<Connectivity, Boolean> hasState(final NetworkInfo.State... states)
Func1<Connectivity, Boolean> hasType(final int... types)
Func1<Connectivity, Boolean> hasState(NetworkInfo.State... states)
Func1<Connectivity, Boolean> hasType(int... types)
```

### Observing Internet connectivity
Expand All @@ -137,10 +139,16 @@ An `Observable` will return `true` to the subscription if device is connected to

**Please note**: This method is less efficient than `observeNetworkConnectivity(context)` method, because it opens socket connection with remote host (default is www.google.com) every two seconds with two seconds of timeout and consumes data transfer. Use this method if you really need it. Optionally, you can unsubscribe subcription right after you get notification that Internet is available and do the work you want in order to decrease network calls.

If you want to check Internet connectivity _as soon as possible_, you can use the following method:

```java
Observable<Boolean> observeInternetConnectivityImmediately()
```

If you want to specify your own custom details for checking Internet connectivity, you can use the following method:

```java
Observable<Boolean> observeInternetConnectivity(final int interval, final String host, final int port, final int timeout)
Observable<Boolean> observeInternetConnectivity(int interval, String host, int port, int timeout)
```

It allows you to specify custom interval of checking connectivity in milliseconds, host, port and connection timeout in milliseconds.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,11 @@
import android.support.test.runner.AndroidJUnit4;
import com.github.pwittchen.reactivenetwork.library.network.observing.NetworkObservingStrategy;
import com.github.pwittchen.reactivenetwork.library.network.observing.strategy.LollipopNetworkObservingStrategy;

import org.junit.Test;
import org.junit.runner.RunWith;

import rx.Observable;
import rx.functions.Action1;

import static com.google.common.truth.Truth.assertThat;
Expand All @@ -32,6 +35,7 @@
private static final int TEST_VALID_PORT = 80;
private static final int TEST_VALID_TIMEOUT = 1000;
private static final int TEST_VALID_INTERVAL = 1000;
public static final int TEST_VALID_INITIAL_INTERVAL = 1000;

@Test public void testReactiveNetworkObjectShouldNotBeNull() {
// given
Expand All @@ -44,6 +48,90 @@
assertThat(reactiveNetwork).isNotNull();
}

@Test
public void observeNetworkConnectivityShouldNotBeNull() {
// given
Context context = InstrumentationRegistry.getTargetContext();

// when
Observable<Connectivity> observable;
observable = ReactiveNetwork.observeNetworkConnectivity(context);

// then
assertThat(observable).isNotNull();
}

@Test
public void observeNetworkConnectivityWithStrategyShouldNotBeNull() {
// given
Context context = InstrumentationRegistry.getTargetContext();
NetworkObservingStrategy strategy = new LollipopNetworkObservingStrategy();

// when
Observable<Connectivity> observable;
observable = ReactiveNetwork.observeNetworkConnectivity(context, strategy);

// then
assertThat(observable).isNotNull();
}

@Test
public void observeInternetConnectivityDefaultShouldNotBeNull() {
// given
Observable<Boolean> observable;

// when
observable = ReactiveNetwork.observeInternetConnectivity();

// then
assertThat(observable).isNotNull();
}

@Test
public void observeInternetConnectivityImmediatelyShouldNotBeNull() {
// given
Observable<Boolean> observable;

// when
observable = ReactiveNetwork.observeInternetConnectivityImmediately();

// then
assertThat(observable).isNotNull();
}

@Test
public void observeInternetConnectivityWithConfigurationShouldNotBeNull() {
// given
Observable<Boolean> observable;
int interval = TEST_VALID_INTERVAL;
String host = TEST_VALID_HOST;
int port = TEST_VALID_PORT;
int timeout = TEST_VALID_TIMEOUT;

// when
observable = ReactiveNetwork.observeInternetConnectivity(interval, host, port, timeout);

// then
assertThat(observable).isNotNull();
}

@Test
public void observeInternetConnectivityWithFullConfigurationShouldNotBeNull() {
// given
Observable<Boolean> observable;
int initialInterval = TEST_VALID_INITIAL_INTERVAL;
int interval = TEST_VALID_INTERVAL;
String host = TEST_VALID_HOST;
int port = TEST_VALID_PORT;
int timeout = TEST_VALID_TIMEOUT;

// when
observable = ReactiveNetwork.observeInternetConnectivity(initialInterval, interval, host, port, timeout);

// then
assertThat(observable).isNotNull();
}

@Test public void observeNetworkConnectivityShouldBeDefaultIfEmpty() {
ReactiveNetwork.observeNetworkConnectivity(InstrumentationRegistry.getContext())
.subscribe(new Action1<Connectivity>() {
Expand Down Expand Up @@ -198,4 +286,37 @@ public void observeInternetConnectivityShouldThrowAnExceptionForZeroTimeout() {
// then
// an exception is thrown
}

@Test
public void observeInternetConnectivityShouldNotThrowAnExceptionForZeroInitialInterval() {
// given
Observable<Boolean> observable;
int initialInterval = 0;
int interval = TEST_VALID_INTERVAL;
String host = TEST_VALID_HOST;
int port = TEST_VALID_PORT;
int timeout = TEST_VALID_TIMEOUT;

// when
observable = ReactiveNetwork.observeInternetConnectivity(initialInterval, interval, host, port, timeout);

// then
assertThat(observable).isNotNull();
}

@Test(expected = IllegalArgumentException.class)
public void observeInternetConnectivityShouldThrowAnExceptionForNegativeInitialInterval() {
// given
int initialInterval = -1;
int interval = TEST_VALID_INTERVAL;
String host = TEST_VALID_HOST;
int port = TEST_VALID_PORT;
int timeout = TEST_VALID_TIMEOUT;

// when
ReactiveNetwork.observeInternetConnectivity(initialInterval, interval, host, port, timeout);

// then
// an exception is thrown
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ public static Func1<Connectivity, Boolean> hasType(final int... types) {
* @return boolean true if connectivity is default and false if not
*/
public boolean isDefault() {
return getState() == DEFAULT_STATE && getType() == DEFAULT_TYPE && getName() == DEFAULT_NAME;
return getState() == DEFAULT_STATE && getType() == DEFAULT_TYPE && getName().equals(DEFAULT_NAME);
}

@Override public String toString() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public class ReactiveNetwork {
private static final String DEFAULT_PING_HOST = "www.google.com";
private static final int DEFAULT_PING_PORT = 80;
private static final int DEFAULT_PING_INTERVAL_IN_MS = 2000;
private static final int DEFAULT_INITIAL_PING_INTERVAL_IN_MS = DEFAULT_PING_INTERVAL_IN_MS;
private static final int DEFAULT_PING_TIMEOUT_IN_MS = 2000;

protected ReactiveNetwork() {
Expand Down Expand Up @@ -101,10 +102,25 @@ public static Observable<Connectivity> observeNetworkConnectivity(final Context
* and false if not
*/
public static Observable<Boolean> observeInternetConnectivity() {
return observeInternetConnectivity(DEFAULT_PING_INTERVAL_IN_MS, DEFAULT_PING_HOST,
return observeInternetConnectivity(DEFAULT_INITIAL_PING_INTERVAL_IN_MS, DEFAULT_PING_INTERVAL_IN_MS, DEFAULT_PING_HOST,
DEFAULT_PING_PORT, DEFAULT_PING_TIMEOUT_IN_MS);
}

/**
* Observes connectivity with the Internet <i>immediately</i> with default settings. It pings remote host
* (www.google.com) at port 80 every 2 seconds with 2 seconds of timeout. This operation is used
* for determining if device is connected to the Internet or not. Please note that this method is
* less efficient than {@link #observeNetworkConnectivity(Context)} method and consumes data
* transfer, but it gives you actual information if device is connected to the Internet or not.
*
* @return RxJava Observable with Boolean - true, when we have an access to the Internet
* and false if not
*/
public static Observable<Boolean> observeInternetConnectivityImmediately() {
return observeInternetConnectivity(0, DEFAULT_PING_INTERVAL_IN_MS, DEFAULT_PING_HOST,
DEFAULT_PING_PORT, DEFAULT_PING_TIMEOUT_IN_MS);
}

/**
* Observes connectivity with the Internet by opening socket connection with remote host
*
Expand All @@ -117,23 +133,42 @@ public static Observable<Boolean> observeInternetConnectivity() {
*/
public static Observable<Boolean> observeInternetConnectivity(final int intervalInMs,
final String host, final int port, final int timeoutInMs) {
return observeInternetConnectivity(intervalInMs, intervalInMs, host, port, timeoutInMs);
}

/**
* Observes connectivity with the Internet by opening socket connection with remote host
*
* @param initialIntervalInMs in milliseconds determining the delay of the first connectivity check
* @param intervalInMs in milliseconds determining how often we want to check connectivity
* @param host for checking Internet connectivity
* @param port for checking Internet connectivity
* @param timeoutInMs for pinging remote host in milliseconds
* @return RxJava Observable with Boolean - true, when we have connection with host and false if
* not
*/
public static Observable<Boolean> observeInternetConnectivity(final int initialIntervalInMs, final int intervalInMs,
final String host, final int port, final int timeoutInMs) {
if (initialIntervalInMs < 0) {
throw new IllegalArgumentException("initialIntervalInMs is not a positive number nor a positive number");
}
Preconditions.checkPositive(intervalInMs, "intervalInMs is not positive number");
Preconditions.checkNotNullOrEmpty(host, "host is null or empty");
Preconditions.checkPositive(port, "port is not positive number");
Preconditions.checkPositive(timeoutInMs, "timeoutInMs is not positive number");

return Observable.interval(intervalInMs, TimeUnit.MILLISECONDS, Schedulers.io())
.map(new Func1<Long, Boolean>() {
@Override public Boolean call(Long tick) {
try {
Socket socket = new Socket();
socket.connect(new InetSocketAddress(host, port), timeoutInMs);
return socket.isConnected();
} catch (IOException e) {
return Boolean.FALSE;
}
}
})
.distinctUntilChanged();
return Observable.interval(initialIntervalInMs, intervalInMs, TimeUnit.MILLISECONDS, Schedulers.io())
.map(new Func1<Long, Boolean>() {
@Override public Boolean call(Long tick) {
try {
Socket socket = new Socket();
socket.connect(new InetSocketAddress(host, port), timeoutInMs);
return socket.isConnected();
} catch (IOException e) {
return Boolean.FALSE;
}
}
})
.distinctUntilChanged();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,12 @@ public class PreLollipopNetworkObservingStrategy implements NetworkObservingStra

subscriber.add(unsubscribeInUiThread(new Action0() {
@Override public void call() {
context.unregisterReceiver(receiver);
//Catch case where the receiver is already unregistered
try {
context.unregisterReceiver(receiver);
} catch (Exception e) {
// ignore exception
}
}
}));
}
Expand Down

0 comments on commit 154cac0

Please sign in to comment.