การเชื่อมต่อเครือข่าย / การเข้าถึงอินเทอร์เน็ต
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 */}
if(Runtime.getRuntime().exec("/system/bin/ping -c 1 8.8.8.8").waitFor()==0) ...
กัน ดูคำตอบของฉันสำหรับการใช้งานที่ดีกว่านี้ Btw คำตอบที่ยอมรับได้ (และอื่น ๆ อีกมากมายที่นี่) เพียงตรวจสอบการเชื่อมต่อเครือข่ายไม่ใช่อินเทอร์เน็ต