android7.0版本适配(二):无法通过静态广播接收器监听网络连接

android7.0开始,无法通过在清单文件中注册广播接收器来监听CONNECTIVITY_ACTION广播。很多app都会监听网络变化,单次网络变化,所有静态监听该广播的应用都会被唤起并同时处理它。特别是那些根本没有启动进程的app,也不得不被唤起处理它,十分浪费性能。通过Context.registerReceiver()动态注册的广播依然可以收到CONNECTIVITY_ACTION广播,但不推荐那么做。

android推荐我们通过ConnectivityManager.registerNetworkCallback()方式注册网络变化监听器。

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    //获取ConnectivityManager
    ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    //创建NetworkRequest对象,定制化监听
    NetworkRequest customMonitor = new NetworkRequest.Builder().build();
    //创建网路变化监听器
    ConnectivityManager.NetworkCallback networkCallback = new ConnectivityManager.NetworkCallback() {
        //当网络连接可用时回调
        @Override
        public void onAvailable(@NonNull Network network) {
            super.onAvailable(network);
            EasyLogger.d("on network connected");
        }
        //当网络断开时回调
        @Override
        public void onLost(@NonNull Network network) {
            super.onLost(network);
            EasyLogger.d("on network disconnected");
        }
        //当网络属性变化时回调
        @Override
        public void onCapabilitiesChanged(@NonNull Network network, @NonNull NetworkCapabilities networkCapabilities) {
            super.onCapabilitiesChanged(network, networkCapabilities);
            boolean isMobileNetwork = networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR);
            boolean isWifiNetwork = networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI);
            boolean notUseVPN = networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN);
            EasyLogger.d("is mobile network:" + isMobileNetwork + ";is wifi network:" + isWifiNetwork + "; use :" + !notUseVPN);
        }
    };
    //注册网络监听器
    connectivityManager.registerNetworkCallback(customMonitor, networkCallback);
}

该API自5.0开始引入,建议5.0及以上版本均采用该方式监听网络变化。既然意识到这个性能问题,能够在更低的版本进行优化自然是好事。

先看第一个参数,NetworkRequest用来定制化监听,只有符合约束条件的网络变化才会回调NetworkCallback中的方法。

  • Transport约束
new NetworkRequest.Builder()
        //移动网络
        .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
        .build();

addTransportType()用来添加网络类型约束,上面的代码表示只监听移动网络。多个TransportType之间是“或”的关系,即满足其中之一即可。

new NetworkRequest.Builder()
        //移动网络
        .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
        //wifi网络
        .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
        .build();

上面的代码表示监听移动网络或wifi网络。

removeTransportType()可以删除某个约束,假如它存在的话。

new NetworkRequest.Builder()
        //如果存在wifi网络约束,则删除
        .removeTransportType(NetworkCapabilities.TRANSPORT_WIFI)
        .build();
  • Capability约束
new NetworkRequest.Builder()
        //没有使用
        .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
        //非漫游网络
        .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING)
        .build();

addCapability()用来添加一些网络属性,比如没有使用,非漫游网络等。多个Capability之间是“与”的关系,即必须同时满足。上面的代码表示必须没有使用且不是漫游网络。

所有的Transport和Capability定义在NetworkCapabilities中,可查阅该类获知其含义。


    //transport列表

    @Retention(RetentionPolicy.SOURCE)
    @IntDef(prefix = { "TRANSPORT_" }, value = {
            TRANSPORT_CELLULAR,
            TRANSPORT_WIFI,
            TRANSPORT_BLUETOOTH,
            TRANSPORT_ETHERNET,
            TRANSPORT_VPN,
            TRANSPORT_WIFI_AWARE,
            TRANSPORT_LOWPAN,
    })
    public @interface Transport { }

 

  //capability列表   

 @Retention(RetentionPolicy.SOURCE)
    @IntDef(prefix = { "NET_CAPABILITY_" }, value = {
            NET_CAPABILITY_MMS,
            NET_CAPABILITY_SUPL,
            NET_CAPABILITY_DUN,
            NET_CAPABILITY_FOTA,
            NET_CAPABILITY_IMS,
            NET_CAPABILITY_CBS,
            NET_CAPABILITY_WIFI_P2P,
            NET_CAPABILITY_IA,
            NET_CAPABILITY_RCS,
            NET_CAPABILITY_XCAP,
            NET_CAPABILITY_EIMS,
            NET_CAPABILITY_NOT_METERED,
            NET_CAPABILITY_INTERNET,
            NET_CAPABILITY_NOT_RESTRICTED,
            NET_CAPABILITY_TRUSTED,
            NET_CAPABILITY_NOT_VPN,
            NET_CAPABILITY_VALIDATED,
            NET_CAPABILITY_CAPTIVE_PORTAL,
            NET_CAPABILITY_NOT_ROAMING,
            NET_CAPABILITY_FOREGROUND,
            NET_CAPABILITY_NOT_CONGESTED,
            NET_CAPABILITY_NOT_SUSPENDED,
            NET_CAPABILITY_OEM_PAID,
    })
    public @interface NetCapability { }


什么时候终止监听?只有程序进程退出(注意是进程退出)或解除注册时终止监听。

//解除注册
connectivityManager.unregisterNetworkCallback(networkCallback);

 

android5.0以下我们改成动态监听CONNECTIVITY_ACTION广播,从而彻底告别隐式监听网络变化带来的性能问题。

定义BroadcastReceiver,

public class NetworkMonitorReceiver extends BroadcastReceiver {
    private onNetworkChangedCallback mOnNetworkChangedCallback;

    public NetworkMonitorReceiver(onNetworkChangedCallback onNetworkChangedCallback) {
        mOnNetworkChangedCallback = onNetworkChangedCallback;
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
        //网络是否连接可用
        boolean isConnected = networkInfo != null && networkInfo.isConnected();
        //获取网络类型
        String networkType = networkInfo == null ? "none" : networkInfo.getTypeName();
        if (mOnNetworkChangedCallback != null) {
            //回调监听器
            mOnNetworkChangedCallback.onNetworkChanged(isConnected, networkType);
        }
    }


    public static NetworkMonitorReceiver register(Context context, onNetworkChangedCallback callback) {
        NetworkMonitorReceiver networkMonitorReceiver = new NetworkMonitorReceiver(callback);
        IntentFilter intentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
        context.registerReceiver(networkMonitorReceiver, intentFilter);
        return networkMonitorReceiver;
    }

    public static void unregister(Context context, NetworkMonitorReceiver receiver) {
        context.unregisterReceiver(receiver);
        receiver.mOnNetworkChangedCallback = null;
    }

    public interface onNetworkChangedCallback {
        void onNetworkChanged(boolean isConnected, String type);
    }
}

动态注册广播接收器,

public class MainActivity extends AppCompatActivity implements NetworkMonitorReceiver.onNetworkChangedCallback {
    NetworkMonitorReceiver mNetworkMonitorReceiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mNetworkMonitorReceiver = NetworkMonitorReceiver.register(this, this);

    }

    @Override
    public void onNetworkChanged(boolean isConnected, String type) {
        //网络发生变化
        EasyLogger.d("网络连接可用:" + isConnected + ";网络类型:" + type);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        NetworkMonitorReceiver.unregister(this, mNetworkMonitorReceiver);
    }
}

 

你可能感兴趣的:(系统版本适配)