使用 AndroidHttpClient 将不起作用

Posted

技术标签:

【中文标题】使用 AndroidHttpClient 将不起作用【英文标题】:Using AndroidHttpClient will not work 【发布时间】:2012-05-21 20:53:20 【问题描述】:

我正在尝试使用 androidHttpClient 下载 CSV 文件。由于某种原因,它在"HttpResponse response httpClient.execute(httpGet, localContext); 行中失败,只是转到"finally"

我已经在浏览器中检查了 URL - 它工作正常。

我没有从 HttpResponse 响应中获得任何信息 - 它就像跳过它一样。

我不明白为什么。有什么想法吗?

谢谢 D

private ArrayList<String> retrieveStockFinParamsFromYahooApiUri(String yahooApiCall)
    
        ArrayList<String> stockFinParamsFromYahooApiUriRows = new ArrayList<String>();
        String resultLine = "";

        BufferedReader reader = null;
        AndroidHttpClient httpClient = AndroidHttpClient.newInstance("yahooGetStockParams");
        HttpContext localContext = new BasicHttpContext();
        HttpGet httpGet = new HttpGet(yahooApiCall);

        try 
        
            HttpResponse response = httpClient.execute(httpGet, localContext);              

            reader = new BufferedReader(new InputStreamReader(
                    response.getEntity().getContent()));

            while ((resultLine = reader.readLine()) != null) 
            
                stockFinParamsFromYahooApiUriRows.add(resultLine);
            
        
        catch (IOException e) 
        
            e.printStackTrace();
         
        finally 
        
            if (reader != null) 
            
                try 
                
                    reader.close();
                 
                catch (IOException e) 
                
                    e.printStackTrace();
                
            
        

        return stockFinParamsFromYahooApiUriRows;
    

进一步调查 (05.22.2012):

@Snicolas - 感谢您的 cmets。在我阅读了您的 cmets 之后,我认为问题可能源于我使用模拟器而不是我的实际设备来调试它。我认为模拟器可能会遇到一些连接问题。当我在我的设备上测试它时 - 我注意到问题仍然存在 - 所以这不是问题。

所以我按照您的建议将代码更改为 catch (Throwable e) 并获得以下堆栈快照:

05-22 18:17:41.457: W/System.err(24552): android.os.NetworkOnMainThreadException
05-22 18:17:41.461: W/System.err(24552):    at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1099)
05-22 18:17:41.461: W/System.err(24552):    at java.net.InetAddress.lookupHostByName(InetAddress.java:391)
05-22 18:17:41.461: W/System.err(24552):    at java.net.InetAddress.getAllByNameImpl(InetAddress.java:242)
05-22 18:17:41.465: W/System.err(24552):    at java.net.InetAddress.getAllByName(InetAddress.java:220)
05-22 18:17:41.465: W/System.err(24552):    at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:137)
05-22 18:17:41.465: W/System.err(24552):    at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
05-22 18:17:41.468: W/System.err(24552):    at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
05-22 18:17:41.468: W/System.err(24552):    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:360)
05-22 18:17:41.468: W/System.err(24552):    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
05-22 18:17:41.472: W/System.err(24552):    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
05-22 18:17:41.472: W/System.err(24552):    at android.net.http.AndroidHttpClient.execute(AndroidHttpClient.java:257)
05-22 18:17:41.472: W/System.err(24552):    at com.bewildering.app.StournamentDbAdapter$YahooStocksParams.retrieveStockFinParamsFromYahooApiUri(StournamentDbAdapter.java:1536)
05-22 18:17:41.476: W/System.err(24552):    at com.bewildering.app.StournamentDbAdapter$YahooStocksParams.run(StournamentDbAdapter.java:1709)
05-22 18:17:41.476: W/System.err(24552):    at com.bewildering.app.StournamentActivity.onCreate(StournamentActivity.java:65)
05-22 18:17:41.476: W/System.err(24552):    at android.app.Activity.performCreate(Activity.java:4465)
05-22 18:17:41.476: W/System.err(24552):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)
05-22 18:17:41.480: W/System.err(24552):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1920)
05-22 18:17:41.480: W/System.err(24552):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1981)
05-22 18:17:41.480: W/System.err(24552):    at android.app.ActivityThread.access$600(ActivityThread.java:123)
05-22 18:17:41.484: W/System.err(24552):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1147)
05-22 18:17:41.484: W/System.err(24552):    at android.os.Handler.dispatchMessage(Handler.java:99)
05-22 18:17:41.484: W/System.err(24552):    at android.os.Looper.loop(Looper.java:137)
05-22 18:17:41.484: W/System.err(24552):    at android.app.ActivityThread.main(ActivityThread.java:4424)
05-22 18:17:41.488: W/System.err(24552):    at java.lang.reflect.Method.invokeNative(Native Method)
05-22 18:17:41.488: W/System.err(24552):    at java.lang.reflect.Method.invoke(Method.java:511)
05-22 18:17:41.488: W/System.err(24552):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
05-22 18:17:41.492: W/System.err(24552):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
05-22 18:17:41.492: W/System.err(24552):    at dalvik.system.NativeStart.main(Native Method)

在寻找android.os.NetworkOnMainThreadException时,我发现the documentation 指出这是:当应用程序尝试在其主线程上执行网络操作时抛出的异常。

由此我得出结论,我应该将我的电话转入AsyncTask

谁能确认我理解正确 - 或者我在这里遗漏了什么?奇怪的是,我向catch (Throwable e) 致敬,以便查明真相。


进一步调查 (05.22.2012):

我现在可以确认这个问题是由于 当应用程序尝试在其主线程上执行网络操作时抛出异常...。 正如我 read 这个从蜂窝开始。

现在的问题:我收到来自 Yahoo 的 301 响应(永久移动)。这很奇怪,因为当我将 URL 剪切粘贴到浏览器中时,它可以工作。

知道为什么这应该在浏览器中工作而不是在应用程序中工作吗?我必须提到这个 HTTP 请求接收一个 CSV 文件作为响应。这可能是个问题吗?


进一步调查 (05.23.2012):

由于某种原因(在我的代码中)使用 Yahoo URI http://finance.yahoo.com/d/quotes.csv?s= 时,响应是 301(永久移动)。当使用http://download.finance.yahoo.com/d/quotes.csv?s= 时,响应为 200(OK)。即使两者在浏览器中都可以正常工作。我很幸运地找到了this web page,它给了我一些关于雅虎对哪些 URI 做出反应的线索。现在我可以看到“阅读器”获取数据,一切都很好。我仍然遇到一些奇怪的异常(仍在试图弄清楚):在阅读了响应中的所有行之后,我捕获了一个 Throwable(我从之前的实验中留下了它),然后在堆栈中我得到了 05-23 08:52:41.258: W/dalvikvm(933): threadid=11: thread exiting with uncaught exception (group=0x40a721f8) 和一些东西关于doInBackground(Void... params) 中未捕获的异常。还在调查中……

刚刚解决了这个问题 - 这只是调用 Yahoo API 的一个错误。必须将 &e=.csv 添加到 URI 的末尾才能使其工作。就这样:http://download.finance.yahoo.com/d/quotes.csv?s=KDHIX&f=sl1d1t1c1ohgv&e=.csv


最终代码

private ArrayList<String> retrieveStockFinParamsFromYahooApiUri(String yahooApiCall)
    
        ArrayList<String> stockFinParamsFromYahooApiUriRows = new ArrayList<String>();
        String resultLine = "";

        BufferedReader reader = null;
        AndroidHttpClient httpClient = AndroidHttpClient.newInstance("yahooGetStockParams");
        HttpContext localContext = new BasicHttpContext();
        HttpGet httpGet = new HttpGet(yahooApiCall);

        try 
        
            HttpResponse response = httpClient.execute(httpGet, localContext);                  

            reader = new BufferedReader(new InputStreamReader(
                    response.getEntity().getContent()));

            while ((resultLine = reader.readLine()) != null) 
            
                stockFinParamsFromYahooApiUriRows.add(resultLine);
            

            if(response != null)
            
                try
                
                    response.getEntity().consumeContent();
                
                catch (IOException e) 
                
                    e.printStackTrace();
                

            
        
        catch (IOException e) 
        
            e.printStackTrace();                
         
        finally 
                       
            if(httpClient != null)
            
                httpClient.close();
            

            if (reader != null) 
            
                try 
                
                    reader.close();
                 
                catch (IOException e) 
                
                    e.printStackTrace();
                
            
        

        return stockFinParamsFromYahooApiUriRows;
    

【问题讨论】:

您应该编辑您的帖子并在此处添加完整的错误日志。但这似乎是连接错误。检查httpResponseCode,它必须返回HTTP_OK。 【参考方案1】:

您在执行时得到的Exception 可能不是IOException。然后,您的catch 块永远不会被执行,并且您的finally 块在该方法向retrieveStockFinParamsFromYahooApiUri 的调用者抛出预期异常之前执行。

您至少有 2 个选项:

不要赶上IOException,而是赶上一堂课。试试Throwable,打印堆栈跟踪,看看会发生什么。然后您可以稍后添加其他 catch 块来处理该案例。 (Catching Throwables is a bad programming practice,不过可以暂时使用)。 使用与上述相同的机制将 retrieveStockFinParamsFromYahooApiUri 的调用置于 try catch 块中,以确定预期哪些异常类并采取相应措施。

但是你需要完善你对问题的理解,抓住一切可能的东西,写下堆栈跟踪并检查 logcat。

以下是一些其他建议:

在阅读其内容之前,您需要check the result code of the request。 您可以使用Apache IOUtils 复制响应输入流的内容并将其缓存到文件中。 你可以enable gzipping of the request and the response。 您还需要在 finally 块中正确关闭 HttpConnection you can consume the entity of the response 来实现此目的。

【讨论】:

Snicolas,您能否详细说明消耗实体的含义?我在此阅读了一些Apache documentation,但我仍然不明白“消费实体”的含义。谢谢! D 当然我先点击了链接:-)。我根本不明白“消费实体”是什么意思。它是否涉及填充/清空缓冲区? response.getEntity().consumeContent(); 触发的底层机制是什么?我仍然没有解决这个问题,所以我仍然收到了java.lang.IllegalStateException: AndroidHttpClient created and never closed,这是一个很好的提醒。 response.getEntity().consumeContent();是的,这就是重点。尝试捕获 我添加了response.getEntity().consumeContent();httpClient.close(); - 我相信这是两个不同的东西,释放了两种不同类型的资源。你怎么看? (我在上面添加了我最近的代码)

以上是关于使用 AndroidHttpClient 将不起作用的主要内容,如果未能解决你的问题,请参考以下文章

使用dwr后,javaweb设置的session超时失效,web.xml和tomcat设置都不起作

使用节点运行脚本的计划任务将不起作用

DefaultHttpClient 到 AndroidHttpClient

我的Android进阶之旅------&gt;Android中ListView中嵌套(ListView)控件时item的点击事件不起作的问题解决方法

如果没有剩余行,PrefetchRowsAt 将不起作用

QGraphicsSceneMouseEvent 获取位置将不起作用[重复]