安卓(Android)网络管理工具,判断使用的网络类型、网络状态判断、以及可根据优先级自动切换到实际可以上外网的网络通道

安卓(Android)网络管理工具

判断使用的网络类型、网络状态判断、以及可根据优先级自动切换到实际可以上外网的网络通道

本文连接:https://www.cnblogs.com/muphy/p/15620772.html

适用于以下需求:

1.物联网开发,为了满足网络可靠性,对安卓应用设置了多网口上网,WIFI或者以太网+4G网

2.当使用蜂窝网(4G)时限制数据上传频率,以太网或者WIFI网络不限制

3.需要确保连接上的以太网或者WIFI是否真的可以上外网,网络存在但不可以上网时绑定蜂窝网(4G)上网

安卓(Android)网络管理工具,判断使用的网络类型、网络状态判断、以及可根据优先级自动切换到实际可以上外网的网络通道

 

 

NetWorkUtils.java

//package me.muphy.util;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.os.Build;
import android.util.Log;

import androidx.annotation.RequiresApi;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class NetWorkUtils {

    public static final String TAG = NetWorkUtils.class.getSimpleName();
    public static volatile boolean isActivityConnected = true;
    public static volatile boolean isConnected = true;
    private static ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public static List<NetworkCapabilities> getAllNetworkCapabilities() {
        ConnectivityManager connectivityManager = (ConnectivityManager) ContextHolder.getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
        Network[] networks = connectivityManager.getAllNetworks();
        List<NetworkCapabilities> list = new ArrayList<>();
        for (Network network : networks) {
            NetworkCapabilities capabilities = connectivityManager.getNetworkCapabilities(network);
            list.add(capabilities);
        }
        return list;
    }

    public static String getNetworkName(int transportType) {
        if (transportType == NetworkCapabilities.TRANSPORT_WIFI) {
            return "WIFI";
        } else if (transportType == NetworkCapabilities.TRANSPORT_CELLULAR) {
            return "蜂窝网络";
        } else if (transportType == NetworkCapabilities.TRANSPORT_ETHERNET) {
            return "以太网";
        } else {
            return "其他网络";
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public static int getTransportType(NetworkCapabilities networkCapabilities) {
        if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
            return NetworkCapabilities.TRANSPORT_WIFI;
            //post(NetType.WIFI);
        } else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
            return NetworkCapabilities.TRANSPORT_CELLULAR;
            //post(NetType.CMWAP);
        } else if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) {
            return NetworkCapabilities.TRANSPORT_ETHERNET;
            //post(NetType.AUTO);
        }
        return -1;
    }

    //以太网连上但不能上外网时,程序已经绑定了蜂窝网通道上网,此方法判断是否实际使用蜂窝网上网
    public static boolean isRealCellular() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            boolean activityCellular = isActivityCellular();
            if (activityCellular) {
                return true;
            }
            return !isActivityConnected;
        }
        return true;
    }

    //判断激活的网(默认网络)是否4G网
    @RequiresApi(api = Build.VERSION_CODES.M)
    public static boolean isActivityCellular() {
        boolean isCellular = (getTransportType() == NetworkCapabilities.TRANSPORT_CELLULAR);
        return isCellular;
    }

    public static boolean isCellular(int transportType) {
        boolean isCellular = (transportType == NetworkCapabilities.TRANSPORT_CELLULAR);
        return isCellular;
    }

    //判断激活的网(默认网络)是否4G网
    @RequiresApi(api = Build.VERSION_CODES.M)
    public static boolean isActivityWifi() {
        boolean isWifi = (getTransportType() == NetworkCapabilities.TRANSPORT_WIFI);
        return isWifi;
    }

    public static boolean isWifi(int transportType) {
        boolean isWifi = (transportType == NetworkCapabilities.TRANSPORT_WIFI);
        return isWifi;
    }

    //判断激活的网(默认网络)是否4G网
    @RequiresApi(api = Build.VERSION_CODES.M)
    public static boolean isActivityEthernet() {
        boolean isEthernet = (getTransportType() == NetworkCapabilities.TRANSPORT_ETHERNET);
        return isEthernet;
    }

    public static boolean isEthernet(int transportType) {
        boolean isEthernet = (transportType == NetworkCapabilities.TRANSPORT_ETHERNET);
        return isEthernet;
    }

    @RequiresApi(api = Build.VERSION_CODES.M)
    public static int getTransportType() {
        int transportType = -2;
        ConnectivityManager connectivityManager = (ConnectivityManager) ContextHolder.getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
        Network activeNetwork = connectivityManager.getActiveNetwork();
        if (activeNetwork == null) {
            isConnected = false;
        } else {
            NetworkCapabilities networkCapabilities = connectivityManager.getNetworkCapabilities(activeNetwork);
            if (networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)) {
                isConnected = true;
                transportType = getTransportType(networkCapabilities);
            } else {
                isConnected = false;
            }
        }
        return transportType;
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    public static void requestNetwork() {
        final ConnectivityManager connectivityManager = (ConnectivityManager) ContextHolder.getContext().getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkRequest.Builder builder = new NetworkRequest.Builder();
        builder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
        builder.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
        NetworkRequest networkRequest = builder.build();
        ConnectivityManager.NetworkCallback networkCallback = new ConnectivityManager.NetworkCallback() {
            @Override
            public void onAvailable(Network network) {
                if (Build.VERSION.SDK_INT >= 23) {
                    connectivityManager.bindProcessToNetwork(network);
                } else {
                    // 23后这个方法舍弃了
                    ConnectivityManager.setProcessDefaultNetwork(network);
                }
            }
        };
        final boolean[] chanelFlag = {true};
        executorService.scheduleWithFixedDelay(() -> {
            try {
                //网络都没连接直接返回
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    if (isActivityCellular()) {
                        return;
                    }
                }
                if (!isConnected) {
                    return;
                }
                isActivityConnected = ping();
                if (isActivityConnected) {
                    if (chanelFlag[0]) {
                        return;
                    }
                    chanelFlag[0] = true;
                    //1.以太网络可上外网时改为默认优先级上网
                    if (Build.VERSION.SDK_INT >= 23) {
                        connectivityManager.bindProcessToNetwork(null);
                    } else {
                        ConnectivityManager.setProcessDefaultNetwork(null);
                    }
                    connectivityManager.unregisterNetworkCallback(networkCallback);
                } else if (chanelFlag[0]) {
                    //2.以太网络不可上外网时自动切换蜂窝网
                    connectivityManager.requestNetwork(networkRequest, networkCallback);
                    chanelFlag[0] = false;
                }
            } catch (Exception e) {
                e.printStackTrace();
                LogFileUtils.exceptionToFile(e);
            }
        }, 1, 5, TimeUnit.SECONDS);
    }

    // PING命令 使用新进程使用默认网络 不会使用 networkCallback 绑定的通道  用来判断以太网或者WiFi是否可上外网非常不错
    public static boolean ping() {
        Runtime runtime = Runtime.getRuntime();
        try {
            Process p = runtime.exec("ping -c 1 -W 1 www.baidu.com");
            int ret = p.waitFor();
            Log.i(TAG, "Process:" + ret);
            return ret == 0;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }
}

 

上一篇:springCloud+nacos+seata环境搭建


下一篇:Intellij IDEA基于Springboot的远程调试