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

当前回答

我使用这段代码而不是InetAddress:

    try {

        URL url = new URL("http://"+params[0]);

        HttpURLConnection urlc = (HttpURLConnection) url.openConnection();
        urlc.setRequestProperty("User-Agent", "Android Application:"+Z.APP_VERSION);
        urlc.setRequestProperty("Connection", "close");
        urlc.setConnectTimeout(1000 * 30); // mTimeout is in seconds
        urlc.connect();
        if (urlc.getResponseCode() == 200) {
            Main.Log("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();
    }

其他回答

如果设备处于飞行模式(或者假设在没有可用网络的其他情况下),cm.getActiveNetworkInfo()将为空,因此您需要添加一个空检查。

修改(Eddie的解决方案)如下:

public boolean isOnline() {
    ConnectivityManager cm =
        (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo netInfo = cm.getActiveNetworkInfo();
    return netInfo != null && netInfo.isConnectedOrConnecting();
}

在AndroidManifest.xml中添加以下权限:

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

还有一点,如果你在给定的时间点绝对需要一个网络连接,那么使用netInfo.isConnected()而不是netInfo.isConnectedOrConnecting可能会更好。不过,我想这取决于个人用例。

要让getActiveNetworkInfo()工作,您需要向清单中添加以下内容。

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

如果你需要检查网络连接,使用ping到服务器的方法:

public boolean checkIntCON() {
    try {
        Process ipProcess = Runtime.getRuntime().exec("/system/bin/ping -c 1 8.8.8.8");
        return (ipProcess.waitFor() == 0);
    }
    catch (IOException e)          { e.printStackTrace(); }
    catch (InterruptedException e) { e.printStackTrace(); }
    return false;
}

您可以使用端口进行检查

public boolean checkIntCON() {
    try {
        Socket sock = new Socket();
        SocketAddress sockaddr = new InetSocketAddress("8.8.8.8", 80); 
        // port will change according to protocols

        sock.connect(sockaddr, 1250);
        sock.close();

        return true;
    } catch (IOException e) { return false; }
}

这种方法为您提供了一个非常快速的方法(用于实时反馈)或较慢的方法(用于需要可靠性的一次性检查)。

public boolean isNetworkAvailable(bool SlowButMoreReliable) {
    bool Result = false; 
    try {
        if(SlowButMoreReliable){
            ConnectivityManager MyConnectivityManager = null;
            MyConnectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);

            NetworkInfo MyNetworkInfo = null;
            MyNetworkInfo = MyConnectivityManager.getActiveNetworkInfo();

            Result = MyNetworkInfo != null && MyNetworkInfo.isConnected();

        } else
        {
            Runtime runtime = Runtime.getRuntime();
            Process ipProcess = runtime.exec("/system/bin/ping -c 1 8.8.8.8");

            int i = ipProcess.waitFor();

            Result = i== 0;

        }

    } catch(Exception ex)
    {
        //Common.Exception(ex); //This method is one you should have that displays exceptions in your log
    }
    return Result;
}

这里有一个简单的解决方案,以确保你的应用程序可以访问互联网:

static final String CHECK_INTERNET_ACCESS_URL = "https://www.google.com";

public static void isInternetAccessWorking(Context context) {

    StringRequest stringRequest = new StringRequest(Request.Method.GET, CHECK_INTERNET_ACCESS_URL,
            new Response.Listener<String>() {
                @Override
                public void onResponse(String response) {
                    // Internet access is OK
                }
            }, new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {
            // NO internet access
        }
    });

    Volley.newRequestQueue(context).add(stringRequest);
}

这个解决方案使用Android的Volley库,必须在build.gradle中声明:

implementation 'com.android.volley:volley:1.1.1'