我得到了一个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();
}
}
这里是检查互联网连接的最佳方法。这个方法所做的是执行一系列检查“手机是否处于飞行模式,手机是否连接到网络,等等”。如果所有检查都返回true,该方法将从互联网下载一个文件,并查看内容是否与预期值匹配。
与其他通过ping服务器来检查互联网连接的方法相比,这种方法的好处是:
Android运行时在不同的手机上是不同的-所以你可能并不总是能够执行这些命令,如下所示:为什么ping在一些设备上工作,而不是其他设备?
ping服务器并不总是有效,因为登录页面/重定向在wifi网络上,这可能会给人一种连接的错误印象。
这个答案是用Kotlin写的,并使用Fuel库从互联网上下载一个文件,使用methodfetchUrlAsString,但是任何库都可以被替换,只要你确保你的HTTP请求没有被缓存。可以将showConnectionWarning()和hideConnectionWarning()分别等价于互联网连接状态= false和互联网连接状态= true。
private val networkReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
val activeNetworkInfo = (context?.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager).activeNetworkInfo
if (activeNetworkInfo != null) {
if (activeNetworkInfo.isConnectedOrConnecting) {
//Launches a coroutine to fetch file asynchronously
launch {
try {
//Downloads file from url on the internet - use any library you want here.
val connectionStatus = fetchUrlAsString(<url_for_file_on_internet>)
//check if the contents of the file is as expected
if (connectionStatus == "Connected To Database") {
hideConnectionWarning()
} else {
showConnectionWarning()
}
} catch (e: Exception) {
//Catches an exception - fetchUrlAsString only throws an exception if there is no internet
showConnectionWarning()
}
}
} else {
showConnectionWarning()
}
} else {
showConnectionWarning()
}
}
}
private suspend fun fetchUrlAsString(url: String): String = suspendCoroutine { cont ->
url.httpGet().header(Pair("pragma", "no-cache"), Pair("cache-control", "no-cache")).responseString { _, _, result ->
when (result) {
is Result.Failure -> {
cont.resumeWithException(result.getException())
}
is Result.Success -> {
cont.resume(result.value)
}
}
}
}
您将需要以下权限:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
检查这段代码…这对我很有用:)
public static void isNetworkAvailable(final Handler handler, final int timeout) {
// ask fo message '0' (not connected) or '1' (connected) on 'handler'
// the answer must be send before before within the 'timeout' (in milliseconds)
new Thread() {
private boolean responded = false;
@Override
public void run() {
// set 'responded' to TRUE if is able to connect with google mobile (responds fast)
new Thread() {
@Override
public void run() {
HttpGet requestForTest = new HttpGet("http://m.google.com");
try {
new DefaultHttpClient().execute(requestForTest); // can last...
responded = true;
}
catch (Exception e) {
}
}
}.start();
try {
int waited = 0;
while(!responded && (waited < timeout)) {
sleep(100);
if(!responded ) {
waited += 100;
}
}
}
catch(InterruptedException e) {} // do nothing
finally {
if (!responded) { handler.sendEmptyMessage(0); }
else { handler.sendEmptyMessage(1); }
}
}
}.start();
}
然后,我定义处理程序:
Handler h = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what != 1) { // code if not connected
} else { // code if connected
}
}
};
...并启动测试:
isNetworkAvailable(h,2000); // get the answser within 2000 ms
移动设备上的一个重要用例是确保存在实际连接。当移动用户使用“专属门户”进入Wifi网络时,这是一个常见的问题,他们需要在其中登录。我在后台使用这个阻塞功能来确保连接存在。
/*
* Not Thread safe. Blocking thread. Returns true if it
* can connect to URL, false and exception is logged.
*/
public boolean checkConnectionHttps(String url){
boolean responded = false;
HttpGet requestTest = new HttpGet(url);
HttpParams params = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(params, 3000);
HttpConnectionParams.setSoTimeout(params, 5000);
DefaultHttpClient client = new DefaultHttpClient(params);
try {
client.execute(requestTest);
responded = true;
} catch (ClientProtocolException e) {
Log.w(MainActivity.TAG,"Unable to connect to " + url + " " + e.toString());
} catch (IOException e) {
Log.w(MainActivity.TAG,"Unable to connect to " + url + " " + e.toString());
e.printStackTrace();
}
return responded;
}
我做了这个代码,它是最简单的,它只是一个布尔值。
通过询问if(isOnline()){
如果存在连接,并且可以连接到页面,则会得到状态代码200(稳定连接)。
确保添加正确的INTERNET和ACCESS_NETWORK_STATE权限。
public boolean isOnline() {
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = cm.getActiveNetworkInfo();
if (netInfo != null && netInfo.isConnected()) {
try {
URL url = new URL("http://www.google.com");
HttpURLConnection urlc = (HttpURLConnection) url.openConnection();
urlc.setConnectTimeout(3000);
urlc.connect();
if (urlc.getResponseCode() == 200) {
return new Boolean(true);
}
} catch (MalformedURLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return false;
}