จะตรวจสอบการเชื่อมต่ออินเทอร์เน็ตบน Android ได้อย่างไร? InetAddress ไม่เคยหมดเวลา


657

ฉันได้AsyncTaskที่ควรจะตรวจสอบการเข้าถึงเครือข่ายเพื่อชื่อโฮสต์ แต่doInBackground()ไม่หมดเวลา ใครมีเงื่อนงำ?

public class HostAvailabilityTask extends AsyncTask<String, Void, Boolean> {

    private Main main;

    public HostAvailabilityTask(Main main) {
        this.main = main;
    }

    protected Boolean doInBackground(String... params) {
        Main.Log("doInBackground() isHostAvailable():"+params[0]);

        try {
            return InetAddress.getByName(params[0]).isReachable(30); 
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return false;       
    }

    protected void onPostExecute(Boolean... result) {
        Main.Log("onPostExecute()");

        if(result[0] == false) {
            main.setContentView(R.layout.splash);
            return;
        }

        main.continueAfterHostCheck();
    }   
}

5
หากต้องการตรวจสอบการเชื่อมต่ออินเทอร์เน็ตอาจเป็นวิธีที่เชื่อถือได้มากที่สุดคือการ ping เซิร์ฟเวอร์ชื่อหลักหนึ่งตัวซึ่งสามารถทำได้ด้วยเช่นif(Runtime.getRuntime().exec("/system/bin/ping -c 1 8.8.8.8").waitFor()==0) ...กัน ดูคำตอบของฉันสำหรับการใช้งานที่ดีกว่านี้ Btw คำตอบที่ยอมรับได้ (และอื่น ๆ อีกมากมายที่นี่) เพียงตรวจสอบการเชื่อมต่อเครือข่ายไม่ใช่อินเทอร์เน็ต
Levite


4
อย่าใช้วิธีการ ping ใช้การตรวจสอบ HTTP แทน ICMP ถูกปิดกั้นในบางเครือข่ายดังนั้น ping จะไม่ทำงาน เช่นมันทำงานได้อย่างสมบูรณ์บน wifi ที่บ้านของฉัน แต่มันไม่ได้เมื่อฉันใช้ข้อมูลมือถือในเครือข่ายของ Vodafone (ในฮังการี) หรือรวม 2 วิธีเป็นทางเลือก แต่ต้องระวังเพราะ waitFor () จะรอประมาณ 20 วินาทีแม้ว่าจะใช้ -w หรือ -W ก็ตาม
TamásBolvári

ลองใช้งานได้ที่: stackoverflow.com/a/39766506/3806413
0xAliHn

@ TamásBolvári: ดีกว่าที่จะจัดการกับมันที่เลเยอร์ TCP สิ่งที่ควรทำให้คุณใกล้เคียงกับความเร็วของ ICMP พร้อมความน่าเชื่อถือของการร้องขอ HTTP ฉันแก้ไข "คำตอบ ping" ตามนั้น
Levite

คำตอบ:


554

การเชื่อมต่อเครือข่าย / การเข้าถึงอินเทอร์เน็ต

  • isConnectedOrConnecting()(ใช้ในคำตอบส่วนใหญ่) ตรวจสอบการเชื่อมต่อเครือข่ายใด ๆ
  • หากต้องการทราบว่าเครือข่ายใดมีการเชื่อมต่ออินเทอร์เน็ตหรือไม่ให้ใช้อย่างใดอย่างหนึ่งต่อไปนี้

A) Ping a Server (ง่าย)

// ICMP 
public boolean isOnline() {
    Runtime runtime = Runtime.getRuntime();
    try {
        Process ipProcess = runtime.exec("/system/bin/ping -c 1 8.8.8.8");
        int     exitValue = ipProcess.waitFor();
        return (exitValue == 0);
    }
    catch (IOException e)          { e.printStackTrace(); }
    catch (InterruptedException e) { e.printStackTrace(); }

    return false;
}

+ สามารถเรียกใช้บนเธรดหลัก

- ใช้งานไม่ได้กับอุปกรณ์เก่าบางรุ่น (Galays S3 และอื่น ๆ ) มันจะบล็อกในขณะที่หากไม่มีอินเทอร์เน็ตให้ใช้

B) เชื่อมต่อกับซ็อกเก็ตบนอินเทอร์เน็ต (ขั้นสูง)

// TCP/HTTP/DNS (depending on the port, 53=DNS, 80=HTTP, etc.)
public boolean isOnline() {
    try {
        int timeoutMs = 1500;
        Socket sock = new Socket();
        SocketAddress sockaddr = new InetSocketAddress("8.8.8.8", 53);

        sock.connect(sockaddr, timeoutMs);
        sock.close();

        return true;
    } catch (IOException e) { return false; }
}

+เร็วมาก (ทั้งสองทาง) ทำงานบนอุปกรณ์ทั้งหมดเชื่อถือได้มาก

- ไม่สามารถทำงานบนเธรด UI

วิธีนี้ใช้งานได้อย่างน่าเชื่อถือในทุกอุปกรณ์และรวดเร็วมาก มันต้องทำงานในภารกิจที่แยกต่างหากแม้ว่า (เช่นScheduledExecutorServiceหรือAsyncTask)

คำถามที่เป็นไปได้

  • มันเร็วพอหรือไม่

    ใช่เร็วมาก ;-)

  • ไม่มีวิธีที่เชื่อถือได้ในการตรวจสอบอินเทอร์เน็ตนอกเหนือจากการทดสอบบางอย่างบนอินเทอร์เน็ตหรือไม่?

    ไม่ไกลเท่าที่ฉันรู้ แต่ให้ฉันรู้และฉันจะแก้ไขคำตอบของฉัน

  • เกิดอะไรขึ้นถ้า DNS ไม่ทำงาน

    Google DNS (เช่น8.8.8.8) เป็น DNS สาธารณะที่ใหญ่ที่สุดในโลก ในปี 2013 มีการให้บริการ 130,000 คำขอต่อวัน สมมุติว่าแอปของคุณอาจไม่ใช่คำพูดประจำวัน

  • ต้องการสิทธิ์ใดบ้าง

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

    เพียงแค่เข้าถึงอินเทอร์เน็ต - แปลกใจ ^^ (Btw คุณเคยคิดวิธีการบางอย่างของวิธีการที่แนะนำที่นี่อาจมีกาวระยะไกลเกี่ยวกับการเข้าถึงอินเทอร์เน็ตโดยไม่ได้รับอนุญาตนี้?)

 

พิเศษ: AsyncTaskตัวอย่างหนึ่งนัด

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

    private Consumer mConsumer;
    public  interface Consumer { void accept(Boolean internet); }

    public  InternetCheck(Consumer consumer) { mConsumer = consumer; execute(); }

    @Override protected Boolean doInBackground(Void... voids) { try {
        Socket sock = new Socket();
        sock.connect(new InetSocketAddress("8.8.8.8", 53), 1500);
        sock.close();
        return true;
    } catch (IOException e) { return false; } }

    @Override protected void onPostExecute(Boolean internet) { mConsumer.accept(internet); }
}

///////////////////////////////////////////////////////////////////////////////////
// Usage

    new InternetCheck(internet -> { /* do something with boolean response */ });

พิเศษ: RxJava/RxAndroidตัวอย่างOne-shot (Kotlin)

fun hasInternetConnection(): Single<Boolean> {
  return Single.fromCallable {
    try {
      // Connect to Google DNS to check for connection
      val timeoutMs = 1500
      val socket = Socket()
      val socketAddress = InetSocketAddress("8.8.8.8", 53)

      socket.connect(socketAddress, timeoutMs)
      socket.close()

      true
    } catch (e: IOException) {
      false
    }
  }
  .subscribeOn(Schedulers.io())
  .observeOn(AndroidSchedulers.mainThread())
}

///////////////////////////////////////////////////////////////////////////////////
    // Usage

    hasInternetConnection().subscribe { hasInternet -> /* do something */}

22
นี่เป็นรหัสที่ยอดเยี่ยมมาก! ฉันพบว่ามันมีประโยชน์มากในอุปกรณ์ที่ใช้บัตรเติมเงิน! เมื่อเงินหมดพวกเขาก็มีบริการอินเทอร์เน็ต แต่ไม่มีอินเทอร์เน็ต ดังนั้นเพียงแค่ตรวจสอบการเชื่อมต่อจะไม่ทำ ขอบคุณ!
Blejzer

10
โปรดทราบว่าวิธีการนี้เป็นวิธีการบล็อกดังนั้นคุณไม่ควรดำเนินการใน UI นั้น
Sergii

36
@Levit นี่ควรเป็นคำตอบที่ยอมรับได้ คำตอบข้างต้นเป็นเพียงแค่การตรวจสอบเครือข่าย n ไม่ได้เชื่อมต่ออินเทอร์เน็ต และใช่นี่เร็วมาก ขอบคุณ ดังนั้นโหวตขึ้น
Roon13

9
โซลูชันนี้ใช้ไม่ได้กับอุปกรณ์ทั้งหมด อุปกรณ์บางอย่างส่งคืน 2 เสมอตามที่ @Salmaan ระบุไว้ อุปกรณ์ที่ฉันทดสอบมีการเชื่อมต่ออินเทอร์เน็ตและเป้าหมายการ ping คือเซิร์ฟเวอร์ Google DNS - ซึ่งตอบสนองต่อคำขอ ping ฉันคิดว่าผู้ขายบางรายไม่อนุญาตให้ส่งคำสั่ง ping ตัวอย่างเช่นฉันทดสอบกับแท็บเล็ต Samsung 10.1 (4.3) และโซลูชันไม่ทำงาน เมื่อฉันรันคำสั่ง ping ผ่านยูทิลิตี้บรรทัดคำสั่งฉันได้รับข้อผิดพลาดในการอนุญาต คำสั่งยังไม่ทำงานกับอีมูเลเตอร์ ระวังการใช้วิธีนี้
Eren Yilmaz

9
วิธีการนี้ใช้ไม่ได้กับโทรศัพท์ทุกรุ่น มันล้มเหลวเช่นใน Samsung Galaxy S3 ดูที่นี่: ทำไม ping จึงทำงานกับอุปกรณ์บางอย่างและไม่ใช่อุปกรณ์อื่น
Adil Hussain

1032

หากอุปกรณ์อยู่ในโหมดเครื่องบิน (หรือในสถานการณ์อื่น ๆ ที่ไม่มีเครือข่ายที่ใช้งานได้) cm.getActiveNetworkInfo()จะเป็นnullเช่นนั้นดังนั้นคุณต้องเพิ่มการnullตรวจสอบ

แก้ไข ( โซลูชันของ Eddie ) ด้านล่าง:

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

เพิ่มสิทธิ์ต่อไปนี้ในAndroidManifest.xml:

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

จุดหนึ่งที่มีขนาดเล็กอื่น ๆ ถ้าคุณอย่างต้องมีการเชื่อมต่อเครือข่ายที่จุดที่กำหนดในเวลานั้นมันอาจจะดีกว่าการใช้มากกว่าnetInfo.isConnected() netInfo.isConnectedOrConnectingฉันเดาว่านี่ขึ้นอยู่กับแต่ละกรณีการใช้งาน


109
คุณยังควรและจำเป็นต้องตรวจสอบข้อยกเว้นการหมดเวลา http เนื่องจากอาจมีสถานการณ์เมื่อเครือข่ายเชื่อมต่อ แต่จะไม่มีการเชื่อมต่ออินเทอร์เน็ตจริงเนื่องจากวิธีเดียวในการเข้าถึงผ่านเช่น VPN - วิธีนี้คุณมีสำหรับ เช่นการเชื่อมต่อ Wi-Fi แต่ไม่มีการรับส่งข้อมูลทางอินเทอร์เน็ตที่แท้จริง สถานการณ์อื่นคือเซิร์ฟเวอร์แฮงเอาท์ เหล่านี้เป็น 2 ประเด็นที่ฉันใช้เมื่อเร็ว ๆ นี้และตัวจัดการการเชื่อมต่อจะไม่ช่วย
เที่ยงคืน

21
ฉันเห็นด้วยกับเที่ยงคืนและ Pintu คำตอบนี้ไม่ควรเป็นคำตอบที่ยอมรับได้ไม่มีอะไรเกี่ยวข้องกับการตรวจสอบว่าคุณอยู่บนอินเทอร์เน็ตหรือไม่ ตัวอย่างเช่นหากโทรศัพท์เชื่อมต่อกับเครือข่าย WiFi ที่มีพอร์ทัลเป็นเชลยเช่นที่โรงแรมฟังก์ชั่นนี้จะกลับมาจริงอย่างไม่ถูกต้อง คำตอบที่ถูกต้องคือการ ping เซิร์ฟเวอร์บนอินเทอร์เน็ตสาธารณะ
miguel

9
เมื่อไม่มีอินเทอร์เน็ตที่ใช้งานได้สำหรับเราเตอร์ของฉันถ้าฉันเชื่อมต่อกับเราเตอร์ผ่าน wifi รหัสด้านบนจะกลับมาจริง แต่มันไม่ควรจะใช่มั้ย คุณช่วยฉันได้ไหม
MoHaN K RaJ

5
ฉันต้องเพิ่มบริบทในcontext.getSystemServiceหรือไม่ทำงาน ฉันได้รับเบาะแสของฉันที่นี่androidhive.info/2012/07/…
Francisco Corrales Morales

1
เป็นวิธีที่ดีในการตรวจสอบความพร้อมของเครือข่าย แต่จะตรวจสอบการเชื่อมต่ออินเทอร์เน็ตได้อย่างไร
TamásBolvári

296

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

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

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

นอกจากนี้คุณยังสามารถใช้requestRouteToHostหากคุณมีโฮสต์ชื่อและประเภทการเชื่อมต่อ (WiFi / มือถือ) ในใจ

คุณจะต้อง:

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

ในรายการ Android ของคุณ


82
จะเป็นการดีกว่าถ้าทำการตรวจสอบแบบ null ที่ระดับ cm.getActiveNetworkInfo () จะส่งค่า null หากไม่มีเครือข่ายที่ใช้งานอยู่
ซามูเอล

ดูstackoverflow.com/a/11691676/1979773สำหรับการแปลที่ลึกซึ้งยิ่งขึ้นเกี่ยวกับ requestRouteToHost ()
Spartako

ฉันต้องเพิ่มบริบทในcontext.getSystemServiceหรือไม่ทำงาน ฉันได้รับเบาะแสของฉันที่นี่androidhive.info/2012/07/…
Francisco Corrales Morales

9
โซลูชันนี้จะกลับมาจริงหากคุณเชื่อมต่อกับฮอตสปอต WiFi แม้ว่าฮอตสปอตนี้จะไม่มีการเชื่อมต่ออินเทอร์เน็ต
Josh


63

ในการgetActiveNetworkInfo()ไปทำงานคุณต้องเพิ่มสิ่งต่อไปนี้ในรายการ

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

อันนี้ควรจะอยู่ภายใต้คำตอบที่ถูกต้องแน่นอน (เสียเวลามากเกินไปในการหาสิ่งที่นรกผิด)
Indrek Kõue

2
ไม่จำเป็นต้องได้รับอนุญาตจากอินเทอร์เน็ตเพียงแค่ ACCESS_NETWORK_STATE อินเทอร์เน็ตจำเป็นเฉพาะเมื่อคุณทำการเชื่อมต่อไปยังสถานที่ห่างไกลจริง ๆ ไม่ได้สอบถามสถานะของวิทยุของอุปกรณ์
Tom

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

โปรดใช้ความระมัดระวังgetActiveNetworkInfo()ในการเลิกใช้ API ระดับ 29
สแต็ค

46

ตรวจสอบคลาส ConnectivityManager คุณสามารถใช้คลาสนี้เพื่อรับข้อมูลเกี่ยวกับการเชื่อมต่อที่ใช้งานอยู่บนโฮสต์ http://developer.android.com/reference/android/net/ConnectivityManager.html

แก้ไข: คุณสามารถใช้

Context.getSystemService(Context.CONNECTIVITY_SERVICE)
    .getNetworkInfo(ConnectivityManager.TYPE_MOBILE) 

หรือ

Context.getSystemService(Context.CONNECTIVITY_SERVICE)
    .getNetworkInfo(ConnectivityManager.TYPE_WIFI) 

และแยกวิเคราะห์ DetailedState enum ของวัตถุ NetworkInfo ที่ส่งคืน

แก้ไขแก้ไข: หากต้องการทราบว่าคุณสามารถเข้าถึงโฮสต์ได้หรือไม่คุณสามารถใช้

Context.getSystemService(Context.CONNECTIVITY_SERVICE)
    .requestRouteToHost(TYPE_WIFI, int hostAddress)

เห็นได้ชัดว่าฉันใช้ Context.getSystemService (Context.CONNECTIVITY_SERVICE) เป็นพร็อกซีเพื่อพูด

ConnectivityManager cm = Context.getSystemService(Context.CONNECTIVITY_SERVICE);
cm.yourMethodCallHere();

ไม่แน่ใจ แต่ดูเหมือนว่าจะเป็นรหัสเพื่อทดสอบว่าการเชื่อมต่อเครือข่ายแบบใดเปิดอยู่ เช่น im บน WiFi ไม่มีการรับประกันว่าคุณบ้านเราเตอร์ไร้สายเชื่อมต่อกับ internett ... เพื่อตรวจสอบว่าคุณจริง ๆ ต้องทำคำขอไปยัง
เซิร์ฟเวอร์

1
มีข้อผิดพลาดในส่วนแก้ไขแก้ไขฉันจะออกจากการเรียก requestRouteToHost () เรื่องการอ่านคำตอบตอนนี้ :)
Chinmay จิ

requestRouteToHost เลิกใช้แล้ว
Jahaziel

46

ตรวจสอบรหัสนี้ ... มันใช้งานได้สำหรับฉัน :)

public static void isNetworkAvailable(final Handler handler, final int timeout) {
    // ask fo message '0' (not connected) or '1' (connected) on 'handler'
    // the answer must be send before before within the 'timeout' (in milliseconds)

    new Thread() {
        private boolean responded = false;   
        @Override
        public void run() { 
            // set 'responded' to TRUE if is able to connect with google mobile (responds fast) 
            new Thread() {      
                @Override
                public void run() {
                    HttpGet requestForTest = new HttpGet("http://m.google.com");
                    try {
                        new DefaultHttpClient().execute(requestForTest); // can last...
                        responded = true;
                    } 
                    catch (Exception e) {
                    }
                } 
            }.start();

            try {
                int waited = 0;
                while(!responded && (waited < timeout)) {
                    sleep(100);
                    if(!responded ) { 
                        waited += 100;
                    }
                }
            } 
            catch(InterruptedException e) {} // do nothing 
            finally { 
                if (!responded) { handler.sendEmptyMessage(0); } 
                else { handler.sendEmptyMessage(1); }
            }
        }
    }.start();
}

จากนั้นฉันจะกำหนดตัวจัดการ:

Handler h = new Handler() {
    @Override
    public void handleMessage(Message msg) {

        if (msg.what != 1) { // code if not connected

        } else { // code if connected

        }   
    }
};

... และเริ่มการทดสอบ:

isNetworkAvailable(h,2000); // get the answser within 2000 ms

3
Google คืออะไรลง นอกจากนี้ยังต้องได้รับอนุญาตจากอินเทอร์เน็ตซึ่งไม่จำเป็นสำหรับงานที่ได้รับ ในที่สุดข้อมูลนั้นจะใช้ข้อมูล (แม้ว่าจะไม่มีนัยสำคัญ) ดูเหมือนว่านี่จะเป็นกระบอง
Tom

28
@Tom จะยุติธรรมนี่อาจเป็นคำตอบที่ถูกต้องเท่านั้น ตัวอย่างอื่นแสดงเพียงว่าการเชื่อมต่อเครือข่ายพร้อมใช้งานและ / หรือหากมีการเชื่อมต่อกับเครือข่ายนั้น แต่ไม่ตอบคำถามหากเครือข่ายนั้นสามารถทำการเชื่อมต่อระยะไกลได้ (เช่นไปยังเว็บไซต์) ดังนั้นนี่คือคำตอบผู้โพสต์ Q และคำตอบอื่น ๆ ไม่ได้
slinden77

2
@dmmh ใช่มันน่าเสียดายจริง ๆ จากสิ่งที่ฉันเคยเห็นด้วย Android APIs บางที ping ง่ายอาจจะดีกว่า, stackoverflow.com/questions/3905358/... หากคุณกังวลจริง ๆ คุณสามารถรวมรายการของ IP ไปยัง ping ได้เพราะในขณะที่มีโอกาสน้อยมากที่ Google จะลงไปมีโอกาสน้อยกว่าที่ Google, Bing และ Yahoo จะลดลงในวันเดียวกัน . แค่ความคิดของฉัน
ทอม

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

16
ในประเทศจีน Google ถูกบล็อก !!
Anthone

26

พบที่และแก้ไข (!) จากลิงค์นี้:

ในไฟล์ Manifest ของคุณให้เพิ่มอย่างน้อย:

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

คุณอาจได้รับอนุญาตจากอินเทอร์เน็ตหากคุณเข้าใช้งาน ดังนั้นฟังก์ชั่นบูลีนที่อนุญาตให้ทำการทดสอบการเชื่อมต่อคือ:

private boolean checkInternetConnection() {
    ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    // test for connection
    if (cm.getActiveNetworkInfo() != null
            && cm.getActiveNetworkInfo().isAvailable()
            && cm.getActiveNetworkInfo().isConnected()) {
        return true;
    } else {
        Log.v(TAG, "Internet Connection Not Present");
        return false;
    }
}

18

ฉันทำรหัสนี้มันง่ายที่สุดและมันก็เป็นบูลีน โดยถามif(isOnline()){

คุณจะได้รับหากมีการเชื่อมต่อและหากมันสามารถเชื่อมต่อไปยังหน้ารหัสสถานะ 200 (การเชื่อมต่อที่มีเสถียรภาพ)

ตรวจสอบให้แน่ใจเพื่อเพิ่มที่ถูกต้องINTERNETและACCESS_NETWORK_STATEสิทธิ์

public boolean isOnline() {
    ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo netInfo = cm.getActiveNetworkInfo();
    if (netInfo != null && netInfo.isConnected()) {
        try {
            URL url = new URL("http://www.google.com");
            HttpURLConnection urlc = (HttpURLConnection) url.openConnection();
            urlc.setConnectTimeout(3000);
            urlc.connect();
            if (urlc.getResponseCode() == 200) {
                return new Boolean(true);
            }
        } catch (MalformedURLException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    return false;
}

6
บางทีคุณควรแทนที่ 200 ด้วย HttpURLConnection.HTTP_OK
Yash

5
เกิดอะไรขึ้นถ้า Google ไม่ทำงาน
Yauraw Gadav

12

มันใช้งานได้สำหรับฉัน:

วิธีตรวจสอบความพร้อมเครือข่าย:

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

วิธีตรวจสอบการเข้าถึงอินเทอร์เน็ต:

public Boolean isOnline() {
    try {
        Process p1 = java.lang.Runtime.getRuntime().exec("ping -c 1 www.google.com");
        int returnVal = p1.waitFor();
        boolean reachable = (returnVal==0);
        return reachable;
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return false;
}

นี่เป็นทางออกที่ยอดเยี่ยมในการตรวจสอบว่าเซิร์ฟเวอร์หมดประสิทธิภาพดีหรือไม่ ขอบคุณ!
Williew

1
isOnline () ไม่ควรรันบนเธรดหลักเลยราวกับว่ามีสัญญาณไวไฟ แต่ไม่มีอินเทอร์เน็ตมันจะใช้เวลานานเกินไปและบล็อกเธรดหลัก
อับอาย

9

มีมากกว่าหนึ่งวิธี

ครั้งแรกวิธีที่สั้นที่สุด แต่ไม่มีประสิทธิภาพ

การอนุญาตสถานะเครือข่ายจำเป็นเท่านั้น

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

แล้ววิธีนี้

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

        NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
        boolean isConnected = activeNetwork != null &&
                activeNetwork.isConnected();

        return isConnected;

    }

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

ประการที่สองวิธีที่มีประสิทธิภาพ

จำเป็นต้องระบุสถานะเครือข่ายและอินเทอร์เน็ต

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

จากนั้นชั้นนี้

 public class CheckInternetAsyncTask extends AsyncTask<Void, Integer, Boolean> {

        private Context context;

        public CheckInternetAsyncTask(Context context) {
            this.context = context;
        }

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

            ConnectivityManager cm =
                    (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);

            assert cm != null;
            NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
            boolean isConnected = activeNetwork != null &&
                    activeNetwork.isConnected();


            if (isConnected) {
                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();
                    if (urlc.getResponseCode() == 204 &&
                            urlc.getContentLength() == 0)
                        return true;

                } catch (IOException e) {
                    Log.e("TAG", "Error checking internet connection", e);
                    return false;
                }
            } else {
                Log.d("TAG", "No network available!");
                return false;
            }


            return null;
        }

        @Override
        protected void onPostExecute(Boolean result) {
            super.onPostExecute(result);
            Log.d("TAG", "result" + result);

            if(result){
                // do ur code
            }

        }


    }

โทร CheckInternetAsyncTask

new CheckInternetAsyncTask(getApplicationContext()).execute();

คำอธิบายบางอย่าง: -

  • คุณต้องตรวจสอบอินเทอร์เน็ตAsyncTaskก่อนมิฉะนั้นจะสามารถโยนได้android.os.NetworkOnMainThreadExceptionในบางกรณี

  • ConnectivityManager ใช้ในการตรวจสอบการเข้าถึงเครือข่ายถ้าส่งคำขอจริง (ปิง)

  • ส่งคำขอไปยังhttp://clients3.google.com/generate_204URL ที่นี้ที่รู้จักกันดีเป็นที่รู้จักกันเพื่อกลับหน้าว่างที่มีสถานะ HTTP 204 นี้ได้เร็วขึ้นและมีประสิทธิภาพมากขึ้นกว่าhttp://www.google.comอ่านนี้ หากคุณมีเว็บไซต์แนะนำให้ใส่เว็บไซต์ของคุณแทนที่จะเป็น google เฉพาะเมื่อคุณใช้เว็บไซต์ภายในแอป

  • หมดเวลาสามารถเปลี่ยนช่วง (20ms -> 2000ms), 1500ms ใช้กันทั่วไป


2
เป็นคำถามที่ดีมากมันเศร้าที่คุณไม่มีคะแนนมากขึ้น นี่จะต้องเป็นคำตอบที่ถูกต้อง
Jhon Fredy Trujillo Ortega

ฉันใหม่สำหรับ Android แม้ว่าคำตอบนี้จะได้รับการคุ้มครองเป็นอย่างดีและได้รับความสนใจมากขึ้น @ 7569106
Mazen Embaby

1
คำตอบที่ดีที่สุดและสมบูรณ์ขอขอบคุณ หากมีคนสังเกตเห็นเว็บไซต์ว่าเงื่อนไขต้องเป็นเช่นนี้urlc.getResponseCode () == 200และไม่จำเป็นต้องตรวจสอบurlc.getContentLength () == 0
AREF

ตัวเลือกที่สองของคุณเกิดความผิดพลาดฉันไม่รู้ว่าทำไม
nafees ahmed

มันค้างแอปพลิเคชัน
nafees ahmed

8

จากทุกสิ่งที่ฉันได้เห็นจนถึงวิธีที่สั้นและสะอาดที่สุด:

public final static boolean isConnected( Context context )
{   
   final ConnectivityManager connectivityManager = 
         (ConnectivityManager) context.getSystemService( Context.CONNECTIVITY_SERVICE );  
   final NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();    
   return networkInfo != null && networkInfo.isConnected();
}

PS: นี่ไม่ได้ ping โฮสต์ใด ๆ เพียงตรวจสอบการเชื่อมต่อสถานะดังนั้นถ้าเราเตอร์ของคุณไม่มีการเชื่อมต่ออินเทอร์เน็ตและอุปกรณ์ของคุณเชื่อมต่อกับมันวิธีนี้จะกลับมาจริงแม้ว่าคุณจะไม่มีอินเทอร์เน็ต
สำหรับการทดสอบจริงฉันขอแนะนำให้ดำเนินการตามคำขอ HttpHead (เช่น www.google.com)และตรวจสอบสถานะหาก200 OKทุกอย่างเรียบร้อยและอุปกรณ์ของคุณมีการเชื่อมต่ออินเทอร์เน็ต


ฉันต้องการที่จะวางวิธีนี้ในระดับโลกดังนั้นฉันจึงต้องใช้รุ่นนี้เพื่อให้ฉันสามารถผ่านบริบทจากกิจกรรมที่ฉันเรียกมันจาก ขอบคุณ!
RyanG

8

นี่คือวิธีที่ฉันใช้:

public boolean isNetworkAvailable(final Context context) {
    return ((ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE)).getActiveNetworkInfo() != null;
}

ยิ่งกว่านั้นให้ตรวจสอบเพื่อให้แน่ใจว่าเป็น "เชื่อมต่อ" แล้ว:

public boolean isNetworkAvailable(final Context context) {
    final ConnectivityManager connectivityManager = ((ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE));
    return connectivityManager.getActiveNetworkInfo() != null && connectivityManager.getActiveNetworkInfo().isConnected();
}

นี่คือวิธีการใช้วิธีการ:

if (isNetworkAvailable(context)) {
    // code here
} else {
    // code
}

ต้องได้รับอนุญาต:

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

https://stackoverflow.com/a/16124915/950427


7

กรณีการใช้งานที่สำคัญอย่างหนึ่งบนอุปกรณ์พกพาเพื่อให้แน่ใจว่ามีการเชื่อมต่อจริง นี่เป็นปัญหาที่พบบ่อยเมื่อผู้ใช้มือถือเข้าสู่เครือข่าย Wifi ด้วย "Captive Portal" ซึ่งพวกเขาจำเป็นต้องลงชื่อเข้าใช้ฉันใช้ฟังก์ชั่นการบล็อกนี้ในพื้นหลังเพื่อให้แน่ใจว่ามีการเชื่อมต่ออยู่

/*
 * Not Thread safe. Blocking thread. Returns true if it
 * can connect to URL, false and exception is logged.
 */
public boolean checkConnectionHttps(String url){
    boolean responded = false;
    HttpGet requestTest = new HttpGet(url);
    HttpParams params = new BasicHttpParams();
    HttpConnectionParams.setConnectionTimeout(params, 3000);
    HttpConnectionParams.setSoTimeout(params, 5000);
    DefaultHttpClient client = new DefaultHttpClient(params);
    try {
        client.execute(requestTest);
        responded = true;
    } catch (ClientProtocolException e) {
        Log.w(MainActivity.TAG,"Unable to connect to " + url + " " + e.toString());
    } catch (IOException e) {
        Log.w(MainActivity.TAG,"Unable to connect to " + url + " " + e.toString());
        e.printStackTrace();
    }
    return responded;
}

3
+1 สำหรับการตรวจสอบการเชื่อมต่อจากต้นทางถึงปลายทางจริง อย่างไรก็ตามสำหรับสถานการณ์ "Captive Portal" ฉันพบว่าหลายคนจะผ่านการทดสอบด้านบนแม้ว่าคุณจะไม่ได้ลงชื่อเข้าใช้ แต่คุณจะได้รับหน้าเข้าสู่ระบบและการตอบกลับ 200 ครั้งไม่ว่าคุณจะถามอะไรก็ตาม ดังนั้นฉันจึงพยายามที่จะตีหน้าบนโดเมนของตัวเองที่ฉันรู้ว่าไม่มีอยู่และตรวจสอบให้แน่ใจว่าฉันได้รับ 404 อีกวิธีหนึ่งคุณสามารถไปที่หน้าเว็บที่มีอยู่ที่รู้จักอยู่ให้แน่ใจว่าคุณได้รับ 200 และตรวจสอบเนื้อหา จะถูกส่งกลับเพื่อให้แน่ใจว่าเป็นสิ่งที่คุณคาดหวัง
GreyBeardedGeek

6

คุณสามารถวนซ้ำผ่านการเชื่อมต่อเครือข่ายทั้งหมดและตรวจสอบว่ามีการเชื่อมต่อที่ใช้ได้อย่างน้อยหนึ่งรายการ:

public boolean isConnected() {
    boolean connected = false;

    ConnectivityManager cm = 
        (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);

    if (cm != null) {
        NetworkInfo[] netInfo = cm.getAllNetworkInfo();

        for (NetworkInfo ni : netInfo) {
            if ((ni.getTypeName().equalsIgnoreCase("WIFI")
                    || ni.getTypeName().equalsIgnoreCase("MOBILE"))
                    && ni.isConnected() && ni.isAvailable()) {
                connected = true;
            }

        }
    }

    return connected;
}

6

สำหรับฉันมันไม่ใช่วิธีที่ดีในการตรวจสอบสถานะการเชื่อมต่อในคลาสกิจกรรมเพราะ

ConnectivityManager cm =
    (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);

ควรถูกเรียกใช้ที่นั่นหรือคุณต้องกดลงอินสแตนซ์กิจกรรม (บริบท) ของคุณไปยังคลาสตัวจัดการการเชื่อมต่อเพื่อตรวจสอบสถานะการเชื่อมต่อที่นั่นเมื่อไม่มีการเชื่อมต่อที่พร้อมใช้งาน (WiFi, เครือข่าย) ฉันตรวจพบข้อยกเว้น

JSONObject jObj = null;
Boolean responded = false;
HttpGet requestForTest = new HttpGet("http://myserver.com");
try {
    new DefaultHttpClient().execute(requestForTest);
    responded = true;
} catch (UnknownHostException e) {
    jObj = new JSONObject();
    try {
        jObj.put("answer_code", 1);
        jObj.put("answer_text", "No available connection");
    } catch (Exception e1) {}
    return jObj;
} catch (IOException e) {
    e.printStackTrace();
}

ด้วยวิธีนี้ฉันสามารถจัดการกรณีนี้พร้อมกับกรณีอื่น ๆ ในระดับเดียวกัน (เซิร์ฟเวอร์ของฉันตอบกลับด้วยสตริง json เสมอ)


6

มันใช้งานได้สำหรับฉัน ลองดู

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    try {
        URL url = new URL("http://stackoverflow.com/posts/11642475/edit" );
        //URL url = new URL("http://www.nofoundwebsite.com/" );
        executeReq(url);
        Toast.makeText(getApplicationContext(), "Webpage is available!", Toast.LENGTH_SHORT).show();
    }
    catch(Exception e) {
        Toast.makeText(getApplicationContext(), "oops! webpage is not available!", Toast.LENGTH_SHORT).show();
    }
}

private void executeReq(URL urlObject) throws IOException
{
    HttpURLConnection conn = null;
    conn = (HttpURLConnection) urlObject.openConnection();
    conn.setReadTimeout(30000);//milliseconds
    conn.setConnectTimeout(3500);//milliseconds
    conn.setRequestMethod("GET");
    conn.setDoInput(true);

    // Start connect
    conn.connect();
    InputStream response =conn.getInputStream();
    Log.d("Response:", response.toString());
}}

คำตอบนี้ไม่สามารถใช้งานได้ในขณะนี้เนื่องจากเราไม่สามารถเข้าถึงเครือข่ายในเธรดหลักได้ในขณะนี้
正宗白布鞋

1
ฉันหมายถึงจาก API ระดับ 11 สิ่งนี้ไม่ทำงาน เหตุผล: developer.android.com/reference/android/os/... ถ้ามันเหมาะกับคุณก็หมายความว่าคุณกำลังเรียกใช้รหัสนี้บนอุปกรณ์ Android เก่า (ก่อนหน้า GB)
正宗白布鞋

นโยบาย StrictMode.ThreadPolicy = ใหม่ StrictMode.ThreadPolicy.Builder () .permitAll (). build (); StrictMode.setThreadPolicy (นโยบาย); เพิ่มสองบรรทัดนี้สองโปรแกรมของคุณเพื่อหลีกเลี่ยงข้อยกเว้นเธรดหลักของเครือข่าย
selva_pollachi

ตกลงฉันไม่ควรพูดว่าสิ่งนี้ใช้ไม่ได้ฉันควรจะบอกว่ามันสามารถทำงานได้ (ตามเป้าหมายเวอร์ชั่นเก่าหรือการตั้งค่า Strictmode) แต่ไม่ได้ผล นี่อาจทำให้ ANR ง่าย (ด้วยการกำหนดค่าการหมดเวลาที่สูงมากใน httpurlconnection)
正宗白布鞋

ใช่แล้ว .. คุณถูกต้องเพียงแค่ฉันใส่นี่เพราะมันเป็นวิธีหนึ่ง
selva_pollachi

6

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

public boolean isNetworkAvailable(bool SlowButMoreReliable) {
    bool Result = false; 
    try {
        if(SlowButMoreReliable){
            ConnectivityManager MyConnectivityManager = null;
            MyConnectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);

            NetworkInfo MyNetworkInfo = null;
            MyNetworkInfo = MyConnectivityManager.getActiveNetworkInfo();

            Result = MyNetworkInfo != null && MyNetworkInfo.isConnected();

        } else
        {
            Runtime runtime = Runtime.getRuntime();
            Process ipProcess = runtime.exec("/system/bin/ping -c 1 8.8.8.8");

            int i = ipProcess.waitFor();

            Result = i== 0;

        }

    } catch(Exception ex)
    {
        //Common.Exception(ex); //This method is one you should have that displays exceptions in your log
    }
    return Result;
}

5

ฉันใช้รหัสนี้แทน InetAddress:

    try {

        URL url = new URL("http://"+params[0]);

        HttpURLConnection urlc = (HttpURLConnection) url.openConnection();
        urlc.setRequestProperty("User-Agent", "Android Application:"+Z.APP_VERSION);
        urlc.setRequestProperty("Connection", "close");
        urlc.setConnectTimeout(1000 * 30); // mTimeout is in seconds
        urlc.connect();
        if (urlc.getResponseCode() == 200) {
            Main.Log("getResponseCode == 200");
            return new Boolean(true);
        }
    } catch (MalformedURLException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

มันจะดีถ้าคุณได้ชี้แจงว่า IOException หมายถึงไม่มีการเชื่อมต่ออินเทอร์เน็ตและเชื่อถือได้อย่างไร
Milad.Nozari

5

ไม่ซับซ้อนในการตรวจสอบสถานะการเชื่อมต่อเครือข่าย Android / อินเทอร์เน็ต DetectConnectionชั้นด้านล่างจะช่วยให้คุณตรวจสอบสถานะนี้:

import android.content.Context;
import android.net.ConnectivityManager;

public class DetectConnection {
    public static boolean checkInternetConnection(Context context) {
        ConnectivityManager con_manager = (ConnectivityManager) context
                                .getSystemService(Context.CONNECTIVITY_SERVICE);

        if (con_manager.getActiveNetworkInfo() != null
            && con_manager.getActiveNetworkInfo().isAvailable()
            && con_manager.getActiveNetworkInfo().isConnected()) {
                return true;
        } else {
            return false;
        }
    }
}

สำหรับรายละเอียดเพิ่มเติมไปที่ วิธีตรวจสอบสถานะเครือข่าย Android / การเชื่อมต่ออินเทอร์เน็ต


5

แนวทางที่ดีที่สุด:

public static boolean isOnline() {
    try {
    InetAddress.getByName("google.com").isReachable(3);

    return true;
    } catch (UnknownHostException e){
    return false;
    } catch (IOException e){
    return false;
    }
    }

1
ฉันชอบวิธีการนี้ แต่ฉันต้องชี้ให้เห็นบางสิ่ง isReachable () คืนค่าบูลีนดังนั้นแทนที่จะส่งคืนค่าจริงในส่วนลองคุณสามารถทำได้เช่นบูลีนเชื่อมต่อ = InetAddress.getByName ("google.com"). isReachable (3); จากนั้นเชื่อมต่อกลับ นอกจากนี้ isReacheable throws IOException และ IllegalArgumentException ข้อยกเว้นดังนั้นมันจะเป็นความคิดที่ดีในการแทนที่ UnknownHostException ด้วย IllegalArgumentException และรวมถึง catch ที่สาม: catch (Exception E)
Yash

2
แต่แล้ว isReachable ใช้ ICMP ซึ่งอาจต้องใช้สิทธิ์ root และใช้พอร์ต 7 ซึ่งโดยปกติจะไม่มีบริการที่ทำงานอยู่ในระบบล่าสุด ดังนั้นวิธีที่ดีที่สุดในการตรวจสอบเส้นทางไปยังบริการออนไลน์คือ TCP ปกติ ดังนั้นการลงคะแนน
Yash

5

ต่อไปนี้เป็นรหัสจากUtilsชั้นเรียนของฉัน:

public static boolean isNetworkAvailable(Context context) {
        ConnectivityManager connectivityManager 
              = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
        return activeNetworkInfo != null && activeNetworkInfo.isConnected();
}

5
public class Network {

Context context;

public Network(Context context){
    this.context = context;
}

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

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

}

ในขณะที่คนอื่น ๆ ที่ไม่ได้อ่านปัญหามันไม่ได้แก้ปัญหาเพราะมันไม่ได้ตรวจสอบการเชื่อมต่อกับอินเทอร์เน็ต การเชื่อมต่อกับฮอตสปอต wifi ในพื้นที่จะกลับมาเป็นจริงแม้ว่าฮอตสปอตจะไม่อนุญาตให้คุณผ่านอินเทอร์เน็ต
Pedro Pombeiro

5

คุณสามารถใช้วิธีนี้เพื่อตรวจสอบความพร้อมเครือข่าย -

public static boolean isDeviceOnline(Context context) {
        boolean isConnectionAvail = false;
        try {
            ConnectivityManager cm = (ConnectivityManager) context
                    .getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo netInfo = cm.getActiveNetworkInfo();
            return netInfo.isConnected();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return isConnectionAvail;
    }

5

ฉันใช้วิธีการแก้ปัญหาโดย @Levit และสร้างฟังก์ชันที่จะไม่เรียกใช้คำขอ Http พิเศษ

มันจะแก้ไขข้อผิดพลาด Unable to Resolve Host

public static boolean isInternetAvailable(Context context) {
    ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
    if (activeNetwork == null) return false;

    switch (activeNetwork.getType()) {
        case ConnectivityManager.TYPE_WIFI:
            if ((activeNetwork.getState() == NetworkInfo.State.CONNECTED ||
                    activeNetwork.getState() == NetworkInfo.State.CONNECTING) &&
                    isInternet())
                return true;
            break;
        case ConnectivityManager.TYPE_MOBILE:
            if ((activeNetwork.getState() == NetworkInfo.State.CONNECTED ||
                    activeNetwork.getState() == NetworkInfo.State.CONNECTING) &&
                    isInternet())
                return true;
            break;
        default:
            return false;
    }
    return false;
}

private static boolean isInternet() {

    Runtime runtime = Runtime.getRuntime();
    try {
        Process ipProcess = runtime.exec("/system/bin/ping -c 1 8.8.8.8");
        int exitValue = ipProcess.waitFor();
        Debug.i(exitValue + "");
        return (exitValue == 0);
    } catch (IOException | InterruptedException e) {
        e.printStackTrace();
    }

    return false;
}

ตอนนี้เรียกมันว่า

if (!isInternetAvailable(getActivity())) {
     //Show message
} else {
     //Perfoem the api request
}

4

นี้จะครอบคลุมในเอกสาร Android http://developer.android.com/training/monitoring-device-state/connectivity-monitoring.html


1
แต่วิธีที่อธิบายไว้ไม่มีการตรวจสอบการเชื่อมต่ออินเทอร์เน็ตจริงๆเพียงตรวจสอบว่ามีการเชื่อมต่อหรือไม่ (ไม่ว่าจะมีการเข้าถึงอินเทอร์เน็ตหรือไม่ก็ตาม) ชื่อของเอกสารทางการนั้นทำให้เข้าใจผิดจริงๆ
Tiago

2
การให้คำตอบสำหรับคำถามนั้นดีกว่าการโพสต์ลิงก์ไปยังข้อมูล เกิดอะไรขึ้นถ้าลิงค์ตายไป? เราจะไม่มีคำตอบ
Jose Llausas

4

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

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

NetworkUtils.class

public class NetworkUtils {

    public static final int STATUS_CONNECTED = 0 ;

    public static boolean isInternetAvailable(Context ctx){
        ConnectivityManager cm = (ConnectivityManager)ctx.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
        return activeNetwork != null && activeNetwork.isConnectedOrConnecting();
    }

    public static int isInternetActiveWithPing() {
        try {
            Runtime runtime = Runtime.getRuntime();
            Process process = runtime.exec("/system/bin/ping -c 1 8.8.8.8");
            int exitValue = process.waitFor();
            return exitValue;
        } catch (Exception ex) {
            return -1;
        }
    }

    public static boolean isInternetActiveWithInetAddress() {
        try {
            InetAddress inetAddress = InetAddress.getByName("www.google.com");
            return inetAddress != null && !inetAddress.toString().equals("");
        } catch (Exception ex) {
            return false;
        }
    }

    public static void displayInternetConnectionMessage(Context ctx){
        Toast.makeText(ctx, "Check Internet Connection", Toast.LENGTH_SHORT).show();
    }
}

คุณสามารถตรวจสอบว่ามีการใช้งานอินเทอร์เน็ตโดยใช้รหัสด้านล่าง:

 private void checkInternetConnection() {
        if (NetworkUtils.isInternetAvailable(this)) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    if (NetworkUtils.isInternetActiveWithPing() == NetworkUtils.STATUS_CONNECTED) {
                        performNetworkingOperations();
                    } else {
                        if (NetworkUtils.isInternetActiveWithInetAddress()) {
                            performNetworkingOperations();
                        } else {
                            displayConnectionMessage();
                        }
                    }
                }
            }).start();

        } else {
            displayConnectionMessage();
        }
    }

    private void performNetworkingOperations() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(MainActivity.this, "Internet is Available", Toast.LENGTH_SHORT).show();
            }
        });
    }

    private void displayConnectionMessage() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                NetworkUtils.displayInternetConnectionMessage(MainActivity.this);
            }
        });
    }

ดีกว่าแพ็คเกลียวใน NetworkUtils ของคุณและดังนั้นจึง "บังคับ" นักพัฒนาที่จะไม่ใช้วิธีการที่ผิดพลาดของคุณ
Ewoks

หากต้องการลบเงื่อนไขเพิ่มเติม ถ้า ((NetworkUtils.isInternetActiveWithPing () == NetworkUtils.STATUS_CONNECTED) || NetworkUtils.isInternetActiveWithInetAddress ()} {// ข้อความแสดงข้อผิดพลาด}
Jawad Zeb

4

สำคัญมากในการตรวจสอบว่าเรามีการเชื่อมต่อกับisAvailable ()และถ้าเป็นไปได้ที่จะสร้างการเชื่อมต่อกับisConnected ()

private static ConnectivityManager manager;

public static boolean isOnline(Context context) {
    ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
    return networkInfo != null && networkInfo.isAvailable() && networkInfo.isConnected();
}

และคุณสามารถแยกประเภทของเครือข่ายWiFi ที่ใช้งานอยู่:

public static boolean isConnectedWifi(Context context) {
    ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
    return networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_WIFI;
}

หรือมือถือMóvil :

public static boolean isConnectedMobile(Context context) {
    ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
    return networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_MOBILE;
}

อย่าลืมสิทธิ์:

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

บทสรุปที่ดีเกี่ยวกับองค์ประกอบการเชื่อมต่ออุปกรณ์เพียงแค่ต้องการรวมคำสั่ง try / catch เพื่อหลีกเลี่ยงข้อขัดข้อง ในทำนองเดียวกันเพียงทำการโทร HttpURLC การเชื่อมต่อตามปกติตราบใดที่มีข้อผิดพลาดในการจัดการคุณจะรู้ว่าคุณมีการเชื่อมต่ออินเทอร์เน็ตหรือไม่
rangi

4

Kotlin และ coroutines

ฉันได้วางฟังก์ชั่นในซึ่งมีViewModel viewModelScopeการใช้สิ่งที่สังเกตได้LiveDataฉันแจ้งกิจกรรมเกี่ยวกับการเชื่อมต่อ

ViewModel

 fun checkInternetConnection() {
        viewModelScope.launch {
            withContext(Dispatchers.IO) {
                try {
                    val timeoutMs = 3000
                    val socket = Socket()
                    val socketAddress = InetSocketAddress("8.8.8.8", 53)

                    socket.connect(socketAddress, timeoutMs)
                    socket.close()

                    withContext(Dispatchers.Main) {
                        _connection.value = true
                    }
                }
                catch(ex: IOException) {
                    withContext(Main) {
                        _connection.value = false
                    }
                }
            }
        }
    }
 private val _connection = MutableLiveData<Boolean>()
 val connection: LiveData<Boolean> = _connection

กิจกรรม

 private fun checkInternetConnection() {
     viewModel.connection.observe(this) { hasInternet ->
         if(!hasInternet) {
             //hasn't connection
         }
         else {
            //has connection
         }
     }
  }

3

เพียงแค่สร้างคลาสต่อไปนี้ซึ่งตรวจสอบการเชื่อมต่ออินเทอร์เน็ต:

public class ConnectionStatus {

    private Context _context;

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

    public boolean isConnectionAvailable() {
        ConnectivityManager connectivity = (ConnectivityManager) _context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        if (connectivity != null) {
            NetworkInfo[] info = connectivity.getAllNetworkInfo();
            if (info != null)
                for (int i = 0; i < info.length; i++)
                    if (info[i].getState() == NetworkInfo.State.CONNECTED) {
                        return true;
                    }
        }
        return false;
    }
}

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

วิธีการต่อไปนี้ใน MainActivity แล้วเรียกผลลัพธ์จากวิธีที่อธิบายไว้ก่อนหน้านี้และแจ้งให้ผู้ใช้ดำเนินการตาม:

public void addListenerOnWifiButton() {
        Button btnWifi = (Button)findViewById(R.id.btnWifi);

        iia = new ConnectionStatus(getApplicationContext());

        isConnected = iia.isConnectionAvailable();
        if (!isConnected) {
            btnWifi.setOnClickListener(new View.OnClickListener() {

                @Override
                public void onClick(View v) {
                    startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS));
                    Toast.makeText(getBaseContext(), "Please connect to a hotspot",
                            Toast.LENGTH_SHORT).show();
                }
            });
        }
        else {
            btnWifi.setVisibility(4);
            warning.setText("This app may use your mobile data to update events and get their details.");
        }
    }

ในโค้ดด้านบนหากผลลัพธ์เป็นเท็จ (ดังนั้นจึงไม่มีการเชื่อมต่ออินเทอร์เน็ตผู้ใช้จะถูกนำไปที่แผง Android Wi-Fi ซึ่งเขาได้รับแจ้งให้เชื่อมต่อกับฮอตสปอต Wi-Fi


3

อัปเดต 29/06/2015 หากคุณใช้ Xamarin.Android และต้องการตรวจสอบการเชื่อมต่อคุณสามารถใช้แพ็คเกจ Nuget ที่จะให้ฟังก์ชั่นนี้ในหลายแพลตฟอร์ม ผู้สมัครที่ดีอยู่ที่นี่และที่นี่ [สิ้นสุดการอัพเดท]

คำตอบข้างต้นค่อนข้างดี แต่ทั้งหมดอยู่ใน Java และเกือบทั้งหมดตรวจสอบการเชื่อมต่อ ในกรณีของฉันฉันต้องมีการเชื่อมต่อกับการเชื่อมต่อบางประเภทและฉันกำลังพัฒนาบน Xamarin.Android นอกจากนี้ฉันไม่ผ่านการอ้างอิงไปยังบริบทกิจกรรมของฉันในเลเยอร์ฮาร์ดแวร์ฉันใช้บริบทแอปพลิเคชัน ดังนั้นนี่คือทางออกของฉันในกรณีที่บางคนมาที่นี่ด้วยข้อกำหนดที่คล้ายกัน ฉันยังไม่ได้ทำการทดสอบเต็มรูปแบบ แต่จะอัปเดตคำตอบเมื่อฉันทำการทดสอบเสร็จแล้ว

using Android.App;
using Android.Content;
using Android.Net;

namespace Leopard.Mobile.Hal.Android
{
    public class AndroidNetworkHelper
    {
        public static AndroidNetworkStatus GetWifiConnectivityStatus()
        {
            return GetConnectivityStatus(ConnectivityType.Wifi);
        }

        public static AndroidNetworkStatus GetMobileConnectivityStatus()
        {
            return GetConnectivityStatus(ConnectivityType.Mobile);
        }

        #region Implementation

        private static AndroidNetworkStatus GetConnectivityStatus(ConnectivityType connectivityType)
        {
            var connectivityManager = (ConnectivityManager)Application.Context.GetSystemService(Context.ConnectivityService);
            var wifiNetworkInfo = connectivityManager.GetNetworkInfo(connectivityType);
            var result = GetNetworkStatus(wifiNetworkInfo);
            return result;
        }

        private static AndroidNetworkStatus GetNetworkStatus(NetworkInfo wifiNetworkInfo)
        {
            var result = AndroidNetworkStatus.Unknown;
            if (wifiNetworkInfo != null)
            {
                if (wifiNetworkInfo.IsAvailable && wifiNetworkInfo.IsConnected)
                {
                    result = AndroidNetworkStatus.Connected;
                }
                else
                {
                    result = AndroidNetworkStatus.Disconnected;
                }
            }
            return result;
        } 

        #endregion
    }

    public enum AndroidNetworkStatus
    {
        Connected,
        Disconnected,
        Unknown
    }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.