Kết nối mạng / truy cập Internet
isConnectedOrConnecting()
(được sử dụng trong hầu hết các câu trả lời) kiểm tra mọi kết nối mạng
- Để biết liệu có bất kỳ mạng nào trong số đó có truy cập internet hay không, hãy sử dụng một trong các cách sau
A) Ping một máy chủ (dễ dàng)
// 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;
}
+
có thể chạy trên luồng chính
-
không hoạt động trên một số thiết bị cũ (Galays S3, v.v.), nó sẽ chặn một lúc nếu không có internet.
B) Kết nối với một Ổ cắm trên Internet (nâng cao)
// 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; }
}
+
rất nhanh (dù bằng cách nào), hoạt động trên tất cả các thiết bị, rất đáng tin cậy
-
không thể chạy trên luồng UI
Điều này hoạt động rất đáng tin cậy, trên mọi thiết bị, và rất nhanh. Nó cần phải chạy trong một nhiệm vụ riêng biệt (ví dụ ScheduledExecutorService
hoặc AsyncTask
).
Câu hỏi có thể
Có thực sự đủ nhanh?
Vâng, rất nhanh ;-)
Không có cách nào đáng tin cậy để kiểm tra internet, ngoài việc kiểm tra một cái gì đó trên internet?
Không xa như tôi biết, nhưng hãy cho tôi biết, và tôi sẽ chỉnh sửa câu trả lời của mình.
Nếu DNS bị sập thì sao?
Google DNS (ví dụ 8.8.8.8
) là DNS công cộng lớn nhất trên thế giới. Tính đến năm 2013, nó đã phục vụ 130 tỷ yêu cầu mỗi ngày. Hãy nói rằng, ứng dụng của bạn có thể không phải là cuộc nói chuyện trong ngày.
Những quyền nào được yêu cầu?
<uses-permission android:name="android.permission.INTERNET" />
Chỉ cần truy cập internet - thật bất ngờ ^^ (Btw bạn đã bao giờ nghĩ đến, làm thế nào một số phương pháp được đề xuất ở đây thậm chí có thể có một keo dán từ xa về truy cập internet, mà không có sự cho phép này?)
Thêm: AsyncTask
Ví dụ một lần
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 */ });
Thêm: RxJava/RxAndroid
Ví dụ một lần bắn (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) ...
. Xem câu trả lời của tôi để thực hiện tốt hơn về điều này. Btw câu trả lời được chấp nhận (và nhiều người khác ở đây) chỉ cần kiểm tra kết nối mạng chứ không phải internet.