我有一个AsyncTask应该检查对主机名的网络访问。但是doInBackground()永远不会超时。有人有线索吗?
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(); } }
isConnectedOrConnecting()
// 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 等),如果没有可用的互联网,它会阻塞一段时间。
-
// 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)。
ScheduledExecutorService
是的,非常快;-)
据我所知,但请告诉我,我将编辑我的答案。
Google DNS(例如8.8.8.8)是世界上最大的公共 DNS。截至 2018 年,它每天处理超过一万亿个查询 [ 1 ]。我们只是说,您的应用程序可能不会成为今天的热门话题。
8.8.8.8
<uses-permission android:name="android.permission.INTERNET" />
只是上网 - 惊喜^^(顺便说一句,你有没有想过,这里建议的一些方法甚至可以在没有这个许可的情况下远程连接互联网?)
听
RxJava/RxAndroid
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 */}
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已弃用,应将其替换为您的应用程序的线程调度、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 */ });