Phát hiện nếu thiết bị Android có kết nối Internet


138

Tôi cần biết thiết bị của mình có kết nối Internet hay không. Tôi tìm thấy nhiều câu trả lời như:

private boolean isNetworkAvailable() {
    ConnectivityManager connectivityManager 
         = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
    return activeNetworkInfo != null;
}

(Lấy từ Phát hiện xem có kết nối Internet có sẵn trên Android hay không .)

Nhưng điều này không đúng, ví dụ nếu tôi kết nối với mạng không dây không có quyền truy cập Internet , phương pháp này sẽ trả về true. Có cách nào để biết thiết bị có kết nối Internet không và nếu nó chỉ được kết nối một cái gì đó?


Này, bạn cũng có thể đi với [này] [1]. Điều đó có thể giúp! [1]: stackoverflow.com/questions/4238921/ từ
akshay


Khối isNetworkConnectedchức năng chứa mã không dùng cho tất cả Build.VERSION.SDK_INT >= Build.VERSION_CODES.M. Một cuộc thảo luận sâu hơn về vấn đề & cách khắc phục có thể được tìm thấy ở đây stackoverflow.com/questions/53532406/
Kẻ

Câu trả lời:


182

Bạn đúng rồi. Mã bạn đã cung cấp chỉ kiểm tra nếu có kết nối mạng. Cách tốt nhất để kiểm tra xem có kết nối Internet đang hoạt động hay không là thử và kết nối với một máy chủ đã biết qua http.

public static boolean hasActiveInternetConnection(Context context) {
    if (isNetworkAvailable(context)) {
        try {
            HttpURLConnection urlc = (HttpURLConnection) (new URL("http://www.google.com").openConnection());
            urlc.setRequestProperty("User-Agent", "Test");
            urlc.setRequestProperty("Connection", "close");
            urlc.setConnectTimeout(1500); 
            urlc.connect();
            return (urlc.getResponseCode() == 200);
        } catch (IOException e) {
            Log.e(LOG_TAG, "Error checking internet connection", e);
        }
    } else {
        Log.d(LOG_TAG, "No network available!");
    }
    return false;
}

Tất nhiên, bạn có thể thay thế http://www.google.comURL cho bất kỳ máy chủ nào khác mà bạn muốn kết nối hoặc máy chủ mà bạn biết có thời gian hoạt động tốt.

Như Tony Cho cũng đã chỉ ra trong nhận xét này bên dưới , hãy đảm bảo bạn không chạy mã này trên luồng chính, nếu không, bạn sẽ nhận được ngoại lệ NetworkOnMainThread (trong Android 3.0 trở lên). Sử dụng AsyncTask hoặc Runnable thay thế.

Nếu bạn muốn sử dụng google.com, bạn nên xem bản sửa đổi của Jeshurun. Trong câu trả lời của anh ấy, anh ấy đã sửa đổi mã của tôi và làm cho nó hiệu quả hơn một chút. Nếu bạn kết nối với

HttpURLConnection urlc = (HttpURLConnection) 
            (new URL("http://clients3.google.com/generate_204")
            .openConnection());

và sau đó kiểm tra mã phản hồi cho 204

return (urlc.getResponseCode() == 204 && urlc.getContentLength() == 0);

sau đó bạn không phải tìm nạp toàn bộ trang chủ google trước.


9
@varunbhardwaj bạn chỉ có thể lấy một trang web khác (ví dụ: b Nikol.com khi triển khai ứng dụng của bạn ở Trung Quốc) hoặc bạn có thể thử trang web thứ hai nếu trang đầu tiên không đảm bảo không có kết nối.
THelper

2
i +1 câu trả lời của bạn và biết sử dụng nó trong ứng dụng của tôi, nhưng có một trường hợp lớn phụ thuộc vào một số trang web và câu hỏi của tôi vẫn chưa được trả lời. Dù sao cách giải quyết tuyệt vời hơnx.
varun bhardwaj

2
@blackcrow Phụ thuộc vào thời gian bạn / người dùng sẵn sàng chờ đợi. Cá nhân tôi coi 1000ms là giới hạn thấp hơn, 6000ms trung bình và dài 15000ms. Nhưng nếu kiểm tra đang chạy trong nền và người dùng không chờ đợi, bạn có thể sử dụng thời gian chờ lâu hơn nhiều.
THelper

1
@varunbhardwaj Cần có một số URI bạn có thể truy cập từ các dịch vụ web của mình. Điều đầu tiên chúng tôi yêu cầu khi ứng dụng của chúng tôi khởi động là một tệp bootstrap chứa nhiều thông tin cấu hình khác nhau, cho phép chúng tôi thay đổi các thông số khác nhau phía máy chủ. Một cái gì đó như thế có thể được sử dụng.
Steve

11
Điều này cũng nên được đưa xuống trên một chủ đề nền (trong khi kiểm tra ConnectivityManagerkhông yêu cầu này). Nếu không, trên các thiết bị Android 4.x +, bạn sẽ có một NetworkOnMainThreadngoại lệ.
Anthony Chuinard

90

Tôi đã sửa đổi câu trả lời của THelper một chút, để sử dụng một bản hack đã biết mà Android đã sử dụng để kiểm tra xem mạng WiFi được kết nối có truy cập Internet hay không. Điều này hiệu quả hơn rất nhiều so với việc lấy toàn bộ trang chủ Google. Xem ở đâyở đây để biết thêm.

public static boolean hasInternetAccess(Context context) {
    if (isNetworkAvailable(context)) {
        try {
            HttpURLConnection urlc = (HttpURLConnection) 
                (new URL("http://clients3.google.com/generate_204")
                .openConnection());
            urlc.setRequestProperty("User-Agent", "Android");
            urlc.setRequestProperty("Connection", "close");
            urlc.setConnectTimeout(1500); 
            urlc.connect();
            return (urlc.getResponseCode() == 204 &&
                        urlc.getContentLength() == 0);
        } catch (IOException e) {
            Log.e(TAG, "Error checking internet connection", e);
        }
    } else {
        Log.d(TAG, "No network available!");
    }
    return false;
}

1
Xin chào, có ổn không khi sử dụng thực hành này trong các ứng dụng hiện tại?
Slava Fomin II

Đây có phải là hiệu quả trong việc thực hiện trong ứng dụng hiện tại của chúng tôi?
therealprashant

5
Nó sẽ là cách hiệu quả hơn so với phương pháp trong câu trả lời ở trên. Nắm bắt trang chủ Google là rất không hiệu quả, đặc biệt là nếu họ tình cờ có một hình tượng trưng trên đó.
Jeshurun

1
Kiểm tra như phản hồi chính xác nên được cập nhật với điều này bởi vì nó cải thiện câu trả lời. Làm tốt lắm, cảm ơn
Hugo

3
Bạn có thể muốn sử dụng g.cn/generate_204 thay vì client3.google.com/generate_204 nếu bạn cũng muốn kiểm tra kết nối ở Trung Quốc
breez

18
public boolean isInternetWorking() {
    boolean success = false;
    try {
        URL url = new URL("https://google.com");
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setConnectTimeout(10000);
        connection.connect();
        success = connection.getResponseCode() == 200;
    } catch (IOException e) {
        e.printStackTrace();
    }
    return success;
}

Trả lại đúng nếu internet thực sự có sẵn

Hãy chắc chắn rằng bạn có hai quyền này

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

nếu http không hoạt động vì bảo mật Android mới, họ không cho phép giao tiếp văn bản đơn giản ngay bây giờ. bây giờ chỉ để vượt qua nó.

android: usedCleartextTraffic = "true"


Đây là câu trả lời hay nhất, đầy đủ nhất: đó là cách làm ngắn nhất (ping không truy cập toàn bộ trang web), nó chạy độc lập với kết nối nào bạn có và nó chạy trong quá trình giành chiến thắng để nó chơi tốt với các phiên bản Android .
MacD

ý bạn là gì ? đây là một đoạn mà tôi đang sử dụng trong một dự án hiện tại checkInternet
Bilal Shahid

ý anh ta là cuộc gọi này sẽ chặn UI và anh ta cần thực hiện cuộc gọi này trong chuỗi ??
Amit Hooda

2
Điều này không hiệu quả với tôi ... Nguyên nhân bởi: android.os.NetworkOnMainThreadException tại android.os.StrictMode $ AndroidBlockGuardPolicy.onNetwork (StrictMode.java:1273) tại java.net.InetAddress.lookuphostByName (Inet vào lúc
Maryadi Poipo

@HyosokaPoipo bạn không nên gọi điều này trên luồng chính. Sử dụng một chủ đề riêng hoặc AsyncTask.
Pramesh Bajracharya

14

Nếu bạn đang nhắm mục tiêu Lollipop hoặc cao hơn, có thể sử dụng lớp NetworkCapabilities mới, nghĩa là:

public static boolean hasInternetConnection(final Context context) {
    final ConnectivityManager connectivityManager = (ConnectivityManager)context.
            getSystemService(Context.CONNECTIVITY_SERVICE);

    final Network network = connectivityManager.getActiveNetwork();
    final NetworkCapabilities capabilities = connectivityManager
            .getNetworkCapabilities(network);

    return capabilities != null
            && capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED);
}

1
connectivityManager.getActiveNetwork();yêu cầu API lvl23 là Marshmallow chứ không phải Lollipop.
Saenic

Chúng ta cũng nên kiểm tra khả năng.hasCapability (NetworkCapabilities.NET_CAPABILITY_INTERNET)?
Alex

Alex capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)dường như làm mánh khóe cho tôi!
rstojano

6

Bạn không nhất thiết phải tạo kết nối HTTP đầy đủ. Bạn có thể thử chỉ cần mở kết nối TCP đến một máy chủ đã biết và nếu thành công, bạn có kết nối internet.

public boolean hostAvailable(String host, int port) {
  try (Socket socket = new Socket()) {
    socket.connect(new InetSocketAddress(host, port), 2000);
    return true;
  } catch (IOException e) {
    // Either we have a timeout or unreachable host or failed DNS lookup
    System.out.println(e);
    return false;
  }
}

Sau đó, chỉ cần kiểm tra với:

boolean online = hostAvailable("www.google.com", 80);

Cổng 80 có phải là cổng an toàn để sử dụng không?
ralphgabb

Miễn là nó lưu trữ máy chủ HTTP, nó sẽ chấp nhận kết nối TCP trên Cổng 80.
Xiv

Điều này có nên được sử dụng bên trong AsyncTask hay chỉ được gọi trong phương thức onCreate của MainActivity chẳng hạn?
AlexioVay

@Vay bất cứ điều gì liên quan đến mạng không nên chạy trên luồng chính / ui. Vì vậy, có, điều này nên được sử dụng trong mộtAsyncTask
winklerrr

6

Dựa trên các câu trả lời được chấp nhận, tôi đã xây dựng lớp này với một trình nghe để bạn có thể sử dụng nó trong luồng chính:

Đầu tiên : Lớp InterntCheck kiểm tra kết nối internet trong nền sau đó gọi phương thức nghe với kết quả.

public class InternetCheck extends AsyncTask<Void, Void, Void> {


    private Activity activity;
    private InternetCheckListener listener;

    public InternetCheck(Activity x){

        activity= x;

    }

    @Override
    protected Void doInBackground(Void... params) {


        boolean b = hasInternetAccess();
        listener.onComplete(b);

        return null;
    }


    public void isInternetConnectionAvailable(InternetCheckListener x){
        listener=x;
        execute();
    }

    private boolean isNetworkAvailable() {
        ConnectivityManager connectivityManager = (ConnectivityManager) activity.getSystemService(CONNECTIVITY_SERVICE);
        NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
        return activeNetworkInfo != null;
    }
    private boolean hasInternetAccess() {
        if (isNetworkAvailable()) {
            try {
                HttpURLConnection urlc = (HttpURLConnection) (new URL("http://clients3.google.com/generate_204").openConnection());
                urlc.setRequestProperty("User-Agent", "Android");
                urlc.setRequestProperty("Connection", "close");
                urlc.setConnectTimeout(1500);
                urlc.connect();
                return (urlc.getResponseCode() == 204 &&
                        urlc.getContentLength() == 0);
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            Log.d("TAG", "No network available!");
        }
        return false;
    }

    public interface InternetCheckListener{
        void onComplete(boolean connected);
    }

}

Thứ hai : khởi tạo một thể hiện của lớp trong luồng chính và chờ phản hồi (nếu bạn đã làm việc với Firebase api cho Android trước khi điều này quen thuộc với bạn!).

new InternetCheck(activity).isInternetConnectionAvailable(new InternetCheck.InternetCheckListener() {

        @Override
        public void onComplete(boolean connected) {
           //proceed!
        }
    });

Bây giờ bên trong phương thức onComplete bạn sẽ biết liệu thiết bị có được kết nối với internet hay không.


3

thử cái này

public class ConnectionDetector {
    private Context _context;

    public ConnectionDetector(Context context) {
        this._context = context;
    }

    public boolean isConnectingToInternet() {
        if (networkConnectivity()) {
            try {
                HttpURLConnection urlc = (HttpURLConnection) (new URL(
                        "http://www.google.com").openConnection());
                urlc.setRequestProperty("User-Agent", "Test");
                urlc.setRequestProperty("Connection", "close");
                urlc.setConnectTimeout(3000);
                urlc.setReadTimeout(4000);
                urlc.connect();
                // networkcode2 = urlc.getResponseCode();
                return (urlc.getResponseCode() == 200);
            } catch (IOException e) {
                return (false);
            }
        } else
            return false;

    }

    private boolean networkConnectivity() {
        ConnectivityManager cm = (ConnectivityManager) _context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo networkInfo = cm.getActiveNetworkInfo();
        if (networkInfo != null && networkInfo.isConnected()) {
            return true;
        }
        return false;
    }
}

bạn sẽ phải thêm quyền sau vào tệp kê khai của mình:

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

Rồi gọi như thế:

if((new ConnectionDetector(MyService.this)).isConnectingToInternet()){
    Log.d("internet status","Internet Access");
}else{
    Log.d("internet status","no Internet Access");
}


sử dụng đồng tính này thử bắt do đó lỗi không được hiển thị, trước tiên hãy thêm quyền internet sau đó thử điều này. nó hoạt động tốt
Attaullah

Hãy để tôi nói cho bạn biết làm thế nào tôi gọi phương pháp này trong hoạt động của tôi?
Milan Gajera

Tôi đã thử gửi bài cho bạn và tôi đã gặp một lỗi mà tôi đã đăng một lỗi trong blog của mình
Milan Gajera


1

Bạn có thể làm điều này bằng cách sử dụng ConnectivityManager API cho Android. Nó cho phép bạn kiểm tra xem bạn có kết nối với internet và loại kết nối internet mà bạn được kết nối hay không. Về cơ bản, Metered hoặc Un-metered.

Để kiểm tra kết nối internet.

ConnectivityManager cm = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
boolean isConnected = activeNetwork != null && activeNetwork.isConnectedOrConnecting();

Liên kết tài liệu: https://developer.android.com/training/monitoring-device-state/connectivity-status-type


Làm thế nào để bạn kiểm tra nếu dữ liệu di động đã hết? Điều này trả về đúng ngay cả khi dữ liệu di động được kết nối và không còn số dư dữ liệu trên tài khoản.
dùng2672052

0
private static NetworkUtil mInstance;
private volatile boolean mIsOnline;

private NetworkUtil() {
    ScheduledExecutorService exec = Executors.newSingleThreadScheduledExecutor();
    exec.scheduleAtFixedRate(new Runnable() {
        @Override
        public void run() {
            boolean reachable = false;
            try {
                Process process = java.lang.Runtime.getRuntime().exec("ping -c 1 www.google.com");
                int returnVal = process.waitFor();
                reachable = (returnVal==0);
            } catch (Exception e) {
                e.printStackTrace();
            }
            mIsOnline = reachable;
        }
    }, 0, 5, TimeUnit.SECONDS);
}

public static NetworkUtil getInstance() {
    if (mInstance == null) {
        synchronized (NetworkUtil.class) {
            if (mInstance == null) {
                mInstance = new NetworkUtil();
            }
        }
    }
    return mInstance;
}

public boolean isOnline() {
    return mIsOnline;
}

Hy vọng mã trên giúp bạn, cũng đảm bảo bạn có sự cho phép internet trong ứng dụng của bạn.


0

Cách mới nhất để làm điều đó từ tài liệu là sử dụng ConnectivityManagerđể truy vấn mạng đang hoạt động và xác định xem nó có kết nối Internet hay không.

public boolean hasInternetConnectivity() {
    ConnectivityManager cm =
        (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);

    NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
    return (activeNetwork != null &&
                      activeNetwork.isConnectedOrConnecting());
}

Thêm hai quyền này vào tệp AndroidManifest.xml của bạn:

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

1
Không hoạt động :( Như @Buda Gavril nói, nếu tôi kết nối với mạng không dây không có truy cập Internet, phương pháp này vẫn sẽ trở lại đúng. Thử nghiệm trên Xiaomi 4, Android 6.0.1.
DysaniazzZ

0

Kiểm tra loại wifi trong trình quản lý kết nối:

   //check network connection
    ConnectivityManager cm = (ConnectivityManager) this.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
    boolean hasNetworkConnection = activeNetwork != null && activeNetwork.isConnectedOrConnecting();
    System.out.println("Connection ? : " + hasNetworkConnection);
    //check wifi
    boolean hasWifiConnection = activeNetwork.getType() == ConnectivityManager.TYPE_WIFI;
    System.out.println("Wifi ? : " + hasWifiConnection);

Tài liệu Android mô tả 'TYPE_WIFI' là 'Kết nối dữ liệu WIFI. Các thiết bị có thể hỗ trợ nhiều hơn một. '


0

Một giải pháp hay để kiểm tra xem mạng đang hoạt động có kết nối internet hay không:

public boolean isNetworkAvailable(Context context) {
    ConnectivityManager connectivityManager
            = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    if (connectivityManager != null) {
        Network network = connectivityManager.getActiveNetwork();
        NetworkCapabilities networkCapabilities = connectivityManager.getNetworkCapabilities(network);
        return networkCapabilities != null && networkCapabilities
                .hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
    }
    return false;
}

0

Bạn có thể sử dụng ConnectivityManager.

val cm = getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
            val activeNetwork: NetworkInfo? = cm.activeNetworkInfo
            val dialogBuilder = AlertDialog.Builder(this)

            if (activeNetwork!=null) // Some network is available
            {
                if (activeNetwork.isConnected) { // Network is connected to internet

    }else{ // Network is NOT connected to internet

    }

Kiểm tra cái nàycái này


0

Sử dụng lớp sau , được cập nhật lên cấp API cuối cùng: 29.

// License: MIT
// http://opensource.org/licenses/MIT
package net.i2p.android.router.util;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.os.Build;
import android.telephony.TelephonyManager;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.concurrent.CancellationException;



/**
 * Check device's network connectivity and speed.
 *
 * @author emil http://stackoverflow.com/users/220710/emil
 * @author str4d
 * @author rodrigo https://stackoverflow.com/users/5520417/rodrigo
 */
public class ConnectivityAndInternetAccessCheck {

    private static ArrayList < String > hosts = new ArrayList < String > () {
        {
            add("google.com");
            add("facebook.com");
            add("apple.com");
            add("amazon.com");
            add("twitter.com");
            add("linkedin.com");
            add("microsoft.com");
        }
    };
    /**
     * Get the network info.
     *
     * @param context the Context.
     * @return the active NetworkInfo.
     */
    private static NetworkInfo getNetworkInfo(Context context) {
        NetworkInfo networkInfo = null;
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        if (cm != null) {
            networkInfo = cm.getActiveNetworkInfo();
        }
        return networkInfo;
    }

    /**
     * Gets the info of all networks
     * @param context The context
     * @return an array of @code{{@link NetworkInfo}}
     */
    private static NetworkInfo[] getAllNetworkInfo(Context context) {
        ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        return cm.getAllNetworkInfo();
    }

    /**
     * Gives the connectivity manager
     * @param context The context
     * @return the @code{{@link ConnectivityManager}}
     */
    private static ConnectivityManager getConnectivityManager(Context context) {
        return (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    }

    /**
     * Check if there is any connectivity at all.
     *
     * @param context the Context.
     * @return true if we are connected to a network, false otherwise.
     */
    public static boolean isConnected(Context context) {
        boolean isConnected = false;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            ConnectivityManager connectivityManager = ConnectivityAndInternetAccessCheck.getConnectivityManager(context);
            Network[] networks = connectivityManager.getAllNetworks();
            networksloop: for (Network network: networks) {
                if (network == null) {
                    isConnected = false;
                } else {
                    NetworkCapabilities networkCapabilities = connectivityManager.getNetworkCapabilities(network);
                    if(networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)){
                        isConnected = true;
                        break networksloop;
                    }
                    else {
                        isConnected = false;
                    }
                }
            }

        } else {
            NetworkInfo[] networkInfos = ConnectivityAndInternetAccessCheck.getAllNetworkInfo(context);
            networkinfosloop: for (NetworkInfo info: networkInfos) {
                // Works on emulator and devices.
                // Note the use of isAvailable() - without this, isConnected() can
                // return true when Wifi is disabled.
                // http://stackoverflow.com/a/2937915
                isConnected = info != null && info.isAvailable() && info.isConnected();
                if (isConnected) {
                    break networkinfosloop;
                }
            }

        }
        return isConnected;
    }

    /**
     * Check if there is any connectivity to a Wifi network.
     *
     * @param context the Context.
     * @return true if we are connected to a Wifi network, false otherwise.
     */
    public static boolean isConnectedWifi(Context context) {
        boolean isConnectedWifi = false;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            ConnectivityManager connectivityManager = ConnectivityAndInternetAccessCheck.getConnectivityManager(context);
            Network[] networks = connectivityManager.getAllNetworks();
            networksloop: for (Network network: networks) {
                if (network == null) {
                    isConnectedWifi = false;
                } else {
                    NetworkCapabilities networkCapabilities = connectivityManager.getNetworkCapabilities(network);
                    if(networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)){
                        if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)) {
                            isConnectedWifi = true;
                            break networksloop;
                        } else {
                            isConnectedWifi = false;
                        }
                    }
                }

            }


        } else {
            NetworkInfo[] networkInfos = ConnectivityAndInternetAccessCheck.getAllNetworkInfo(context);
            networkinfosloop: for (NetworkInfo n: networkInfos) {
                isConnectedWifi = n != null && n.isAvailable() && n.isConnected() && n.getType() == ConnectivityManager.TYPE_WIFI;
                if (isConnectedWifi) {
                    break networkinfosloop;
                }

            }
        }
        return isConnectedWifi;
    }

    /**
     * Check if there is any connectivity to a mobile network.
     *
     * @param context the Context.
     * @return true if we are connected to a mobile network, false otherwise.
     */
    public static boolean isConnectedMobile(Context context) {
        boolean isConnectedMobile = false;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            ConnectivityManager connectivityManager = ConnectivityAndInternetAccessCheck.getConnectivityManager(context);
            Network[] allNetworks = connectivityManager.getAllNetworks();
            networksloop: for (Network network: allNetworks) {
                if (network == null) {
                    isConnectedMobile = false;
                } else {
                    NetworkCapabilities networkCapabilities = connectivityManager.getNetworkCapabilities(network);
                    if(networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)){
                        if (networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
                            isConnectedMobile = true;
                            break networksloop;
                        } else {
                            isConnectedMobile = false;
                        }
                    }
                }

            }

        } else {
            NetworkInfo[] networkInfos = ConnectivityAndInternetAccessCheck.getAllNetworkInfo(context);
            networkinfosloop: for (NetworkInfo networkInfo: networkInfos) {
                isConnectedMobile = networkInfo != null && networkInfo.isAvailable() && networkInfo.isConnected() && networkInfo.getType() == ConnectivityManager.TYPE_MOBILE;
                if (isConnectedMobile) {
                    break networkinfosloop;
                }
            }
        }
        return isConnectedMobile;
    }

    /**
     * Check if there is fast connectivity.
     *
     * @param context the Context.
     * @return true if we have "fast" connectivity, false otherwise.
     */
    public static boolean isConnectedFast(Context context) {
        boolean isConnectedFast = false;
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            NetworkInfo[] networkInfos = ConnectivityAndInternetAccessCheck.getAllNetworkInfo(context);
            networkInfosloop:
            for (NetworkInfo networkInfo: networkInfos) {
                isConnectedFast = networkInfo != null && networkInfo.isAvailable() && networkInfo.isConnected() && isConnectionFast(networkInfo.getType(), networkInfo.getSubtype());
                if (isConnectedFast) {
                    break networkInfosloop;
                }
            }
        } else {
            throw new UnsupportedOperationException();
        }
        return isConnectedFast;
    }

    /**
     * Check if the connection is fast.
     *
     * @param type the network type.
     * @param subType the network subtype.
     * @return true if the provided type/subtype combination is classified as fast.
     */
    private static boolean isConnectionFast(int type, int subType) {
        if (type == ConnectivityManager.TYPE_WIFI) {
            return true;
        } else if (type == ConnectivityManager.TYPE_MOBILE) {
            switch (subType) {
                case TelephonyManager.NETWORK_TYPE_1xRTT:
                    return false; // ~ 50-100 kbps
                case TelephonyManager.NETWORK_TYPE_CDMA:
                    return false; // ~ 14-64 kbps
                case TelephonyManager.NETWORK_TYPE_EDGE:
                    return false; // ~ 50-100 kbps
                case TelephonyManager.NETWORK_TYPE_EVDO_0:
                    return true; // ~ 400-1000 kbps
                case TelephonyManager.NETWORK_TYPE_EVDO_A:
                    return true; // ~ 600-1400 kbps
                case TelephonyManager.NETWORK_TYPE_GPRS:
                    return false; // ~ 100 kbps
                case TelephonyManager.NETWORK_TYPE_HSDPA:
                    return true; // ~ 2-14 Mbps
                case TelephonyManager.NETWORK_TYPE_HSPA:
                    return true; // ~ 700-1700 kbps
                case TelephonyManager.NETWORK_TYPE_HSUPA:
                    return true; // ~ 1-23 Mbps
                case TelephonyManager.NETWORK_TYPE_UMTS:
                    return true; // ~ 400-7000 kbps
                /*
                 * Above API level 7, make sure to set android:targetSdkVersion
                 * to appropriate level to use these
                 */
                case TelephonyManager.NETWORK_TYPE_EHRPD: // API level 11
                    return true; // ~ 1-2 Mbps
                case TelephonyManager.NETWORK_TYPE_EVDO_B: // API level 9
                    return true; // ~ 5 Mbps
                case TelephonyManager.NETWORK_TYPE_HSPAP: // API level 13
                    return true; // ~ 10-20 Mbps
                case TelephonyManager.NETWORK_TYPE_IDEN: // API level 8
                    return false; // ~25 kbps
                case TelephonyManager.NETWORK_TYPE_LTE: // API level 11
                    return true; // ~ 10+ Mbps
                // Unknown
                case TelephonyManager.NETWORK_TYPE_UNKNOWN:
                default:
                    return false;
            }
        } else {
            return false;
        }
    }

    public ArrayList < String > getHosts() {
        return hosts;
    }

    public void setHosts(ArrayList < String > hosts) {
        this.hosts = hosts;
    }
    //TODO Debug on devices
    /**
     * Checks that Internet is available by pinging DNS servers.
     */
    private static class InternetConnectionCheckAsync extends AsyncTask < Void, Void, Boolean > {

        private Context context;

        /**
         * Creates an instance of this class
         * @param context The context
         */
        public InternetConnectionCheckAsync(Context context) {
            this.setContext(context);
        }

        /**
         * Cancels the activity if the device is not connected to a network.
         */
        @Override
        protected void onPreExecute() {
            if (!ConnectivityAndInternetAccessCheck.isConnected(getContext())) {
                cancel(true);
            }
        }

        /**
         * Tells whether there is Internet access
         * @param voids The list of arguments
         * @return True if Internet can be accessed
         */
        @Override
        protected Boolean doInBackground(Void...voids) {
            return isConnectedToInternet(getContext());
        }

        @Override
        protected void onPostExecute(Boolean aBoolean) {
            super.onPostExecute(aBoolean);
        }

        /**
         * The context
         */
        public Context getContext() {
            return context;
        }

        public void setContext(Context context) {
            this.context = context;
        }
    } //network calls shouldn't be called from main thread otherwise it will throw //NetworkOnMainThreadException

    /**
     * Tells whether Internet is reachable
     * @return true if Internet is reachable, false otherwise
     * @param context The context
     */
    public static boolean isInternetReachable(Context context) {
        try {
            return new InternetConnectionCheckAsync(context).execute().get();
        } catch (CancellationException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * Tells whether there is Internet connection
     * @param context The context
     * @return @code {true} if there is Internet connection
     */
    private static boolean isConnectedToInternet(Context context) {
        boolean isAvailable = false;
        if (!ConnectivityAndInternetAccessCheck.isConnected(context)) {
            isAvailable = false;
        } else {
            try {
                foreachloop: for (String h: new ConnectivityAndInternetAccessCheck().getHosts()) {
                    if (isHostAvailable(h)) {
                        isAvailable = true;
                        break foreachloop;
                    }
                }
            }
            catch (IOException e) {
                e.printStackTrace();
            }
        }

        return isAvailable;

    }

    /**
     * Checks if the host is available
     * @param hostName
     * @return
     * @throws IOException
     */
    private static boolean isHostAvailable(String hostName) throws IOException {
        try (Socket socket = new Socket()) {
            int port = 80;
            InetSocketAddress socketAddress = new InetSocketAddress(hostName, port);
            socket.connect(socketAddress, 3000);

            return true;
        } catch (UnknownHostException unknownHost) {
            return false;
        }
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.