Android等待AsyncTask检查服务器连接是否可用

时间:2013-07-26 12:46:41

标签: android android-asynctask android-networking networkonmainthread

我想要一种能够返回互联网连接状态的方法,如果没有可用的连接就像'离线',如果我无法连接到服务器则'错误',或者如果我在线没有错误则'在线'。

我想从主威胁中调用此方法,我也无法在方法本身中发出HTTP请求,并且必须将其放在AsyncTask或类似的内容中。但我不知道如何操纵我的代码。

这几乎是我想要的,但是如何在try块中提取代码呢?它总是抛出NetworkOnMainThreadException

public static int isOnline(Activity activity)
{
    ConnectivityManager cm = (ConnectivityManager) activity.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo netInfo = cm.getActiveNetworkInfo();
    int netType = 0;
    if (netInfo != null)
    {
        netType = netInfo.getType();
        if (netInfo.isAvailable() && netInfo.isConnected())
        {
            if (netType == ConnectivityManager.TYPE_WIFI || netType == ConnectivityManager.TYPE_MOBILE)
            {
                try
                {
                    URL myUrl = new URL(HTTP_HOST);
                    URLConnection connection = myUrl.openConnection();
                    connection.setConnectTimeout(5000);
                    connection.connect();
                    return INTERNET_CONNECTIVITY_ONLINE;
                } catch (IOException e)
                {
                    return INTERNET_CONNECTIVITY_ERROR;
                }
            }
        }
    }
    return INTERNET_CONNECTIVITY_OFFLINE;
}

修改

我忘了说我的HTTP_HOST需要HTTP身份验证。也许我必须为请求添加这些身份验证吗?

修改

想要这样的事情:

public static int isOnline(Activity activity)
{
    ConnectivityManager cm = (ConnectivityManager) activity.getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo netInfo = cm.getActiveNetworkInfo();
    int netType = 0;
    if (netInfo != null)
    {
        netType = netInfo.getType();
        if (netInfo.isAvailable() && netInfo.isConnected())
        {
            if (netType == ConnectivityManager.TYPE_WIFI || netType == ConnectivityManager.TYPE_MOBILE)
            {
                MyAsyncTask as = new MyAsyncTask();
                return as.execute("") == true ? INTERNET_CONNECTIVITY_ONLINE : INTERNET_CONNECTIVITY_ERROR;
            }
        }
    }
    return INTERNET_CONNECTIVITY_OFFLINE;
}

3 个答案:

答案 0 :(得分:1)

好的 - 所以我想我们都误解了这个问题。

我是否正确,您希望在应用中的所有其他呼叫之前拨打服务器,以确定它是否可用?

解决方案:

1。)您的服务器可能随时关闭。为什么不直接查询您期望工作的端点,然后在需要时处理5xx响应。这将为您节省往返次数并大大提高稳定性。

2.。)为什么不使用回调?如果您使用的是UI, 使用回调。 原因为什么android thrwos NetworkOnMainTHread是因为它阻止 - 这意味着你的整个用户界面将会挂起。如果你使用AsyncTask然后阻止(或者说“等待”),直到它完成,你只会绕过Andorid的内置检查 - 你仍然会有一个错误的应用程序UI线程挂起。

AsyncTask旨在简化回调 - 方法onPostExecute在UI thead上运行,而doInBackground在后​​台线程上运行。这很好。在postExecute位检查服务器后执行代码,在doInBackground中执行http。

3。)好吧,我们假设出于某种原因(这可能是完全有效的;))你需要实际将你在AsyncTask开始的通话转变为阻止通话吗? 在这种情况下,您需要覆盖onPostExecute中的AsyncTask并使用Semaphore

在半Java代码中:

// in your blocking method:
Semaphore myAsyncWaiterSemaphore = new Semaphore(0);
AsyncTask myAsyncTask = new MyAsyncTask(myAsyncWaiterSemaphore); // take the semaphore in the ctor and set it as a field.
myAsyncWaiterSemaphore.acquire();

// in your async task:
onPostExecute(your-args...) {
    this.mSemaphore.acquire(); // you've passed this in as a field.
}

我们走了。然后你的响应需要在某个地方有响应代码的getter和setter来检查结果。

但除非你确定需要,否则请不要做(3)。是的,(3)如果您想在阻塞方法中执行此操作,等待http的异步加载完成的方式,但更好的方法是使用回调并在第一次回调被触发后触发应用程序的http的其余部分

我意识到这需要考虑很多,所以请发表评论以便澄清。

最佳。

答案 1 :(得分:0)

你可以使用这种方法,你只想制作自己的InternetDetector或其他任何你想称之为类的东西:

public class InternetDetector{

    private InternetDetector(){ }

    public static InternetDetector getInstance(){
        return new InternetDetector();
    }

    public boolean isOnline(){
        ConnectivityManager cm = (ConnectivityManager) activity.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo netInfo = cm.getActiveNetworkInfo();
        int netType = 0;
        if (netInfo != null){
            netType = netInfo.getType();
            if (netInfo.isAvailable() && netInfo.isConnected()){
                if (netType == ConnectivityManager.TYPE_WIFI || netType ==       ConnectivityManager.TYPE_MOBILE){
                return true;
                }
            }
        }
        return false;

    }

}

创建此课程后,您可以随时随地调用它。只需使用静态工厂来获取实例并检查可用性。

    if(InternetDetector.getInstance().isOnline()){
          //do your internt stuff here
    }

你可以在这个if语句中执行任何需要互联网的代码,因为如果它是真的,那里就有互联网。

答案 2 :(得分:0)

观看:Google I / O 2010 - Android REST客户端应用程序https://www.youtube.com/watch?v=xHXn3Kg2IQE

请阅读:http://blog.ericwoodruff.me/2013/09/android-remote-sync-content-provider.html

总结:您不应该从AsyncTask进行任何下载。这应该在IntentService中完成,或者更好地在带有ContentProvider的SyncAdatper中完成。