我得到了一个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。

所以这是我基于@Levite回答的完整解决方案:

首先,你必须有AsynckTask检查网络可用性,这是我的:

public class Connectivity {
 private static final String TAG = "Connectivity";
private static boolean hasConnected = false, hasChecked = false;
private InternetListener internetListener;
private Activity activity;

public Connectivity(InternetListener internetListener, Activity activity) {
    this.internetListener = internetListener;
    this.activity = activity;
}

public void startInternetListener() {


    CheckURL checkURL = new CheckURL(activity);

    checkURL.execute();

    long startTime = System.currentTimeMillis();

    while (true) {
        if (hasChecked && hasConnected) {
            activity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    internetListener.onConnected();
                }
            });

            checkURL.cancel(true);
            return;
        }

        // check if time
        if (System.currentTimeMillis() - startTime >= 1000) {
            activity.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    internetListener.onDisconnected();
                }
            });


            checkURL.cancel(true);
            return;
        }
    }

    //return hasConnected;
}


class CheckURL extends AsyncTask<Void, Void, Boolean> {

    private Activity activity;

    public CheckURL(Activity activity) {
        this.activity = activity;
    }

    @Override
    protected Boolean doInBackground(Void... params) {
        if (!isNetWorkAvailable(activity)) {
            Log.i(TAG, "Internet not available!");
            return false;
        }

        int timeoutMs = 3000;

        try {
            Socket sock = new Socket();
            SocketAddress sockaddr = new InetSocketAddress("8.8.8.8", 53);
            sock.connect(sockaddr, timeoutMs);
            sock.close();
            Log.i(TAG, "Internet available :)");
            return true;

        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }

    }

    @Override
    protected void onPostExecute(Boolean result) {
        hasChecked = true;
        hasConnected = result;
        super.onPostExecute(result);}}
     

private static final String TAG = "Connectivity";


private static boolean isNetWorkAvailable(Activity activity) {

    ConnectivityManager connectivityManager =
            (ConnectivityManager) 
   activity.getSystemService(Activity.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo =
            null;
    if (connectivityManager != null) {
        networkInfo = 
   connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
    }
    boolean isConnected;
    boolean isWifiAvailable = false;
    if (networkInfo != null) {
        isWifiAvailable = networkInfo.isAvailable();
    }
    boolean isWifiConnected = false;
    if (networkInfo != null) {
        isWifiConnected = networkInfo.isConnected();
    }
    if (connectivityManager != null) {
        networkInfo =
                connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
    }
    boolean isMobileAvailable = false;
    if (networkInfo != null) {
        isMobileAvailable = networkInfo.isAvailable();
    }
    boolean isMobileConnected = false;
    if (networkInfo != null) {
        isMobileConnected = networkInfo.isConnected();
    }
    isConnected = (isMobileAvailable && isMobileConnected) ||
            (isWifiAvailable && isWifiConnected);
    return (isConnected);}
    }}



private static boolean isNetWorkAvailable(Context context) {

    ConnectivityManager connectivityManager =
            (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo =
            null;
    if (connectivityManager != null) {
        networkInfo = connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
    }
    boolean isConnected;
    boolean isWifiAvailable = false;
    if (networkInfo != null) {
        isWifiAvailable = networkInfo.isAvailable();
    }
    boolean isWifiConnected = false;
    if (networkInfo != null) {
        isWifiConnected = networkInfo.isConnected();
    }
    if (connectivityManager != null) {
        networkInfo =
                connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
    }
    boolean isMobileAvailable = false;
    if (networkInfo != null) {
        isMobileAvailable = networkInfo.isAvailable();
    }
    boolean isMobileConnected = false;
    if (networkInfo != null) {
        isMobileConnected = networkInfo.isConnected();
    }
    isConnected = (isMobileAvailable && isMobileConnected) ||
            (isWifiAvailable && isWifiConnected);
    return (isConnected);

}

}

之后,你应该创建另一个线程来启动AscnkTask并使用InternetListener监听结果。

public interface InternetListener {
void onConnected();
void onDisconnected();
}

而等待AsynckTask结果的线程,你可以把它放在Utility类中:

 private static Thread thread;

public static void startNetworkListener(Context context, InternetListener 
    internetListener) {

    if (thread == null){
        thread = new Thread(new Runnable() {
            @Override
            public void run() {
                Looper.prepare();
                new Connectivity(internetListener,context).startInternetListener();
            }
        });
    }

    thread.start();
 }

最后调用startNetworkListener()方法并监听结果。

My Utils.java类中的activity示例:

     Utils.startNetworkListener(this, new InternetListener() {
        @Override
        public void onConnected() {
           // do your work when internet available. 
        }

        @Override
        public void onDisconnected() {
          // do your work when no internet available. 
        }
    });

快乐编码:)。

其他回答

这对我来说确实有用:

验证网络可用性。

private Boolean isNetworkAvailable() {
ConnectivityManager connectivityManager 
      = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo activeNetworkInfo = connectivityManager.getActiveNetworkInfo();
return activeNetworkInfo != null && activeNetworkInfo.isConnectedOrConnecting();}

验证互联网接入:

public Boolean isOnline() {
    try {
        Process p1 = java.lang.Runtime.getRuntime().exec("ping -c 1 www.google.com");
        int returnVal = p1.waitFor();
        boolean reachable = (returnVal==0);
        return reachable;
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return false;
}

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

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

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();
public boolean isOnline() {
    boolean var = false;
    ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    if ( cm.getActiveNetworkInfo() != null ) {
        var = true;
    }
    return var;
} 

我是这样做的。 我想会更短更有可读性。

干杯!

Saiyan

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/

看一下ConnectivityManager类。您可以使用这个类来获取主机上活动连接的信息。http://developer.android.com/reference/android/net/ConnectivityManager.html

编辑:你可以使用

Context.getSystemService(Context.CONNECTIVITY_SERVICE)
    .getNetworkInfo(ConnectivityManager.TYPE_MOBILE) 

or

Context.getSystemService(Context.CONNECTIVITY_SERVICE)
    .getNetworkInfo(ConnectivityManager.TYPE_WIFI) 

并解析返回NetworkInfo对象的DetailedState枚举

EDIT EDIT:查看是否可以访问主机

Context.getSystemService(Context.CONNECTIVITY_SERVICE)
    .requestRouteToHost(TYPE_WIFI, int hostAddress)

显然,我使用Context.getSystemService(Context.CONNECTIVITY_SERVICE)作为代理来表示

ConnectivityManager cm = Context.getSystemService(Context.CONNECTIVITY_SERVICE);
cm.yourMethodCallHere();