首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Android 網路連線檢查:ConnectivityManager 正確用法與 InetAddress 陷阱

     編輯:程式設計綜合問答

常見需求:App 啟動或關鍵操作前檢查網路是否可用。許多開發者嘗試用 InetAddress.getByName().isReachable() 或 ping,但這些方法**不可靠、延遲高、無權限**。正統做法是使用 ConnectivityManager。

標準檢查程式碼 (API 29+ / Android 10+)

public boolean isNetworkAvailable(Context context) {
    ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    if (cm == null) return false;
    
    NetworkCapabilities capabilities = cm.getNetworkCapabilities(cm.getActiveNetwork());
    return capabilities != null 
        && (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
            || capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
            || capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET));
}

相容舊版 (API < 29)


public boolean isOnline(Context context) {
    ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    if (cm == null) return false;
    
    NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
    return activeNetwork != null && activeNetwork.isConnectedOrConnecting();
}

關鍵差異:isConnected() vs isConnectedOrConnecting()

方法含義適用場景
isConnected()已建立連線、可傳輸資料需**立即**發送請求、上傳檔案
isConnectedOrConnecting()已連線**或**正在連線中啟動時檢查、預載資料、允許短暫等待

為什麼不用 InetAddress.isReachable()?

  • 需要 INTERNET 權限,但仍可能被防火牆/路由器阻擋 ICMP
  • 執行時間不可控(預設無超時參數),常導致 UI 卡頓
  • 無法區分 Wi-Fi/行動網路/乙太網路
  • Android 系統不保證回應 ICMP Echo Request

進階:監聽網路狀態變化 (NetworkCallback)


ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkRequest request = new NetworkRequest.Builder()
    .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
    .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
    .build();

cm.registerNetworkCallback(request, new ConnectivityManager.NetworkCallback() {
    @Override
    public void onAvailable(@NonNull Network network) {
        // 網路可用
        runOnUiThread(() -> Toast.makeText(MainActivity.this, "網路已連線", Toast.LENGTH_SHORT).show());
    }

    @Override
    public void onLost(@NonNull Network network) {
        // 網路中斷
        runOnUiThread(() -> Toast.makeText(MainActivity.this, "網路已斷開", Toast.LENGTH_SHORT).show());
    }
});

// 記得在 onDestroy 取消註冊
// cm.unregisterNetworkCallback(callback);

必要權限

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />

總結建議

  1. ✅ 使用 ConnectivityManager 而非 InetAddress/ping
  2. ✅ API 29+ 用 NetworkCapabilities,舊版用 NetworkInfo
  3. ✅ 區分 isConnected 與 isConnectedOrConnecting
  4. ✅ 長生命週期元件(Service、Application)註冊 NetworkCallback 監聽變化
  5. ✅ 實際請求前**再次檢查**,網路狀態瞬息萬變

正確檢查網路狀態,能大幅減少無效請求、提升使用者體驗。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved