安卓项目实战之:安卓7.0优化下的全局网络连接状态监听

版权声明:转载必须注明本文转自郭子轩的博客 https://blog.csdn.net/gpf1320253667/article/details/84553900

须知:Android7.0起网络变化监听隐式广播被关闭

在 Android 7.0 版本中除了提供诸多多窗口支持、活动通知、后台优化、消息传递服务和Vulkan 等新特性和功能外,还对系统和 API 行为做出了各种变更,其中最重要的一点:Android7.0为了进行后台的优化删除了三项隐式广播(网络状态变更广播、拍照广播以及录像广播),以帮助优化内存使用和电量消耗。 此项变更很有必要,比如说网络变化的广播(CONNECTIVITY_CHANGE),当网络发生变化时所有注册了隐式监听网络变化的app都会被启动。删除这些广播可以显著提升设备性能和用户体验。同样地,拍照广播和录视频广播(ACTION_NEW_PICTURE or ACTION_NEW_VIDEO)也会出现上述情况。

该变更导致在Android N平台下即使在Manifest.xml清单文件中注册了 CONNECTIVITY_ACTION广播,在网络发生变化时也不会接收到任何的信息。但是正在前台运行的应用程序如果在主线程中通过Context.registerReceiver()动态注册了CONNECTIVITY_ACTION广播,该应用程序仍然可以接收到该广播。(注:这样开发者就可以根据不同的网络状态加载相应的页面信息了,从而提高用户体验)。

总结:为了避免Android7.0版本接收不到系统网络变化的广播,强烈建议使用动态注册广播的形式来注册广播。

1,添加权限

<!-- 访问网络.  -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- 访问WiFi状态.  -->
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<!-- 访问网络状态, 检测网络的可用性. -->
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

2,编写网络监听工具类

工具类见本人博客:安卓项目实战之:网络连接判断工具类
直接Copy过来用即可。

3,新建一个接口来接收状态变化的回调

public interface INetEvent {
    void onNetChange(int netWorkState);
}

4,新建一个BroadcastReceiver,监听网络状态变化

public class NetStateReceiver extends BroadcastReceiver {

    private INetEvent mINetEvent= BaseActivity.mINetEvent;
    @Override
    public void onReceive(Context context, Intent intent) {
        // 如果相等的话就说明网络状态发生了变化
        if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
            //容错机制
            if(mINetEvent!=null) {
                // 接口回调传过去状态的类型
                mINetEvent.onNetChange(NetWorkUtils.getNetWorkState(context));
            }
        }
    }
}

5,在清单文件中配置 (该步骤取消,为适配7.0已在BaseActivity中动态注册)

<!-- 监听网络变化的广播 -->
        <receiver
            android:name=".receiver.NetStateReceiver"
            android:enabled="true"
            android:exported="true">
            <intent-filter>
                <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
            </intent-filter>
        </receiver>

6,在基类BaseActivity中实现INetEvent接口

public abstract class BaseActivity extends AppCompatActivity implements INetEvent {

    public static INetEvent mINetEvent;
    // 网络状态变化的广播接收器
    private NetStateReceiver mNetStateReceiver;
    // 当前网路连接状态,网络状态发生变化,该值会动态更新
    // -1:没有网络    0:移动网络     1:wifi网络
    protect int netWorkState;
    
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //初始化网络状态的监听
        mINetEvent=this; 
        // 初始化时检查网络连接
        checkNet();
        // 动态注册网络状态监听广播
        mNetStateReceiver = new NetStateReceiver();
        IntentFilter filter = new IntentFilter();
        filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
        registerReceiver(mNetStateReceiver , filter);
    }

    /**
     * 初始化时获取当前网络状态
     */
    public void checkNet() {
        this.netWorkState= NetWorkUtils.getNetWorkState(BaseActivity.this);
    }
    
    /**
     * 全局检测网络广播的回调 处理网络变化
     * @param netWorkState 网络状态    -1:没网络  0:移动网络  1:WiFi网络
     */
    public abstract void onNetChanged(int netWorkState);
    
    @Override
    public void onNetChange(int netWorkState) {
        this.netWorkState= netWorkState;
        onNetChanged(netWorkState);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 取消注册
        unregisterReceiver(mNetStateReceiver);
    }
}

7,具体Activity的实现

public class NetStateActivity extends BaseActivity {
    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_netstate);
    }

    @Override
    public void onNetChanged(int netWorkState) {
        switch (netWorkState) {
            case  NetWorkUtils.NETWORK_NONE:
                //没有网络
                break;
            case  NetWorkUtils.NETWORK_MOBILE:
                //移动网络
                break;
            case  NetWorkUtils.NETWORK_WIFI:
                //WiFi网络
                break;
        }
    }
}

广播监听只有在网络状态发生变化的情况下才会触发回调,因此当第一次在没网时启动app的时候,该监听并不会回调,所以我们需要在第一次启动app时做手动的判断,上面的处理中我们每次在Activity界面初始化的时候进行了网络判断,并且将获取到的网络值传给了成员变量netWorkState,所以我们可以直接获取该值进行网络状态判断:

// netWorkState就是继承的父类的成员变量
Toast.makeText(this, "当前网络状态:"+netWorkState, Toast.LENGTH_SHORT).show();

猜你喜欢

转载自blog.csdn.net/gpf1320253667/article/details/84553900
今日推荐