Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle network change between wifi and mobile data?

Tags:

I am building a VoIP app.During a VoIP call when user switches between WiFi to mobile data i have a problem handling the scenario.

In my call screen activity I have registered for receiver which helps me get notified about the network change scenarios.

This is the code which I am using for detecting change in networks in the onRecieve Method. conn_name is private class level variable holding previous connection name.

ConnectivityManager connectivity_mgr = ((ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE)); NetworkInfo net_info = connectivity_mgr.getActiveNetworkInfo();  if (net_info != null && net_info.isConnectedOrConnecting() && !conn_name.equalsIgnoreCase("")) {     new_con = net_info.getExtraInfo();     if (new_con != null && !new_con.equalsIgnoreCase(conn_name))         network_changed = true;     conn_name = (new_con == null) ? "" : new_con;     connectionStatus ="connected"; } else {     if (net_info != null && conn_name.equalsIgnoreCase("")) {         conn_name = net_info.getExtraInfo();         connectionStatus ="connected";         network_changed = true;     } else if(!new_con.equals(conn_name)) {         conn_name = "";         connectionStatus ="disconnected";         network_changed = true;     } } 

So using above method I able detect network changes. But one peculiar thing happens when I am connected with WiFi. When my app starts initially it is connected with mobile data.when user enters into his known WiFi area,he gets connected to his known WiFi. Since WiFi is always chosen as default route,android switches to WiFi and I receive the network notification that WiFi has been turned on.

So I update my apps IP address to WiFi IP address, so no issues here. But still mobile data is still connected at the same time but getActiveNetworkInfo() tells me that I'm connected with WiFi clearly even if I was early connected to mobile data.

So the problem is when user switches off the WiFi button,and mobile data is still connected but I still receive the notification for WiFi turn off. It indicates me that network is disconnected even when my phone is still connected to mobile data.

But after a second I receive a notification that mobile data is connected. But once I receive the network disconnected, I have closed my VoIP call. So when I receive a notification for WiFi switched off how can I make sure whether mobile data is still connected.

I tried getActiveNetworkInfo() but it happens to be null when I receive notification for WiFi turned off.

I have followed this links:

Android API call to determine user setting "Data Enabled"
How to tell if 'Mobile Network Data' is enabled or disabled (even when connected by WiFi)?

Using the above link I am able detect that mobile data button has been enabled when user has connected with mobiledata.it gives me true. But the problem happens when this particular case happens.

Now when wifi is disabled I get notification but it shows that mobile data is disabled even when my mobile data is enabled. I am not able to handle this situation as I disconnect my calls when I receive my disconnected notification.

like image 665
Jeeva Avatar asked Jan 03 '18 15:01

Jeeva


People also ask

How do I stop switch between Wi-Fi and mobile data?

The same setting on Android phones can be found in the Connections area of the Settings app. Go to the WiFi settings, tap the three dots in the corner to find the advanced settings menu, and then turn off the toggle that says "Switch to mobile data."

How do I get my Wi-Fi and mobile data to work at the same time?

To do this, swipe down on your notification bar and check that the mobile data toggle is switched on. Or go into “Settings,” tap “Connections,” and “Data Usage” and make sure that mobile data is switched on. Step 2: Connect to a Wi-Fi network. Tap “Settings,” then “Connections”, then “Wi-Fi” and flip the switch on.

What happens when both Wi-Fi and mobile data is on?

Android actually does support simultaneous connection for both 3G and WiFi devices, through an amazing app called SuperSpeed. On LTE phones it will dramatically increase connect speeds.As others have said, when both WiFi and 3G are simultaneously connected, only WiFi will work.


1 Answers

You can utilize APIs of ConnectivityManager: particularly in your use case you are interested in registerDefaultNetworkCallback():

      public class TestActivity extends AppCompatActivity {          private ConnectivityManager manager;         private final ConnectivityManager.NetworkCallback networkCallback = new ConnectivityManager.NetworkCallback() {             @Override             public void onAvailable(Network network) {                 super.onAvailable(network);                 // this ternary operation is not quite true, because non-metered doesn't yet mean, that it's wifi                 // nevertheless, for simplicity let's assume that's true                 Log.i("vvv", "connected to " + (manager.isActiveNetworkMetered() ? "LTE" : "WIFI"));             }              @Override             public void onLost(Network network) {                 super.onLost(network);                 Log.i("vvv", "losing active connection");             }         };          @Override         protected void onCreate(@Nullable Bundle savedInstanceState) {             super.onCreate(savedInstanceState);              manager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);             manager.registerDefaultNetworkCallback(networkCallback);         }          @Override         protected void onDestroy() {             super.onDestroy();             manager.unregisterNetworkCallback(networkCallback);         }     }  

My device connects to LTE in about half second.

enter image description here

This means, that you cannot know beforehand, whether device will eventually connect to LTE or no at the time, when WIFI gets disconnected. Thus, you can adopt following approach: post an action on a handler to happen in a second and within this action cancel the call. If connection appears anytime soon - unschedule previously posted action. If you end up being in Runnable code, then connection wasn't established quickly, which means, that you should end the call.

      public class TestActivity extends AppCompatActivity {          private ConnectivityManager manager;          private final Handler handler = new Handler();         private final ConnectivityManager.NetworkCallback networkCallback = new ConnectivityManager.NetworkCallback() {             @Override             public void onAvailable(Network network) {                 super.onAvailable(network);                 Log.i("vvv", "connected to " + (manager.isActiveNetworkMetered() ? "LTE" : "WIFI"));                  // we've got a connection, remove callbacks (if we have posted any)                 handler.removeCallbacks(endCall);             }              @Override             public void onLost(Network network) {                 super.onLost(network);                 Log.i("vvv", "losing active connection");                  // Schedule an event to take place in a second                 handler.postDelayed(endCall, 1000);             }         };          private final Runnable endCall = new Runnable() {             @Override             public void run() {                 // if execution has reached here - feel free to cancel the call                 // because no connection was established in a second             }         };          @Override         protected void onCreate(@Nullable Bundle savedInstanceState) {             super.onCreate(savedInstanceState);              manager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);             manager.registerDefaultNetworkCallback(networkCallback);         }          @Override         protected void onDestroy() {             super.onDestroy();             manager.unregisterNetworkCallback(networkCallback);             handler.removeCallbacks(endCall);         }     }  

The downside of the approach is, that registerDefaultNetworkCallback() is available starting from API 24. There does not exist an alternative in ConnectivityManagerCompat either. Instead, you can use registerNetworkCallback() which is available from API 21.

like image 97
azizbekian Avatar answered Oct 12 '22 09:10

azizbekian