如何处理wifi和移动数据之间的网络变化? [英] How to handle network change between wifi and mobile data?

查看:164
本文介绍了如何处理wifi和移动数据之间的网络变化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在构建VoIP应用程序.在VoIP通话期间,当用户在WiFi到移动数据之间切换时,我无法处理这种情况.

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.

这是我用于在onRecieve方法中检测网络变化的代码. conn_name是包含先前连接名称的私有类级别变量.

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;
    }
}

因此,使用上述方法,我可以检测到网络更改.但是,当我连接WiFi时,会发生一件奇怪的事情.当我的应用最初启动时,它已与移动数据连接.当用户进入其已知的WiFi区域时,他便已连接至其已知的WiFi.由于始终选择将WiFi作为默认路由,因此Android会切换到WiFi,并且我会收到网络通知,通知您WiFi已打开.

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.

所以我将我的应用程序IP地址更新为WiFi IP地址,所以这里没有问题.但是,仍然仍然同时连接了移动数据,但是 getActiveNetworkInfo()告诉我,即使我很早就连接到了移动数据,也可以清楚地连接到WiFi.

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.

问题是当用户关闭WiFi按钮并且移动数据仍处于连接状态,但我仍然收到WiFi关闭的通知时. 它表明我即使手机仍连接到移动数据网络也已断开连接.

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.

但是一秒钟后,我收到一条有关移动数据已连接的通知. 但是,一旦收到断开的网络,我就关闭了VoIP呼叫. 因此,当我收到关闭WiFi的通知时,如何确定移动数据是否仍处于连接状态.

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.

我尝试了getActiveNetworkInfo(),但是当我收到WiFi通知已关闭时,它恰好为空.

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

我关注了以下链接:

通过Android API调用来确定用户设置已启用数据"
如何判断移动网络数据"是启用还是禁用(即使通过WiFi连接)?

使用上面的链接,当用户与mobiledata连接时,我能够检测到已启用了mobile data按钮.这使我成真. 但是,当这种特殊情况发生时,问题就发生了.

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.

现在禁用wifi时,我会收到通知,但它显示即使启用了我的移动数据,也禁用了移动数据.收到断开连接的通知后,我断开了呼叫,因此我无法处理这种情况.

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.

推荐答案

您可以使用

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);
        }
    }

我的设备在大约半秒钟内连接到LTE.

My device connects to LTE in about half second.

这意味着,当WIFI断开连接时,您可能无法事先知道设备最终是否会连接到LTE.因此,您可以采用以下方法:在处理程序上发布操作以在一秒钟内发生,然后在该操作内取消调用.如果很快就会出现连接-取消安排先前发布的操作.如果最终使用Runnable代码,则表明连接建立不迅速,这意味着您应该结束呼叫.

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);
        }
    }

该方法的缺点是 registerDefaultNetworkCallback() . registerNetworkCallback() ,可从API 21获得.

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.

这篇关于如何处理wifi和移动数据之间的网络变化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆