-
-
Save PasanBhanu/730a32a9eeb180ec2950c172d54bb06a to your computer and use it in GitHub Desktop.
/* | |
You need to call the below method once. It register the callback and fire it when there is a change in network state. | |
Here I used a Global Static Variable, So I can use it to access the network state in anyware of the application. | |
*/ | |
// You need to pass the context when creating the class | |
public CheckNetwork(Context context) { | |
this.context = context; | |
} | |
// Network Check | |
public void registerNetworkCallback() | |
{ | |
try { | |
ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); | |
NetworkRequest.Builder builder = new NetworkRequest.Builder(); | |
connectivityManager.registerDefaultNetworkCallback(new ConnectivityManager.NetworkCallback(){ | |
@Override | |
public void onAvailable(Network network) { | |
Variables.isNetworkConnected = true; // Global Static Variable | |
} | |
@Override | |
public void onLost(Network network) { | |
Variables.isNetworkConnected = false; // Global Static Variable | |
} | |
} | |
); | |
Variables.isNetworkConnected = false; | |
}catch (Exception e){ | |
Variables.isNetworkConnected = false; | |
} | |
} |
public class Variables { | |
// Global variable used to store network state | |
public static boolean isNetworkConnected = false; | |
} |
public class MainActivity extends AppCompatActivity { | |
@Override | |
protected void onCreate(Bundle savedInstanceState) { | |
super.onCreate(savedInstanceState); | |
setContentView(R.layout.activity_main); | |
// Register Callback - Call this in your app start! | |
CheckNetwork network = new CheckNetwork(getApplicationContext()); | |
network.registerNetworkCallback(); | |
// Check network connection | |
if (Variables.isNetworkConnected){ | |
// Internet Connected | |
}else{ | |
// Not Connected | |
} | |
} | |
} |
In my guess, just change isNetworkConnected to an Int,
onAvailable -> +1
onLost -> -1
This is a really bad strategy, These registers are triggered multiple times throughout app cycle. How will you determine the state, if there it was available 2 times but lost on third time, $available
would be 1. And nonetheless, _if conditions_
needs a boolean. It will be either available or not available. Why waste cpu cycles comparing numeric equations to determine if condition is true or false, when you can just pass boolean directly. Android OS Apis provided those registers for a reason.
If you are wondering about the double calling during wifi->cellular switching, In real world scenario, there would be several edge cases handled when implementing it, so it should be covered. If I remember correctly, When network was switched, onLost was called by wifi, then onAvailable was triggered by cellular when it connected.
I have no prove but if the onAvailable and onLost is called properly it should work.
Without proof, nothing can be assured. Looking on your code, It won't work because you are assuming onAvailable and onLost to be called linearly which is never the case. I can't see any reason why you logged $network, and you haven't demonstrated how are you using available
in your app. CheckNetwork object is just updating the value of available
variable but how are you actually going to use it to determine state of your network. Publish your code on a separate gist and tag me there, I would be happy to take a look there. Lets keep this gist free.
Also, don't name your functions same as system functions, I got confused seeing at registerDefaultNetworkCallback
being called inside your registerNetworkCallback
function.
In my guess, just change isNetworkConnected to an Int,
onAvailable -> +1
onLost -> -1This is a really bad strategy, These registers are triggered multiple times throughout app cycle. How will you determine the state, if there it was available 2 times but lost on third time,
$available
would be 1. And nonetheless,_if conditions_
needs a boolean. It will be either available or not available. Why waste cpu cycles comparing numeric equations to determine if condition is true or false, when you can just pass boolean directly. Android OS Apis provided those registers for a reason.If you are wondering about the double calling during wifi->cellular switching, In real world scenario, there would be several edge cases handled when implementing it, so it should be covered. If I remember correctly, When network was switched, onLost was called by wifi, then onAvailable was triggered by cellular when it connected.
I have no prove but if the onAvailable and onLost is called properly it should work.
Without proof, nothing can be assured. Looking on your code, It won't work because you are assuming onAvailable and onLost to be called linearly which is never the case. I can't see any reason why you logged $network, and you haven't demonstrated how are you using
available
in your app. CheckNetwork object is just updating the value ofavailable
variable but how are you actually going to use it to determine state of your network. Publish your code on a separate gist and tag me there, I would be happy to take a look there. Lets keep this gist free.Also, don't name your functions same as system functions, I got confused seeing at
registerDefaultNetworkCallback
being called inside yourregisterNetworkCallback
function.
Naming is because I just modify the code from this thread.
For how to use the value, that is simple, when the value > 0 there has somehow a network connection exist.
As I know its a bitwise compare and I don't think there has a measurable performance different for true false.
The order of calling available and lost does not matter.
And I said this depend on they engineer the callback correctly (for example, when device switch on once only one onAvailable will call instead on dup calling, that is the part I cannot 100% prove).
Also, I notice a problem for the base design of the program from this thread.
Register the callback on onCreate may cause it add more then one times.
The callback work well at background but if the program get kill at background to free memory,
when it become active it will run onCreate again. I wonder that is the problem someone encountered.
So a better practice is
register at onStart, unregister at onStop
I found nothing wrong after I make this modification.
Register the callback on onCreate may cause it add more then one times.
Tha'ts not whats happening in actual, Registration is done only done once, than a global static is set. As for the update of value, It is done by android system once registered ( something similar to pub-sub way, can't explain fully here ). So there is essentially no overhead. If you accidentally try to register it again, no effect takes place.
On other hand, the old way to initiate NetworkInfo, and then find out if network is available, That was something that was being done everytime check was asked for. Since Android 10, Google is Promoting pub-sub/callback/relay style of apis instead of old functional apis because of performance reason. Anything that needs to be queried from system should be subscribed for, thats the direction they seems to going for.
Hi
My own version for checking if the user already doesn't have a connection, also handle the connection change status
https://gist.github.com/ayoubrem/81689ca066f77ecd1ebb5e14de245e6d
hi bro, your link is page not found, Do you share again? Thank you
@SuppressLint("NewApi")
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void doWork() {
ConnectivityManager cm=(ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);
cm.registerDefaultNetworkCallback(new ConnectivityManager.NetworkCallback(){
public void onAvailable(Network network) {
Log.e("hola", "The default network is now: " + network);
network=cm.getActiveNetwork();
if(network!=null){
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(MainActivity.this);
String minMagnitude = sharedPrefs.getString(
getString(R.string.settings_min_magnitude_key),
getString(R.string.settings_min_magnitude_default));
String orderBy = sharedPrefs.getString(
getString(R.string.settings_order_by_key),
getString(R.string.settings_order_by_default)
);
if (orderBy.equals(getString(R.string.settings_order_by_default))){
extractdata(minMagnitude, "magnitude-asc");
}else{
extractdata(minMagnitude,orderBy);
}
}
}
public void onCapabilitiesChanged(@NonNull Network network, @NonNull NetworkCapabilities networkCapabilities) {
super.onCapabilitiesChanged(network, networkCapabilities);
Log.i(TAG,network+" "+networkCapabilities.toString()+" "+networkCapabilities.hasCapability(NET_CAPABILITY_INTERNET));
runOnUiThread(new Runnable() {
@Override
public void run() {
View loadingIndicator = findViewById(R.id.progressBar);
loadingIndicator.setVisibility(View.VISIBLE);
rvCourses=findViewById(R.id.rvCourses);
mEmptyTextview=findViewById(R.id.empty_view);
mEmptyTextview.setVisibility(View.GONE);
rvCourses.setVisibility(View.VISIBLE);
}
});
if(networkCapabilities.hasCapability(NET_CAPABILITY_INTERNET)){
SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(MainActivity.this);
String minMagnitude = sharedPrefs.getString(
getString(R.string.settings_min_magnitude_key),
getString(R.string.settings_min_magnitude_default));
String orderBy = sharedPrefs.getString(
getString(R.string.settings_order_by_key),
getString(R.string.settings_order_by_default)
);
if (orderBy.equals(getString(R.string.settings_order_by_default))){
extractdata(minMagnitude, "magnitude-asc");
}else{
extractdata(minMagnitude,orderBy);
}
}
}
public void onLost(Network network) {
/*View loadingIndicator = findViewById(R.id.progressBar);
loadingIndicator.setVisibility(View.GONE);
Log.e(TAG, "The application no longer has a default network. The last default network was " + network);
rvCourses=findViewById(R.id.rvCourses);
mEmptyTextview=findViewById(R.id.empty_view);
mEmptyTextview.setText("NO INTERNET CONNECTION");
rvCourses.setVisibility(View.GONE);
mEmptyTextview.setVisibility(View.VISIBLE);*/
runOnUiThread(new Runnable() {
@Override
public void run() {
View loadingIndicator = findViewById(R.id.progressBar);
loadingIndicator.setVisibility(View.GONE);
Log.e(TAG, "The application no longer has a default network. The last default network was " + network);
rvCourses=findViewById(R.id.rvCourses);
mEmptyTextview=findViewById(R.id.empty_view);
mEmptyTextview.setText("NO INTERNET CONNECTION");
rvCourses.setVisibility(View.GONE);
mEmptyTextview.setVisibility(View.VISIBLE);
}
});
}
}
);
}
Hope this helps ;P
@PasanBhanu
please explain why you are using
NetworkRequest.Builder builder = new NetworkRequest.Builder();
@PasanBhanu please explain why you are using
NetworkRequest.Builder builder = new NetworkRequest.Builder();
Reminiscent of older code, Before we found about registerDefault from google team, older version of code was basically build a network request object, add the wifi module and/or bluetooth module (basically any and all network interface you want to observe) and then use that object to registerNetworkCallback
When you use registerDefaultNetworkCallback, it basically connects to the lower level network pool with default options, so you don't need to (but you still can if you want) build your own network object.
I just try it and seems it work
2021-03-26 18:14:52.901 2434-2816/com.example.tmdb D/CheckNetwork: A 140
2021-03-26 18:18:14.533 2434-2816/com.example.tmdb D/CheckNetwork: L 140
2021-03-26 18:18:21.915 2434-2816/com.example.tmdb D/CheckNetwork: A 141
2021-03-26 18:18:25.513 2434-2816/com.example.tmdb D/CheckNetwork: L 141
2021-03-26 18:18:30.613 2434-2816/com.example.tmdb D/CheckNetwork: A 142