12

我尝试了多个 HTTP 类(和其他类) HttpURLConnectionHTTPClient但它们在模拟器中不起作用。然后我决定在我的手机上测试它,它运行良好!

那么我该如何解决Android模拟器的这种奇怪行为,即HTTP类不起作用(而浏览器可以工作)?他们完全崩溃了一个应用程序。

这是我的代码:

public static SimpleXML getResponse(String action, Map<String, String> params) {
     // Create a new HttpClient and Post Header
    HttpClient httpclient = new DefaultHttpClient();
    HttpPost httppost = new HttpPost(action);

    try {
        // Add your data
        List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(params.size());
        for(Map.Entry<String, String> heh : params.entrySet())
            nameValuePairs.add(new BasicNameValuePair(heh.getKey(), heh.getValue()));
        httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

        // Execute HTTP Post Request
        HttpResponse response = httpclient.execute(httppost);
        return SimpleXML.loadXml(response.getEntity().getContent());       

    } catch (ClientProtocolException e) {
        return null;
    } catch (IOException e) {
        return null;
    }   
}

LogCat 日志:

06-30 22:07:28.972: E/AndroidRuntime(682): FATAL EXCEPTION: main
06-30 22:07:28.972: E/AndroidRuntime(682): android.os.NetworkOnMainThreadException
06-30 22:07:28.972: E/AndroidRuntime(682):  at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1117)
06-30 22:07:28.972: E/AndroidRuntime(682):  at java.net.InetAddress.lookupHostByName(InetAddress.java:385)
06-30 22:07:28.972: E/AndroidRuntime(682):  at java.net.InetAddress.getAllByNameImpl(InetAddress.java:236)
06-30 22:07:28.972: E/AndroidRuntime(682):  at java.net.InetAddress.getAllByName(InetAddress.java:214)
06-30 22:07:28.972: E/AndroidRuntime(682):  at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:137)
06-30 22:07:28.972: E/AndroidRuntime(682):  at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
06-30 22:07:28.972: E/AndroidRuntime(682):  at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
06-30 22:07:28.972: E/AndroidRuntime(682):  at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:360)
06-30 22:07:28.972: E/AndroidRuntime(682):  at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
06-30 22:07:28.972: E/AndroidRuntime(682):  at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
06-30 22:07:28.972: E/AndroidRuntime(682):  at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)
06-30 22:07:28.972: E/AndroidRuntime(682):  at net.ekvium.air.API.getResponse(API.java:98)
06-30 22:07:28.972: E/AndroidRuntime(682):  at net.ekvium.air.MainActivity$1.onClick(MainActivity.java:62)
06-30 22:07:28.972: E/AndroidRuntime(682):  at android.view.View.performClick(View.java:4084)
06-30 22:07:28.972: E/AndroidRuntime(682):  at android.view.View$PerformClick.run(View.java:16966)
06-30 22:07:28.972: E/AndroidRuntime(682):  at android.os.Handler.handleCallback(Handler.java:615)
06-30 22:07:28.972: E/AndroidRuntime(682):  at android.os.Handler.dispatchMessage(Handler.java:92)
06-30 22:07:28.972: E/AndroidRuntime(682):  at android.os.Looper.loop(Looper.java:137)
06-30 22:07:28.972: E/AndroidRuntime(682):  at android.app.ActivityThread.main(ActivityThread.java:4745)
06-30 22:07:28.972: E/AndroidRuntime(682):  at java.lang.reflect.Method.invokeNative(Native Method)
06-30 22:07:28.972: E/AndroidRuntime(682):  at java.lang.reflect.Method.invoke(Method.java:511)
06-30 22:07:28.972: E/AndroidRuntime(682):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
06-30 22:07:28.972: E/AndroidRuntime(682):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
06-30 22:07:28.972: E/AndroidRuntime(682):  at dalvik.system.NativeStart.main(Native Method)
4

3 回答 3

20

如果您查看此 Android 文档,它会解释

网络主线程异常:

当应用程序尝试在其主线程上执行网络操作时引发的异常。

这仅针对面向 Honeycomb SDK 或更高版本的应用程序抛出。允许以早期 SDK 版本为目标的应用程序在其主事件循环线程上进行网络连接,但非常不鼓励这样做。

因此,根据操作系统版本,可能会强制执行(抛出异常)您不在 UI 线程上发出网络请求的策略。这可以解释为什么您的代码可以在设备上运行,而不是在模拟器上运行(如果它们有不同的 Android 版本)。

可以改变ThreadPolicy. 但作为替代方案,我建议您再次查看 Android 文档中的声明。他们强烈反对在主线程上执行网络操作,我当然同意他们的观点。

因此,与其更改策略以使其合法,不如考虑更改代码,以便getResponse()不会在 UI 线程上调用您的方法。

通常,您会使用AsyncTask 在后台完成工作

于 2012-06-30T22:28:15.020 回答
15

发生这种情况是因为您尝试在主线程上执行网络活动。

我有同样的问题,它工作了一段时间,然后经过几周的开发,它停止工作。

我找到的解决方案是将这些行添加到

onCreate()

方法:

    StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
    StrictMode.setThreadPolicy(policy);

希望这对你也有用

编辑

由于赞成票的数量越来越多,我想补充一些东西。这将删除NetworkingOnMainThreadException但是,到目前为止,这不是推荐的方式。

这个例外是有原因的。网络活动可能需要时间,在主线程(负责更新 UI 的线程)上执行网络连接会冻结线程,直到网络连接完成(这是每个线程上发生的情况,但是当它在专用线程上执行时)线程,没关系)。在 Android 中,如果 UI 线程在 5 秒内未处于活动状态,它将显示Application is not responsive, Do you want to close it?对话框。

这就是异常所要防止的。像我建议的那样设置政策,虽然消除了例外,但做事的方式是错误的。任何网络操作都应在单独的线程上完成,无论是通过使用AsyncTask还是通过Thread手动创建。AsyncTask是一种非常简单直接的实现方式,这就是我推荐的。

使用我的答案时请考虑此编辑。

干杯

于 2012-06-30T22:14:42.757 回答
0

您可以使用以下代码禁用严格模式:

if (android.os.Build.VERSION.SDK_INT > 9) {
StrictMode.ThreadPolicy policy = 
new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}

不建议这样做:使用AsyncTask接口。

AsyncTask 的链接

另一个参考的链接

于 2015-09-11T05:57:07.147 回答