Skip to content

Instantly share code, notes, and snippets.

@yangweigbh
Last active January 18, 2021 10:35
Show Gist options
  • Save yangweigbh/e89bb4336f6ccb6e59ef05f28f03405f to your computer and use it in GitHub Desktop.
Save yangweigbh/e89bb4336f6ccb6e59ef05f28f03405f to your computer and use it in GitHub Desktop.
Class to listen to network change
public interface NetworkEventProvider {
void setListener(Listener listener);
interface Listener {
/**
* @param networkStatus {@link com.birbit.android.jobqueue.network.NetworkUtil.NetworkStatus}
*/
void onNetworkChange(@NetworkUtil.NetworkStatus int networkStatus);
}
}
public interface NetworkUtil {
/**
* Order of these constant values matter as they are relied upon to be incrementing in terms
* of availability.
*/
@Retention(RetentionPolicy.SOURCE)
@IntDef({DISCONNECTED, METERED, UNMETERED})
@interface NetworkStatus {}
int DISCONNECTED = 0;
int METERED = 1;
int UNMETERED = 2;
/**
* Returns the current connection status. If you cannot detect granular network type, return
* {@link #UNMETERED} if there is an internet connection or {@link #DISCONNECTED} if there is no
* connection.
*
* @param context The application context
*
* @return The current connection status. It should be one of {@link #DISCONNECTED},
* {@link #METERED} or {@link #UNMETERED}.
*/
@NetworkStatus
int getNetworkStatus(Context context);
}
public class NetworkUtilImpl implements NetworkUtil, NetworkEventProvider {
private Listener listener;
public NetworkUtilImpl(Context context) {
context = context.getApplicationContext();
if (VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (VERSION.SDK_INT >= Build.VERSION_CODES.M) {
listenForIdle(context);
}
listenNetworkViaConnectivityManager(context);
} else {
context.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
dispatchNetworkChange(context);
}
}, getNetworkIntentFilter());
}
}
@TargetApi(23)
private void listenNetworkViaConnectivityManager(final Context context) {
ConnectivityManager cm = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkRequest request = new NetworkRequest.Builder()
.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
.addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
.build();
cm.registerNetworkCallback(request, new ConnectivityManager.NetworkCallback() {
@Override
public void onAvailable(Network network) {
dispatchNetworkChange(context);
}
});
}
@TargetApi(23)
private void listenForIdle(Context context) {
context.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
dispatchNetworkChange(context);
}
}, new IntentFilter(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED));
}
void dispatchNetworkChange(Context context) {
if(listener == null) {//shall not be but just be safe
return;
}
//http://developer.android.com/reference/android/net/ConnectivityManager.html#EXTRA_NETWORK_INFO
//Since NetworkInfo can vary based on UID, applications should always obtain network information
// through getActiveNetworkInfo() or getAllNetworkInfo().
listener.onNetworkChange(getNetworkStatus(context));
}
@Override
public int getNetworkStatus(Context context) {
if (isDozing(context)) {
return NetworkUtil.DISCONNECTED;
}
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = cm.getActiveNetworkInfo();
if (netInfo == null) {
return NetworkUtil.DISCONNECTED;
}
if (netInfo.getType() == ConnectivityManager.TYPE_WIFI ||
netInfo.getType() == ConnectivityManager.TYPE_ETHERNET) {
return NetworkUtil.UNMETERED;
}
return NetworkUtil.METERED;
}
@TargetApi(23)
private static IntentFilter getNetworkIntentFilter() {
IntentFilter networkIntentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
if (VERSION.SDK_INT >= 23) {
networkIntentFilter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
}
return networkIntentFilter;
}
/**
* Returns true if the device is in Doze/Idle mode. Should be called before checking the network connection because
* the ConnectionManager may report the device is connected when it isn't during Idle mode.
*/
@TargetApi(23)
private static boolean isDozing(Context context) {
if (VERSION.SDK_INT >= 23) {
PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
return powerManager.isDeviceIdleMode() &&
!powerManager.isIgnoringBatteryOptimizations(context.getPackageName());
} else {
return false;
}
}
@Override
public void setListener(Listener listener) {
this.listener = listener;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment