如何在Android上检查互联网访问?InetAddress 永远不会超时 [英] How to check internet access on Android? InetAddress never times out
问题描述
我有一个 AsyncTask
应该检查对主机名的网络访问.但是 doInBackground()
永远不会超时.有人知道吗?
I got a AsyncTask
that is supposed to check the network access to a host name. But the doInBackground()
is never timed out. Anyone have a clue?
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();
}
}
推荐答案
网络连接/互联网访问
isConnectedOrConnecting()
(用于大多数答案)检查任何网络连接- 要了解这些网络中是否有任何一个可以互联网访问,请使用以下方法之一
isConnectedOrConnecting()
(used in most answers) checks for any network connection- To know whether any of those networks have internet access, use one of the following
Network connection / Internet access
// 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 等)上不起作用,如果没有互联网可用,它会阻塞一段时间.
-
does not work on some old devices (Galays S3, etc.), it blocks a while if no internet is available.
// 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; }
}
+
非常快(无论哪种方式),适用于所有设备,非常可靠
+
very fast (either way), works on all devices, very reliable
-
无法在 UI 线程上运行
-
can't run on the UI thread
这在所有设备上都非常可靠,而且速度非常快.但它需要在单独的任务中运行(例如 ScheduledExecutorService
或 AsyncTask
).
This works very reliably, on every device, and is very fast. It needs to run in a separate task though (e.g. ScheduledExecutorService
or AsyncTask
).
真的够快了吗?
Is it really fast enough?
是的,非常快;-)
除了在互联网上测试一些东西之外,还有没有其他可靠的方法可以检查互联网?
Is there no reliable way to check internet, other than testing something on the internet?
据我所知,但请告诉我,我会编辑我的答案.
如果 DNS 出现故障怎么办?
What if the DNS is down?
Google DNS(例如 8.8.8.8
)是世界上最大的公共 DNS.截至 2018 年,它每天处理超过一万亿次查询 [1].这么说吧,您的应用可能不会成为热门话题.
Google DNS (e.g. 8.8.8.8
) is the largest public DNS in the world. As of 2018 it handled over a trillion queries a day [1]. Let 's just say, your app would probably not be the talk of the day.
需要哪些权限?
<uses-permission android:name="android.permission.INTERNET" />
只是互联网访问 - 惊喜^^(顺便说一句,你有没有想过,这里建议的一些方法如何甚至可以在没有此许可的情况下远程连接互联网访问?)
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 */}
额外:一次性RxJava/RxAndroid
示例(Java)
Extra: One-shot RxJava/RxAndroid
Example (Java)
public static Single<Boolean> hasInternetConnection() {
return Single.fromCallable(() -> {
try {
// Connect to Google DNS to check for connection
int timeoutMs = 1500;
Socket socket = new Socket();
InetSocketAddress socketAddress = new InetSocketAddress("8.8.8.8", 53);
socket.connect(socketAddress, timeoutMs);
socket.close();
return true;
} catch (IOException e) {
return false;
}
}).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());
}
///////////////////////////////////////////////////////////////////////////////////
// Usage
hasInternetConnection().subscribe((hasInternet) -> {
if(hasInternet) {
}else {
}
});
额外:一次性AsyncTask
示例
注意: 这显示了如何执行请求的另一个示例.但是,由于 AsyncTask
已被弃用,它应该被您的应用程序的线程调度、Kotlin Coroutines、Rx、...
Extra: One-shot AsyncTask
Example
Caution: This shows another example of how to do the request. However, since AsyncTask
is deprecated, it should be replaced by your App's thread scheduling, Kotlin Coroutines, Rx, ...
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 */ });
这篇关于如何在Android上检查互联网访问?InetAddress 永远不会超时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!