我得到了一个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();
}
}
芬兰湾的科特林实现
/**
* Function that uses ping, takes server name or ip as argument.
*
* @return [Double.MAX_VALUE] if server is not reachable. Average RTT if the server is reachable.
*
* Success output example
*
* PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
* 64 bytes from 8.8.8.8: icmp_seq=1 ttl=254 time=172 ms
* 64 bytes from 8.8.8.8: icmp_seq=2 ttl=254 time=166 ms
* 64 bytes from 8.8.8.8: icmp_seq=3 ttl=254 time=167 ms
* 64 bytes from 8.8.8.8: icmp_seq=4 ttl=254 time=172 ms
* 64 bytes from 8.8.8.8: icmp_seq=5 ttl=254 time=167 ms
* --- 8.8.8.8 ping statistics ---
* 5 packets transmitted, 5 received, 0% packet loss, time 4011ms
* rtt min/avg/max/mdev = 166.470/169.313/172.322/2.539 ms
* |________________________|
* value to parse using it.split('=')[1].trim().split(' ')[0].trim().split('/')[1].toDouble()
*/
@ExperimentalStdlibApi
fun pingServerAverageRtt(host: String): Double {
var aveRtt: Double = Double.MAX_VALUE
try {
// execute the command on the environment interface, timeout is set as 0.2 to get response faster.
val pingProcess: Process = Runtime.getRuntime().exec("/system/bin/ping -i 0.2 -c 5 $host")
// gets the input stream to get the output of the executed command
val bufferedReader = BufferedReader(InputStreamReader(pingProcess.inputStream))
bufferedReader.forEachLine {
if (it.isNotEmpty() && it.contains("min/avg/max/mdev")) { // when we get to the last line of executed ping command
aveRtt = it.split('=')[1].trim()
.split(' ')[0].trim()
.split('/')[1].toDouble()
}
}
} catch (e: IOException) {
e.printStackTrace()
}
return aveRtt
}
使用的例子
val latency = pingServerAverageRtt(ipString)
if (latency != Double.MAX_VALUE) {
//server reachable
} else {
//server not reachable
}
这个线程中的大多数答案只检查是否有可用的连接,但不检查该连接是否工作,其他答案不是设备范围,我的解决方案应该在每个设备上工作。
你可以在启动应用程序之前在你的主要活动中删除我的代码,它会快速确定是否有实际的互联网连接,如果有对话框将立即删除,应用程序将被启动,如果没有警报会弹出说应用程序需要互联网连接才能工作。
final AlertDialog alertDialog = new AlertDialog.Builder(this).create();
alertDialog.setTitle("Checking Connection");
alertDialog.setMessage("Checking...");
alertDialog.show();
new CountDownTimer(5000, 1000) {
@Override
public void onTick(long millisUntilFinished) {
new Thread(new Runnable() {
public void run() {
try {
URL url = new URL("http://web.mit.edu/");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(5000);
isConnected = connection.getResponseCode() == HttpURLConnection.HTTP_OK;
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
if (isConnected == false){
alertDialog.setMessage("Try " + (5 - millisUntilFinished/1000) + " of 5.");
} else {
alertDialog.dismiss();
}
}
@Override
public void onFinish() {
if (isConnected == false) {
alertDialog.dismiss();
new AlertDialog.Builder(activity)
.setTitle("No Internet")
.setMessage("Please connect to Internet first.")
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// kill the app?
}
})
.setIcon(android.R.drawable.ic_dialog_alert)
.show();
} else {
// Launch the app
}
}
}.start();
非常重要的是检查我们是否与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" />