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

当前回答

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

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

其他回答

这是我解决这个问题的解决方案,并检查有效的互联网连接,因为正如他们所说,网络信息类不能给你预期的结果,它可能会在网络连接但没有互联网时返回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. 
        }
    });

快乐编码:)。

不要忘记将这些权限添加到您的manifest:

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

最简单的解决办法是

在大多数情况下,如果他/她想连接到远程服务器,只会检查互联网连接,所以简单和最好的解决方案是ping你的服务器,如下所示。

public boolean isConnected() {
    final String command = "ping -c 1 yourExmapleDomain.com";
    boolean isConnected = false;
    try {
        isConnected = Runtime.getRuntime().exec(command).waitFor() == 0;
    } catch (InterruptedException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    return isConnected;
}

Kotlin和协程

我将函数放置在一个ViewModel中,该ViewModel具有viewModelScope。使用一个可观察的LiveData,我通知一个活动有关连接。

ViewModel

 fun checkInternetConnection(timeoutMs: Int) {
        viewModelScope.launch(Dispatchers.IO) {
            try {
                val socket = Socket()
                val socketAddress = InetSocketAddress("8.8.8.8", 53)

                socket.connect(socketAddress, timeoutMs)
                socket.close()

                _connection.postValue(true)
            }
            catch(ex: IOException) {
                _connection.postValue(false)
            }
        }
    }
 private val _connection = MutableLiveData<Boolean>()
 val connection: LiveData<Boolean> = _connection

活动

 private fun checkInternetConnection() {
     viewModel.connection.observe(this) { hasInternet ->
         if(!hasInternet) {
             //hasn't connection
         }
         else {
            //has connection
         }
     }
  }

这段代码将帮助您找到互联网是否打开。

public final boolean isInternetOn() {
        ConnectivityManager conMgr = (ConnectivityManager) this.con
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo info = conMgr.getActiveNetworkInfo();
        return (info != null && info.isConnected());
}

此外,您应该提供以下权限

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