Apache DefaultHttpClient 调用会导致“java.lang.RuntimeException: Stub!”
我正在尝试 Android 开发。我有一个将与 RESTful 资源交互的项目,我正在尝试弄清楚如何通过 HTTP 使用参数进行基本 GET 操作。从我读到的所有内容来看,共识似乎是支持 HTTPClient 而不是 HttpURLConnection。
我编写了一个包装类,其中的方法负责实例化关键对象以使用 HTTPClient 发出请求:
public String get() {
String responseString = null;
HttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet();
try {
get.setURI(new URI(this.baseURL()));
} catch (URISyntaxException e1) {
e1.printStackTrace();
}
HttpResponse response;
try {
response = client.execute(get);
responseString = readResponse(response.getEntity());
if(response != null) {
System.out.println(responseString);
}
} catch(ClientProtocolException e) {
e.printStackTrace();
} catch(IOException e) {
e.printStackTrace();
}
return responseString;
}
行 HttpClient client = new DefaultHttpClient();
抛出以下异常:
java.lang.RuntimeException: Stub!
at org.apache.http.impl.client.AbstractHttpClient.<init>(AbstractHttpClient.java:5)
at org.apache.http.impl.client.DefaultHttpClient.<init>(DefaultHttpClient.java:7)
at org.rcindustries.appmap.RestClient.get(RestClient.java:54)
at org.rcindustries.appmap.test.functional.RestClientTest.shouldReturnSomeJSon(RestClientTest.java:26)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
每个示例我见过 HttpClient 使用类似的结构来执行 GET 和 POST。与 Android SDK 捆绑在一起的 Apache Commons 库与标准库有显着不同吗?
I'm dipping my toes into Android development. I have a project that will interface with a RESTful resource and I'm trying to figure out how to do a basic GET with params over HTTP. From everything I've read, the consensus seems to be favoring HTTPClient over HttpURLConnection.
I've written a wrapper class with a method that takes care of instantiating the key object to make a request using HTTPClient:
public String get() {
String responseString = null;
HttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet();
try {
get.setURI(new URI(this.baseURL()));
} catch (URISyntaxException e1) {
e1.printStackTrace();
}
HttpResponse response;
try {
response = client.execute(get);
responseString = readResponse(response.getEntity());
if(response != null) {
System.out.println(responseString);
}
} catch(ClientProtocolException e) {
e.printStackTrace();
} catch(IOException e) {
e.printStackTrace();
}
return responseString;
}
The line HttpClient client = new DefaultHttpClient();
throws the following exception:
java.lang.RuntimeException: Stub!
at org.apache.http.impl.client.AbstractHttpClient.<init>(AbstractHttpClient.java:5)
at org.apache.http.impl.client.DefaultHttpClient.<init>(DefaultHttpClient.java:7)
at org.rcindustries.appmap.RestClient.get(RestClient.java:54)
at org.rcindustries.appmap.test.functional.RestClientTest.shouldReturnSomeJSon(RestClientTest.java:26)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Every example I've seen for HttpClient uses a similar structure to do GETs and POSTs. Is the Apache Commons library bundled with the Android SDK significantly different that the standard lib?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
对于任何可能感兴趣的人,我遇到了类似的问题 - 尽管我得到的是
DateUtils
的存根错误,而不是HttpClient
。Stephen 似乎是绝对正确的 - Android 平台的类需要模拟器启动并运行: http://simpleprogrammer.com/2010/07/27/the-best-way-to-unit-test-in-android/
非常快上述链接的摘要:
因此,您可以在模拟器上进行单元测试
或
For anyone who may be interested, I bumped into a similar problem - though instead of
HttpClient
I was getting stub errors forDateUtils
.Stephen appears to be absolutely correct - classes that are part of the Android platform need the emulator up and running: http://simpleprogrammer.com/2010/07/27/the-best-way-to-unit-test-in-android/
Really quick summary of the above link:
Therefore, you can unit test...
OR
我认为这是 Android 告诉您不能在该平台上运行该单元测试的方式。涉及与 Android 平台(例如本例中的网络)交互的单元测试需要在实际的 Android 设备或功能正常的 Android 模拟器上运行。
(它们无法在常规 Eclipse 上下文中运行。在早期,您需要 Eclipse 的 Android 插件。现在(自 2013 年以来)您应该使用基于 Intellij 构建的 Android Studio。)
显然,您实际上在做的是针对 Android SDK 提供的存根类运行单元测试。这永远行不通。
I think this is Android's way of telling you that you cannot run that unit test on that platform. Unit tests that involve interacting with the Android platform (e.g. the network in this case) need to be run on an actual Android device or a functioning Android emulator.
(They cannot be run in the context of regular Eclipse. In the early days, you needed Android plugins for Eclipse. These days (since 2013) you should be using Android Studio which build on Intellij.)
Apparently, what you were actually doing was running the unit tests against the stub classes provided by the Android SDK. This cannot ever work.
在 Android SDK 23 中使用 Proguard 和 com.apache.http.legacy 库时会发生这种情况。
在我将其添加到我的 Proguard 配置中后,它就起作用了:
这允许系统 Apache 实现正确覆盖编译的存根进入应用程序。
This happens when using Proguard and the
com.apache.http.legacy
library in Android SDK 23.It worked after I added this to my Proguard config:
Which allows the system Apache implementation to properly override the stubs compiled into the app.
在 API 28 之后,旧库(例如
HttpClient
)已被弃用,会引发Stub!
错误,您现在必须将其包含在清单文件中:https://developers.google.com/maps/documentation/android-sdk/config#specify_requirement_for_apache_http_legacy_library
After API 28, legacy libraries such as
HttpClient
have been deprecated, throws aStub!
error and you must now include this in your Manifest file:https://developers.google.com/maps/documentation/android-sdk/config#specify_requirement_for_apache_http_legacy_library
这个线程有点老了,但是对于不知道的人来说,Robolectric 解决了这个测试问题。
This thread kind of old, but to whoever doesn't know, Robolectric solves this problem for testing.