1. 程式人生 > 其它 >安卓(Android)網路管理工具,判斷使用的網路型別、網路狀態判斷、以及可根據優先順序自動切換到實際可以上外網的網路通道

安卓(Android)網路管理工具,判斷使用的網路型別、網路狀態判斷、以及可根據優先順序自動切換到實際可以上外網的網路通道

安卓(Android)網路管理工具

判斷使用的網路型別、網路狀態判斷、以及可根據優先順序自動切換到實際可以上外網的網路通道

本文連線:https://www.cnblogs.com/muphy/p/15620772.html

適用於以下需求:

1.物聯網開發,為了滿足網路可靠性,對安卓應用設定了多網口上網,WIFI或者乙太網+4G網

2.當使用蜂窩網(4G)時限制資料上傳頻率,乙太網或者WIFI網路不限制

3.需要確保連線上的乙太網或者WIFI是否真的可以上外網,網路存在但不可以上網時繫結蜂窩網(4G)上網

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