Android 5.0 以上监听网络变化

摘要:
在5.0之前,我们都广播BroadcastReceiver。注册与网络变化相关的广播,然后判断是连接还是断开连接非常方便。然而,随着Android版本的迭代,我们在权限方面变得越来越谨慎,广播方式也不是很优雅。因此,网络监控最终在Android 5.0及更高版本中进行了优化,即通过回调。这种开发模式很常见吗?

大家好,大概有一个多月没有更新博客了,我是干什么去了呢?很明显,程序员当然要加班……这一次跟大家分享一下新项目的一些心得。

监听网络变化在开发中是经常用到的,例如我们断网有一些友好的提示,或者根据不同的网络更改一些加载策略,例如wifi看视频,非wifi则会有一个提示,还有极个别更恶心的偷摸的在后台给你下各种安装包,是谁我就不一一列举了。

在5.0以前,我们都是广播BroadcastReceiver,注册跟网络变化相关的广播,然后判断是连接还是断开,这种做法非常方便,但是随着安卓的版本迭代,在权限上越来越谨慎,广播的方式就显得不太优雅。

打个比方,之前就是拿个大喇叭,在大街上各种喊,就好像逛地摊,各种商品的吆喝声混在一起,需要你自己去分辨哪些是你想要的信息,而且又显得很不安全,万一卖的商品比较隐私呢,大家都是很低调的人。

所以在安卓5.0以上终于对网络的监听进行了优化,那就是通过Callback回调的方式,这种开发模式是不是很常用?例如监听下载进度,我只需要三个回调:下载成功,下载失败,下载的进度变化,这种回调方式针对性强,耦合性低,非常方便,和广播相比,就好像我们是一个订购了服务,需要的东西自动上门,very good。

废话铺垫了这么多,下面就是一个实战demo。

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
            // 请注意这里会有一个版本适配bug,所以请在这里添加非空判断
            if (connectivityManager != null) {
                connectivityManager.requestNetwork(new NetworkRequest.Builder().build(), new ConnectivityManager.NetworkCallback() {

                    /**
                     * 网络可用的回调
                     * */
                    @Override
                    public void onAvailable(Network network) {
                        super.onAvailable(network);
                        Log.e("lzp", "onAvailable");
                    }

                    /**
                     * 网络丢失的回调
                     * */
                    @Override
                    public void onLost(Network network) {
                        super.onLost(network);
                        Log.e("lzp", "onLost");
                    }

                    /**
                     * 当建立网络连接时,回调连接的属性
                     * */
                    @Override
                    public void onLinkPropertiesChanged(Network network, LinkProperties linkProperties) {
                        super.onLinkPropertiesChanged(network, linkProperties);
                        Log.e("lzp", "onLinkPropertiesChanged");
                    }

                    /**
                     *  按照官方的字面意思是,当我们的网络的某个能力发生了变化回调,那么也就是说可能会回调多次
                     *
                     *  之后在仔细的研究
                     * */
                    @Override
                    public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) {
                        super.onCapabilitiesChanged(network, networkCapabilities);
                        Log.e("lzp", "onCapabilitiesChanged");
                    }

                    /**
                     * 在网络失去连接的时候回调,但是如果是一个生硬的断开,他可能不回调
                     * */
                    @Override
                    public void onLosing(Network network, int maxMsToLive) {
                        super.onLosing(network, maxMsToLive);
                        Log.e("lzp", "onLosing");
                    }

                    /**
                     * 按照官方注释的解释,是指如果在超时时间内都没有找到可用的网络时进行回调
                     * */
                    @Override
                    public void onUnavailable() {
                        super.onUnavailable();
                        Log.e("lzp", "onUnavailable");
                    }

                });
            }
        }
    }
}

这就是今天的全部代码了,上面已经有了响应的注释,但是还是不够便于我们理解,接下来就仔细的研究一下:

1、首先我们打开app,此时网络是连接的状态:

Android 5.0 以上监听网络变化第1张

一打开demo,我们立刻就得到了onAvailable的回调,意思就是网络目前可用,这一点比广播强多了,因为我们已启动还要单独处理一次,而通过回调的方式,可以立刻得到当前的状态。

2、然后我们手动关闭网络:

Android 5.0 以上监听网络变化第2张

哎?没有onLosing的回调,只看到了onLost,说明我们手动关闭网络连接是一个很粗暴的行为,就像官方注释上写的,如果是一个生硬的断开,他可能不回调。

3、最后我们再次连接网络:

Android 5.0 以上监听网络变化第3张

这次的回调就比较多了,首先是onAvailable,显示网络可用,然后是onCapabilitiesChanged,说此时网络的连接能力发生了第一次变化,估计是连接中把,再然后是onLinkPropertiesChanged,说明连接的属性已经发生了变化,此时应该获得了ip地址等信息,最后又回调了onCapabilitiesChanged,那么应该是网络进度到可用的状态。

#总结#

我没有模拟出onLosing和onUnavailable的场景,至少说明他俩的出现的概率现在已经不高了,我们已经通过注释简单理解了他俩的场景,这里就不做深入研究了。

通过刚才的实验,我们得出了一下结论:

1、要想监听网络的连接和断开,应该在onAvailable和onLost中,他们一定会成对出现。

2、其他的几个回调使用场景会少一点,并且onCapabilitiesChanged会回调多次,所以使用它时我们要慎重,避免重复的操作,但是可以保证最后一次回调,网络的连接一定是连接成功的。

OK,从这个小小的变化,我们看到了安卓在慢慢变得更好,使用起来更简洁更优雅,这也加大了某些素质低的厂商想尽办法后台干点坏事的行为。

今天就到这里,有什么问题大家一起留言讨论~

#补充#

1、记得申请权限:

<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
 <uses-permission android:name="android.permission.WRITE_SETTINGS" />

尤其是WRITE_SETTINGS,这个需要手动申请,千万别忘了。

免责声明:文章转载自《Android 5.0 以上监听网络变化》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Json.Net序列化和反序列化设置c语言中的原子操作下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Android 开发 VectorDrawable 矢量图 (八)animation-list帧动画配合矢量图实现动画

前言  只是矢量图的一个使用小技巧,关键点是<aapt:attr name="android:drawable"> 属性,它其实是代替<item 里的android:drawable属性。理解它,你可以举一反三使用到更多的需要实现动画,按下效果,选择效果的xml文件上,比如一个实现按下效果的xml将原来需要3个xml文件合并成一个xml文...

android浮动搜索框

android浮动搜索框的配置比较繁琐,需要配置好xml文件才能实现onSearchRequest()方法。 1.配置搜索的XML配置文件​,新建文件searchable.xml,保存在res/xml文件夹中。 1 <?xml version="1.0" encoding="UTF-8"?> 2 3 <searchable androi...

IPv6测试环境搭建

IPv6的简介 IPv4 和 IPv6的区别就是 IP 地址前者是 .(dot)分割,后者是以 :(冒号)分割的(更多详细信息自行搜索)。 PS:在使用 IPv6 的热点时候,记得手机开 飞行模式 哦,保证手机只在 Wi-Fi 下上网,以免手机在连接不到网络时候,会默认跳转到使用 蜂窝移动网络(即2G、3G、4G流量) 上网。 本地 Mac 搭建 IPv6...

Android之LinearLayout布局下怎么让按钮固定在底部

1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="fill_parent" 4 android...

Android基础——广播(静态注册)

安卓版本高了就会有点问题,不能静态注册  令活动Main用来发广播,另一个接收器(不是Activity而是receiver)用来接收广播 注册文件 <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/r...

Android 自动生成表格

Layout.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layou...