ตรวจสอบว่าอุปกรณ์ Android มีการเชื่อมต่ออินเทอร์เน็ต


138

ฉันต้องบอกว่าอุปกรณ์ของฉันมีการเชื่อมต่ออินเทอร์เน็ตหรือไม่ ฉันพบคำตอบมากมายเช่น:

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

(นำมาจากการตรวจสอบว่ามีการเชื่อมต่ออินเทอร์เน็ตบน Android )

แต่นี่ไม่ถูกต้องตัวอย่างเช่นถ้าฉันเชื่อมต่อกับเครือข่ายไร้สายที่ไม่มีการเข้าถึงอินเทอร์เน็ตวิธีนี้จะกลับมาจริงหรือไม่ ... มีวิธีที่จะบอกได้หรือไม่ว่าอุปกรณ์นั้นมีการเชื่อมต่ออินเทอร์เน็ต เพื่ออะไร


เฮ้คุณสามารถไปกับ [นี่] [1] เช่นกัน นั่นอาจช่วยได้! [1]: stackoverflow.com/questions/4238921/…
akshay


บล็อกฟังก์ชั่นมีรหัสเลิกทั้งหมดisNetworkConnected Build.VERSION.SDK_INT >= Build.VERSION_CODES.Mการสนทนาเชิงลึกเพิ่มเติมเกี่ยวกับเรื่อง & วิธีแก้ไขสามารถดูได้ที่นี่stackoverflow.com/questions/53532406/…
Basti Vagabond

คำตอบ:


182

คุณพูดถูก รหัสที่คุณให้ไว้จะตรวจสอบเฉพาะในกรณีที่มีการเชื่อมต่อเครือข่าย วิธีที่ดีที่สุดในการตรวจสอบว่ามีการเชื่อมต่ออินเทอร์เน็ตที่ใช้งานอยู่หรือไม่คือลองและเชื่อมต่อกับเซิร์ฟเวอร์ที่รู้จักผ่านทาง 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;
}

แน่นอนคุณสามารถแทนที่http://www.google.comURL สำหรับเซิร์ฟเวอร์อื่น ๆ ที่คุณต้องการเชื่อมต่อหรือเซิร์ฟเวอร์ที่คุณรู้ว่ามีสถานะการออนไลน์ที่ดี

ในฐานะที่เป็นโทนี่โชยังชี้ให้เห็นในความคิดเห็นด้านล่างนี้ตรวจสอบให้แน่ใจว่าคุณไม่ได้เรียกใช้รหัสนี้ในเธรดหลักมิฉะนั้นคุณจะได้รับข้อยกเว้น NetworkOnMainThread (ใน Android 3.0 หรือใหม่กว่า) ใช้ AsyncTask หรือ Runnable แทน

หากคุณต้องการใช้ google.com คุณควรดูการดัดแปลงของ Jeshurun ในคำตอบของเขาเขาแก้ไขรหัสของฉันและทำให้มันมีประสิทธิภาพมากขึ้นเล็กน้อย หากคุณเชื่อมต่อ

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

จากนั้นตรวจสอบรหัสการตอบสนอง 204

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

จากนั้นคุณไม่ต้องเรียกหน้าแรกของ google ทั้งหมดก่อน


9
@varunbhardwaj คุณสามารถใช้เว็บไซต์อื่น (เช่นbaidu.comเมื่อปรับใช้แอปของคุณในจีน) หรือคุณสามารถลองไซต์ที่สองหากเว็บไซต์แรกไม่สามารถเชื่อมต่อได้
THelper

2
ฉัน +1 คำตอบของคุณและรู้ว่าใช้มันในแอปของฉัน แต่มีบางกรณีที่ต้องพึ่งพาอาศัยกันในบางเว็บไซต์และคำถามของฉันยังคงไม่ได้รับคำตอบ anyx วิธีแก้ปัญหาที่ดี thanx
varun bhardwaj

2
@blackcrow ขึ้นอยู่กับระยะเวลาที่คุณ / ผู้ใช้เต็มใจที่จะรอ โดยส่วนตัวฉันถือว่า 1,000ms เป็นขีด จำกัด ต่ำกว่า 6000ms โดยเฉลี่ยและยาว 15000 มิลลิวินาที แต่ถ้าการตรวจสอบทำงานในพื้นหลังและผู้ใช้ไม่รอคุณสามารถใช้การหมดเวลานานขึ้น
THelper

1
@varunbhardwaj ควรมี URI บางอย่างที่คุณสามารถรับได้จากบริการเว็บของคุณ สิ่งแรกที่เราร้องขอเมื่อแอพเริ่มต้นขึ้นคือไฟล์บู๊ตสแตรปที่มีข้อมูลการกำหนดค่าต่าง ๆ ที่ช่วยให้เราสามารถเปลี่ยนพารามิเตอร์พารามิเตอร์ฝั่งเซิร์ฟเวอร์ บางอย่างเช่นนั้นสามารถใช้
Steve

11
สิ่งนี้ควรจะลงบนเธรดพื้นหลัง (ในขณะที่การตรวจสอบConnectivityManagerไม่จำเป็นต้องใช้) มิฉะนั้นสำหรับอุปกรณ์ Android 4.x + คุณจะได้รับการNetworkOnMainThreadยกเว้น
Anthony Chuinard

90

ฉันได้แก้ไขคำตอบของ Thelper เล็กน้อยเพื่อใช้แฮ็คที่รู้จักซึ่ง Android ใช้เพื่อตรวจสอบว่าเครือข่าย WiFi ที่เชื่อมต่อนั้นมีการเข้าถึงอินเทอร์เน็ตหรือไม่ นี่เป็นวิธีที่มีประสิทธิภาพมากกว่าการคว้าหน้าแรกของ Google ทั้งหมด ดูที่นี่และที่นี่สำหรับข้อมูลเพิ่มเติม

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
สวัสดีมันใช้ได้ไหมที่จะใช้วิธีนี้กับแอพปัจจุบัน
Slava Fomin II

สิ่งนี้มีประสิทธิภาพในการใช้งานในแอปปัจจุบันของเราหรือไม่
ประกาศ

5
มันจะมีประสิทธิภาพมากกว่าวิธีในคำตอบข้างต้น การคว้าหน้าแรกของ Google นั้นไม่มีประสิทธิภาพมาก
Jeshurun

1
การตรวจสอบว่าการตอบสนองที่ถูกต้องควรได้รับการปรับปรุงด้วยสิ่งนี้เพราะมันปรับปรุงคำตอบ ผู้ชายทำได้ดีมากขอบคุณ
Hugo

3
คุณอาจต้องการใช้g.cn/generate_204แทนclients3.google.com/generate_204หากคุณต้องการทดสอบการเชื่อมต่อในประเทศจีนเช่นกัน
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;
}

กลับจริงถ้าอินเทอร์เน็ตมีอยู่จริง

ตรวจสอบให้แน่ใจว่าคุณได้รับอนุญาตทั้งสองนี้

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

ถ้า http ใช้งานไม่ได้เนื่องจากความปลอดภัยของ Android ใหม่ที่พวกเขาไม่อนุญาตให้ทำการสื่อสารด้วยข้อความธรรมดาในขณะนี้ สำหรับตอนนี้เพียงผ่านมัน

หุ่นยนต์: usesCleartextTraffic = "true"


นี่เป็นคำตอบที่ดีที่สุดและสมบูรณ์ที่สุด: เป็นวิธีที่สั้นที่สุดในการทำสิ่งต่าง ๆ (ปิงไม่สามารถเข้าถึงเว็บไซต์ทั้งหมด) มันทำงานได้อย่างอิสระจากการเชื่อมต่อที่คุณมีและมันทำงานในกระบวนการชนะเพื่อให้เล่นกับ Android ได้ดี .
MacD

คุณหมายความว่าอะไร ? นี่เป็นอีกตัวอย่างหนึ่งที่ฉันใช้ในการตรวจสอบโครงการในปัจจุบัน
Bilal Shahid

สิ่งที่เขาหมายถึงการโทรนี้จะบล็อก UI และเขาต้องการที่จะทำให้การโทรนี้ในกระทู้?
Amit Hooda

2
สิ่งนี้ไม่ทำงานสำหรับฉัน ... เกิดจาก: android.os.NetworkOnMainThreadException ที่ android.os.StrictMode $ AndroidBlockGuardPolicy.onNetwork (StrictMode.java:1273) ที่ java.net.InetAddress.lookupHostByName (InetAddress.java:431) at
Maryadi Poipo

@HyosokaPoipo คุณไม่ควรเรียกใช้หัวข้อนี้ในเธรดหลัก ใช้เธรดแยกต่างหากหรือ AsyncTask
Pramesh Bajracharya

14

หากคุณกำหนดเป้าหมายไปที่ Lollipop หรือสูงกว่าคุณสามารถใช้คลาส NetworkCapabilities ใหม่เช่น:

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();ต้องใช้ API lvl23 ซึ่งเป็น Marshmallow ไม่ใช่ Lollipop
Saenic

เราควรตรวจสอบความสามารถต่างๆด้วยความสามารถของเครือข่าย (NetworkCapabilities.NET_CAPABILITY_INTERNET)
อเล็กซ์

อเล็กซ์capabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)ดูเหมือนจะทำเคล็ดลับสำหรับฉัน!
rstojano

6

คุณไม่จำเป็นต้องทำการเชื่อมต่อ HTTP แบบเต็มรูปแบบ คุณสามารถลองเปิดการเชื่อมต่อ TCP ไปยังโฮสต์ที่รู้จักและหากประสบความสำเร็จคุณจะมีการเชื่อมต่ออินเทอร์เน็ต

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

จากนั้นตรวจสอบกับ:

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

พอร์ต 80 เป็นพอร์ตที่ปลอดภัยที่จะใช้หรือไม่
ralphgabb

ตราบใดที่มันโฮสต์เซิร์ฟเวอร์ HTTP ก็ควรยอมรับการเชื่อมต่อ TCP บนพอร์ต 80
Xiv

ควรใช้สิ่งนี้ใน AsyncTask หรือเพียงแค่เรียกในเมธอด onCreate ของ MainActivity เช่นกัน?
Alexio

@ ทุกอย่างที่เกี่ยวข้องกับเครือข่ายไม่ควรทำงานบน main / ui-thread ใช่แล้วสิ่งนี้ควรใช้ภายในAsyncTask
winklerrr

6

จากคำตอบที่ได้รับการยอมรับฉันได้สร้างคลาสนี้ด้วยผู้ฟังเพื่อให้คุณสามารถใช้มันในเธรดหลัก:

ก่อน : คลาส InterntCheck ซึ่งตรวจสอบการเชื่อมต่ออินเทอร์เน็ตในพื้นหลังแล้วเรียกเมธอด listener พร้อมผลลัพธ์

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

}

ที่สอง : ยกตัวอย่างอินสแตนซ์ของคลาสในเธรดหลักและรอการตอบกลับ (ถ้าคุณได้ทำงานกับ Firebase api สำหรับ android ก่อนหน้านี้คุณควรคุ้นเคยกับ!)

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

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

ขณะนี้อยู่ในวิธีการที่สมบูรณ์แบบคุณจะได้รับว่าอุปกรณ์นั้นเชื่อมต่อกับอินเทอร์เน็ตหรือไม่


3

ลองอันนี้

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

คุณจะต้องเพิ่มสิทธิ์ต่อไปนี้ในไฟล์ Manifest ของคุณ:

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

จากนั้นโทรเช่นนั้น:

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

ตรวจสอบโพสต์นี้stackoverflow.com/questions/36233507/…
Milan Gajera

เกย์นี้ใช้ลองจับดังนั้นข้อผิดพลาดจะไม่ปรากฏโปรดเพิ่มสิทธิ์อินเทอร์เน็ตก่อนจากนั้นลองใช้ มันทำงานได้ดี
Attaullah

ให้ฉันบอกคุณว่าฉันเรียกวิธีนี้ในกิจกรรมของฉันได้อย่างไร
มิลาน Gajera

ฉันลองคุณโพสต์และฉันได้รับข้อผิดพลาดซึ่งฉันโพสต์ข้อผิดพลาดในบล็อกของฉัน
มิลาน Gajera


1

คุณสามารถทำได้โดยใช้ConnectivityManagerAPI สำหรับ Android อนุญาตให้คุณตรวจสอบว่าคุณเชื่อมต่อกับอินเทอร์เน็ตและประเภทการเชื่อมต่ออินเทอร์เน็ตที่คุณเชื่อมต่ออยู่หรือไม่ โดยทั่วไปวัดหรือไม่วัด

เพื่อตรวจสอบการเชื่อมต่ออินเทอร์เน็ต

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

ลิงค์เอกสาร: https://developer.android.com/training/monitoring-device-state/connectivity-status-type


คุณจะตรวจสอบว่าข้อมูลมือถือหมดได้อย่างไร สิ่งนี้จะคืนความเป็นจริงแม้ว่าจะมีการเชื่อมต่อข้อมูลมือถือและไม่มียอดคงเหลือของข้อมูลในบัญชี
user2672052

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

หวังว่ารหัสข้างต้นจะช่วยคุณได้เช่นกันโปรดตรวจสอบให้แน่ใจว่าคุณได้รับอนุญาตจากอินเทอร์เน็ตในแอปของคุณ


0

วิธีล่าสุดในการทำเช่นนั้นจากเอกสารประกอบคือการใช้ConnectivityManagerเพื่อสอบถามเครือข่ายที่ใช้งานอยู่และพิจารณาว่ามีการเชื่อมต่ออินเทอร์เน็ตหรือไม่

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

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

เพิ่มสิทธิ์ทั้งสองนี้ลงในไฟล์ AndroidManifest.xml ของคุณ:

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

1
ไม่ทำงาน :( @Buda Gavril บอกว่าถ้าฉันเชื่อมต่อกับเครือข่ายไร้สายที่ไม่มีการเข้าถึงอินเทอร์เน็ตวิธีนี้จะยังคงกลับมาจริงทดสอบ Xiaomi 4, Android 6.0.1
DysaniazzZ

0

ตรวจสอบประเภท wifi ในเครื่องมือจัดการการเชื่อมต่อ:

   //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);

เอกสารประกอบ Android อธิบาย 'TYPE_WIFI' ว่าเป็น 'การเชื่อมต่อข้อมูล WIFI อุปกรณ์อาจรองรับมากกว่าหนึ่งรายการ '


0

ทางออกที่ดีในการตรวจสอบว่าเครือข่ายที่ใช้งานมีการเชื่อมต่ออินเทอร์เน็ตหรือไม่:

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

คุณสามารถใช้ 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

    }

ตรวจสอบสิ่งนี้และสิ่งนี้


0

ใช้คลาสต่อไปนี้อัปเดตเป็นระดับ API สุดท้าย: 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;
        }
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.