【发布时间】:2014-02-24 04:06:50
【问题描述】:
我在 API 16 上运行时遇到 HTTP 连接失败的问题,但在 API 10 上运行良好。其他网站连接使用相同的代码可以正常执行,因此尤其是本网站的问题。使用以下代码创建并读入连接:(2014 年 2 月 4 日更新以包含整个测试程序)
package com.example.test2;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.HttpURLConnection;
import java.net.URL;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.widget.TextView;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public void getData(View view) {
new TaskGetDir().execute();
}
public class TaskGetDir extends AsyncTask<Void, Void, String> {
@Override
protected String doInBackground(Void... params) {
String gpx_url = "http://gpx.geotags.com/cgi-bin/gpx.cgi?saddr=Boston,MA%s&daddr=NewYork,NY%s";
String doc_gpx = "";
try {
HttpURLConnection conn = (HttpURLConnection) new URL(gpx_url).openConnection();
InputStream is = new BufferedInputStream(conn.getInputStream());
Reader reader = null;
reader = new InputStreamReader(is, "UTF-8");
char[] buffer = new char[512];
reader.read(buffer);
doc_gpx = new String(buffer);
} catch (IOException e) {
e.printStackTrace();
}
return doc_gpx;
}
protected void onPostExecute(String result) {
TextView out_loc1 = (TextView) findViewById(R.id.sample_out);
out_loc1.setText(result.toString());
}
}
}
代码正确地将 512 个字符提取到缓冲区并通过 API10 上的 textView 显示,但它在 API 16 中崩溃。失败发生在 conn.getContent() 调用期间。 logcat 日志如下所示:
01-31 07:42:34.096: E/AndroidRuntime(11036): FATAL EXCEPTION: AsyncTask #1
01-31 07:42:34.096: E/AndroidRuntime(11036): java.lang.RuntimeException: An error occured while executing doInBackground()
01-31 07:42:34.096: E/AndroidRuntime(11036): at android.os.AsyncTask$3.done(AsyncTask.java:299)
01-31 07:42:34.096: E/AndroidRuntime(11036): at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
01-31 07:42:34.096: E/AndroidRuntime(11036): at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
01-31 07:42:34.096: E/AndroidRuntime(11036): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
01-31 07:42:34.096: E/AndroidRuntime(11036): at java.util.concurrent.FutureTask.run(FutureTask.java:137)
01-31 07:42:34.096: E/AndroidRuntime(11036): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
01-31 07:42:34.096: E/AndroidRuntime(11036): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
01-31 07:42:34.096: E/AndroidRuntime(11036): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
01-31 07:42:34.096: E/AndroidRuntime(11036): at java.lang.Thread.run(Thread.java:856)
01-31 07:42:34.096: E/AndroidRuntime(11036): Caused by: java.lang.IndexOutOfBoundsException
01-31 07:42:34.096: E/AndroidRuntime(11036): at java.lang.AbstractStringBuilder.append0(AbstractStringBuilder.java:156)
01-31 07:42:34.096: E/AndroidRuntime(11036): at java.lang.StringBuilder.append(StringBuilder.java:311)
01-31 07:42:34.096: E/AndroidRuntime(11036): at libcore.net.UriCodec.appendEncoded(UriCodec.java:114)
01-31 07:42:34.096: E/AndroidRuntime(11036): at libcore.net.UriCodec.appendPartiallyEncoded(UriCodec.java:142)
01-31 07:42:34.096: E/AndroidRuntime(11036): at java.net.URLStreamHandler.toExternalForm(URLStreamHandler.java:281)
01-31 07:42:34.096: E/AndroidRuntime(11036): at java.net.URL.toURILenient(URL.java:510)
01-31 07:42:34.096: E/AndroidRuntime(11036): at libcore.net.http.HttpEngine.<init>(HttpEngine.java:195)
01-31 07:42:34.096: E/AndroidRuntime(11036): at libcore.net.http.HttpURLConnectionImpl.newHttpEngine(HttpURLConnectionImpl.java:256)
01-31 07:42:34.096: E/AndroidRuntime(11036): at libcore.net.http.HttpURLConnectionImpl.initHttpEngine(HttpURLConnectionImpl.java:243)
01-31 07:42:34.096: E/AndroidRuntime(11036): at libcore.net.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:78)
01-31 07:42:34.096: E/AndroidRuntime(11036): at java.net.URLConnection.getContent(URLConnection.java:190)
01-31 07:42:34.096: E/AndroidRuntime(11036): at com.example.test.MainActivity$TaskGetData.doInBackground(MainActivity.java:55)
01-31 07:42:34.096: E/AndroidRuntime(11036): at com.example.test.MainActivity$TaskGetData.doInBackground(MainActivity.java:1)
01-31 07:42:34.096: E/AndroidRuntime(11036): at android.os.AsyncTask$2.call(AsyncTask.java:287)
01-31 07:42:34.096: E/AndroidRuntime(11036): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
当本网站进入浏览器窗口时,会提示自动下载文件,然后从服务器端终止连接。它以 xml 格式返回带有我想提取的纬度/经度属性的方向。我的理论是不同的 API 以不同的方式处理这种尝试下载。任何帮助表示赞赏。
【问题讨论】:
-
您是否向我们展示了完整的代码?这是使用
HttpURLConnection的一种非常不寻常的方式。您最好搜索好的示例或使用abstraction library for HTTP requests。至少您应该删除conn.getContent()并将InputStream直接提供给您的 XML 解析器。 -
我已经更新了上面的代码来展示整个测试程序。我删除了 conn.getContent() 调用并看到了相同的结果。它在模拟器上很好地显示缓冲区,但在 conn.getInputStream() 调用时在电话(API 16)上崩溃。我正在使用与此处找到的示例类似的代码:link。如果我使用不同的 url,例如“google.com”,它可以在两个设备上正常连接并显示内容。使用 API16 建立与此特定站点的连接似乎是一个问题。