0

我想要一个返回 Internet 连接状态的方法,例如如果没有可用连接,则返回“离线”,如果无法连接到服务器,则返回“错误”,如果在线没有错误,则返回“在线”。

我想从主要威胁中调用此方法,我也无法在方法本身中发出 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;
}
4

3 回答 3

1

OK- so I think we all misread the question.

Am I right that you want to make a call to the server before all other calls in your app to determine if it's available?

Solutions:

1.) Your server could go down at any time. Why not just procede querying the endpoints you expect to work and then handle 5xx responses when you need to. This will save you a round trip and greatly enhance stabilty.

2.) Why not use a callback? If you're on the UI thead, please use a callback. THe reason why android thrwos NetworkOnMainTHread is because it blocks - that means your entire UI will hang. If you use an AsyncTask and then block (or "wait" as you say) until it's finished, you'll only circumnavigate Andorid's inbuilt check- you'll still have a buggy app were the UI thread hangs.

AsyncTask is designed to make callbacks easy- the method onPostExecute runs on the UI thead, while doInBackground on a background thread. This is good. Put your code to be executed after your server up check in the postExecute bit, do your http in the doInBackground.

3.) OK, let's suppose for some reason (which may be perfectly valid ;) ) you need to actually turn your call that starts in an AsyncTask into a blocking one? In that case, you need to override onPostExecute in the AsyncTask and use a Semaphore.

In semi-Java-code:

// 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.
}

There we go. And then your response would need to have a getter and a setter for the response code somewhere to check the result.

But please don't do (3) unless you're sure you need it. Yes, (3) is how you wait for an async load of http to finish if you want to do it in a blocking method, but still much better to use callbacks and fire off the rest of your app's http once that first callback is fired.

I realise this is a lot to think about, so please do post comments so I can clarify.

Best.

于 2013-07-26T13:37:25.167 回答
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 语句中执行任何需要互联网的代码,因为如果它是真的,那么那里就有互联网。

于 2013-07-26T13:04:14.170 回答
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 中完成。

于 2014-01-29T00:03:07.243 回答