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

当前回答

只需创建下面的类来检查internet连接:

public class ConnectionStatus {

    private Context _context;

    public ConnectionStatus(Context context) {
        this._context = context;
    }

    public boolean isConnectionAvailable() {
        ConnectivityManager connectivity = (ConnectivityManager) _context
                .getSystemService(Context.CONNECTIVITY_SERVICE);
        if (connectivity != null) {
            NetworkInfo[] info = connectivity.getAllNetworkInfo();
            if (info != null)
                for (int i = 0; i < info.length; i++)
                    if (info[i].getState() == NetworkInfo.State.CONNECTED) {
                        return true;
                    }
        }
        return false;
    }
}

该类仅包含一个返回连接状态布尔值的方法。因此,简单来说,如果该方法找到一个到Internet的有效连接,则返回值为true,否则为false,如果没有找到有效连接。

MainActivity中的下面的方法调用前面描述的方法的结果,并提示用户进行相应的操作:

public void addListenerOnWifiButton() {
        Button btnWifi = (Button)findViewById(R.id.btnWifi);

        iia = new ConnectionStatus(getApplicationContext());

        isConnected = iia.isConnectionAvailable();
        if (!isConnected) {
            btnWifi.setOnClickListener(new View.OnClickListener() {

                @Override
                public void onClick(View v) {
                    startActivity(new Intent(Settings.ACTION_WIFI_SETTINGS));
                    Toast.makeText(getBaseContext(), "Please connect to a hotspot",
                            Toast.LENGTH_SHORT).show();
                }
            });
        }
        else {
            btnWifi.setVisibility(4);
            warning.setText("This app may use your mobile data to update events and get their details.");
        }
    }

在上面的代码中,如果结果为假,(因此没有互联网连接,用户将被带到Android wi-fi面板,在那里他将被提示连接到wi-fi热点。

其他回答

从以下链接找到并修改(!):

在你的manifest文件中至少添加:

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

如果您正在访问它,您可能已经拥有INTERNET权限。那么一个允许测试连通性的布尔函数是:

private boolean checkInternetConnection() {
    ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    // test for connection
    if (cm.getActiveNetworkInfo() != null
            && cm.getActiveNetworkInfo().isAvailable()
            && cm.getActiveNetworkInfo().isConnected()) {
        return true;
    } else {
        Log.v(TAG, "Internet Connection Not Present");
        return false;
    }
}

最简单的解决办法是

在大多数情况下,如果他/她想连接到远程服务器,只会检查互联网连接,所以简单和最好的解决方案是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;
}

下面是一些现代代码,使用AsynTask来解决android崩溃的问题,当你尝试在主线程上连接并为用户引入一个带有冲洗和重复选项的警报。

class TestInternet extends AsyncTask<Void, Void, Boolean> {
    @Override
    protected Boolean doInBackground(Void... params) {
        try {
            URL url = new URL("http://www.google.com");
            HttpURLConnection urlc = (HttpURLConnection) url.openConnection();
            urlc.setConnectTimeout(3000);
            urlc.connect();
            if (urlc.getResponseCode() == 200) {
                return true;
            }
        } catch (MalformedURLException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
            return false;
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            return false;
        }
        return false;
    }

    @Override
    protected void onPostExecute(Boolean result) {
        if (!result) { // code if not connected
            AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
            builder.setMessage("An internet connection is required.");
            builder.setCancelable(false);

            builder.setPositiveButton(
                    "TRY AGAIN",
                    new DialogInterface.OnClickListener() {
                        public void onClick(DialogInterface dialog, int id) {
                            dialog.cancel();
                            new TestInternet().execute();
                        }
                    });


            AlertDialog alert11 = builder.create();
            alert11.show();
        } else { // code if connected
            doMyStuff();
        }
    }
}

...

new TestInternet().execute();

不需要太复杂。最简单的框架方式是使用ACCESS_NETWORK_STATE权限并创建一个连接的方法

public boolean isOnline() {
    ConnectivityManager cm =
        (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);

    return cm.getActiveNetworkInfo() != null && 
       cm.getActiveNetworkInfo().isConnectedOrConnecting();
}

如果您有特定的主机和连接类型(wifi/移动),也可以使用requestRouteToHost。

你还需要:

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

在你的android清单中。

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

快乐编码:)。