【问题标题】:Using AndroidHttpClient will not work使用 AndroidHttpClient 将不起作用
【发布时间】: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。

标签: android


【解决方案1】:

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

您至少有 2 个选项:

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

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

以下是一些其他建议:

【讨论】:

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