我得到了一个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();
    }   
}

当前回答

在我目前所见过的所有方法中,最短、最干净的方法应该是:

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

PS:这不会ping任何主机,它只是检查连接状态,所以如果你的路由器没有互联网连接,而你的设备连接到它,这个方法将返回true,尽管你没有互联网。 对于实际的测试,我建议执行一个HttpHead请求(例如到www.google.com)并检查状态,如果它是200 OK,一切正常,并且您的设备有互联网连接。

其他回答

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

以下是您需要的许可:

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
 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;
}

这个线程中的大多数答案只检查是否有可用的连接,但不检查该连接是否工作,其他答案不是设备范围,我的解决方案应该在每个设备上工作。

你可以在启动应用程序之前在你的主要活动中删除我的代码,它会快速确定是否有实际的互联网连接,如果有对话框将立即删除,应用程序将被启动,如果没有警报会弹出说应用程序需要互联网连接才能工作。

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();

下面是我用于可达性检查的Kotlin版本,

芬兰湾的科特林MyReachability

object MyReachability {

    private val REACHABILITY_SERVER = "http://google.com" // can be any URL you want

    private fun hasNetworkAvailable(context: Context): Boolean {
        val service = Context.CONNECTIVITY_SERVICE
        val manager = context.getSystemService(service) as ConnectivityManager?
        val network = manager?.activeNetworkInfo
        Log.d(classTag, "hasNetworkAvailable: ${(network != null)}")
        return (network != null)
    }

    fun hasInternetConnected(context: Context): Boolean {
        if (hasNetworkAvailable(context)) {
            try {
                val connection = URL(REACHABILITY_SERVER).openConnection() as HttpURLConnection
                connection.setRequestProperty("User-Agent", "Test")
                connection.setRequestProperty("Connection", "close")
                connection.connectTimeout = 1500
                connection.connect()
                Log.d(classTag, "hasInternetConnected: ${(connection.responseCode == 200)}")
                return (connection.responseCode == 200)
            } catch (e: IOException) {
                Log.e(classTag, "Error checking internet connection", e)
            }
        } else {
            Log.w(classTag, "No network available!")
        }
        Log.d(classTag, "hasInternetConnected: false")
        return false
    }
}

您甚至可以根据策略和限制将REACHABILITY_SERVER作为参数传递,例如,当您在中国时,您可以检查https://baidu.com而不是https://google.com。

调用示例中,

val webLoaderThread = Thread {
   if (MyReachability.hasInternetConnected(this)){
       runOnUiThread {
           //mWebView.loadUrl(LANDING_SERVER) // connected
       }
   } else {
       runOnUiThread {
           //showDialogNoNetwork() // not connected
       }
   }
}
webLoaderThread.start()

安卓系统权限

不要忘记将以下权限添加到你的AndroidManifest.xml中

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

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

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

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" />