我想要一种能够返回互联网连接状态的方法,如果没有可用的连接就像'离线',如果我无法连接到服务器则'错误',或者如果我在线没有错误则'在线'。
我想从主威胁中调用此方法,我也无法在方法本身中发出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;
}
答案 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中完成。