我得到了一个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 boolean isNetworkAvailable(Context context) {
    boolean flag = checkNetworkAvailable(context);

    if (!flag) {
        Log.d("", "No network available!");
    } 
    return flag;
}


private static boolean checkNetworkAvailable(Context context) {
    ConnectivityManager connectivityManager
            = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
    return activeNetworkInfo != null;
}

Android提供了ConnectivityManager类来了解互联网连接状态。下面的方法将是非常有用的,以了解互联网连接状态。

首先在AndroidManifest.xml中添加INTERNET和ACCESS_NETWORK_STATE权限

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

然后使用下面的方法检查设备是否连接到互联网。如果设备已连接到互联网,此方法将返回true。

public boolean isInternetAvailable(Context context) {
    ConnectivityManager connectivityManager = (ConnectivityManager) 
    context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo activeNetwork = connectivityManager.getActiveNetworkInfo();
    return activeNetwork != null
            && activeNetwork.isConnectedOrConnecting();
}

参考链接:—http://www.androidtutorialshub.com/android-check-internet-connection-status/

如果您想在连接丢失时显示警报。你可以使用下面的方法。

此方法用于一次检查连接。首先,你必须在你的类中创建这个。

private boolean isNetworkConnected() {
        ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
        if(!(cm.getActiveNetworkInfo() != null && cm.getActiveNetworkInfo().isConnected())){
            showNetworkDialog();
            return false;
        }
        return true;
    }

在类中创建此方法作为连接侦听器。

private void ConnectionCheck(){
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkRequest networkRequest = new NetworkRequest.Builder().build();
            connectivityManager.registerNetworkCallback(networkRequest, new ConnectivityManager.NetworkCallback() {
                @Override
                public void onAvailable(Network network) {
                    super.onAvailable(network);
                    Log.i("Tag", "active connection");
                }

                @Override
                public void onLost(Network network) {
                    super.onLost(network);
                    Log.i("Tag", "losing active connection");
                    isNetworkConnected();
                }
            });
        }
    }

为了显示对话框,你可以创建showDialog()方法。

private void showNetworkDialog(){
    new AlertDialog.Builder(MainActivity.this)
            .setIcon(android.R.drawable.ic_dialog_alert)
            .setTitle("Connection lost?")
            .setMessage("Please check your internet connection!")
            .setCancelable(false)
            .setPositiveButton("Exit", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    finish();
                }
            })
            .setNegativeButton("Retry", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    isNetworkConnected();
                }
            })
            .show();
}

最后你可以在onCreate()方法中调用这个方法。

if(isNetworkConnected()){
            ConnectionCheck();
        }

在清单文件中,你必须提到许可。

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

下面是我使用的方法:

public boolean isNetworkAvailable(final Context context) {
    return ((ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE)).getActiveNetworkInfo() != null;
}

更好的是,检查确保它是“连接”的:

public boolean isNetworkAvailable(final Context context) {
    final ConnectivityManager connectivityManager = ((ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE));
    return connectivityManager.getActiveNetworkInfo() != null && connectivityManager.getActiveNetworkInfo().isConnected();
}

下面是如何使用该方法:

if (isNetworkAvailable(context)) {
    // code here
} else {
    // code
}

需要许可:

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

https://stackoverflow.com/a/16124915/950427

非常重要的是检查我们是否与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" />