Java.lang.NoSuchMethodError错误: org.apache.http.client.utils.URLEncodedUtils.encPath

7

我正在尝试在Android中使用Apache HTTP Client库进行GET请求,但是当我尝试发出请求时,我会收到以下堆栈跟踪。

06-17 16:19:58.891  10605-10605/com.myapp.test.android E/SELinux﹕ selinux_android_seapp_context_reload: seapp_contexts file is loaded from /data/security/spota/seapp_contexts
06-17 16:19:58.891  10605-10605/com.myapp.test.android D/dalvikvm﹕ Late-enabling CheckJNI
06-17 16:19:59.001  10605-10605/com.myapp.test.android I/dalvikvm﹕ Could not find method org.apache.http.client.utils.URLEncodedUtils.encPath, referenced from method org.apache.http.client.utils.URIBuilder.encodePath
06-17 16:19:59.001  10605-10605/com.myapp.test.android W/dalvikvm﹕ VFY: unable to resolve static method 2455: Lorg/apache/http/client/utils/URLEncodedUtils;.encPath (Ljava/lang/String;Ljava/nio/charset/Charset;)Ljava/lang/String;
06-17 16:19:59.001  10605-10605/com.myapp.test.android D/dalvikvm﹕ VFY: replacing opcode 0x71 at 0x0002
06-17 16:19:59.001  10605-10605/com.myapp.test.android I/dalvikvm﹕ Could not find method org.apache.http.client.utils.URLEncodedUtils.encUric, referenced from method org.apache.http.client.utils.URIBuilder.encodeUric
06-17 16:19:59.001  10605-10605/com.myapp.test.android W/dalvikvm﹕ VFY: unable to resolve static method 2456: Lorg/apache/http/client/utils/URLEncodedUtils;.encUric (Ljava/lang/String;Ljava/nio/charset/Charset;)Ljava/lang/String;
06-17 16:19:59.001  10605-10605/com.myapp.test.android D/dalvikvm﹕ VFY: replacing opcode 0x71 at 0x0002
06-17 16:19:59.001  10605-10605/com.myapp.test.android I/dalvikvm﹕ Could not find method org.apache.http.client.utils.URLEncodedUtils.format, referenced from method org.apache.http.client.utils.URIBuilder.encodeUrlForm
06-17 16:19:59.001  10605-10605/com.myapp.test.android W/dalvikvm﹕ VFY: unable to resolve static method 2461: Lorg/apache/http/client/utils/URLEncodedUtils;.format (Ljava/lang/Iterable;Ljava/nio/charset/Charset;)Ljava/lang/String;
06-17 16:19:59.001  10605-10605/com.myapp.test.android D/dalvikvm﹕ VFY: replacing opcode 0x71 at 0x0002
06-17 16:19:59.001  10605-10605/com.myapp.test.android I/dalvikvm﹕ Could not find method org.apache.http.client.utils.URLEncodedUtils.encUserInfo, referenced from method org.apache.http.client.utils.URIBuilder.encodeUserInfo
06-17 16:19:59.001  10605-10605/com.myapp.test.android W/dalvikvm﹕ VFY: unable to resolve static method 2457: Lorg/apache/http/client/utils/URLEncodedUtils;.encUserInfo (Ljava/lang/String;Ljava/nio/charset/Charset;)Ljava/lang/String;
06-17 16:19:59.001  10605-10605/com.myapp.test.android D/dalvikvm﹕ VFY: replacing opcode 0x71 at 0x0002
06-17 16:19:59.001  10605-10605/com.myapp.test.android I/dalvikvm﹕ Could not find method org.apache.http.client.utils.URLEncodedUtils.parse, referenced from method org.apache.http.client.utils.URIBuilder.parseQuery
06-17 16:19:59.001  10605-10605/com.myapp.test.android W/dalvikvm﹕ VFY: unable to resolve static method 2465: Lorg/apache/http/client/utils/URLEncodedUtils;.parse (Ljava/lang/String;Ljava/nio/charset/Charset;)Ljava/util/List;
06-17 16:19:59.001  10605-10605/com.myapp.test.android D/dalvikvm﹕ VFY: replacing opcode 0x71 at 0x0008
06-17 16:19:59.001  10605-10605/com.myapp.test.android W/dalvikvm﹕ Exception Ljava/lang/NoSuchMethodError; thrown while initializing Lcom/myapp/test/android/IHeart;
06-17 16:19:59.001  10605-10605/com.myapp.test.android D/AndroidRuntime﹕ Shutting down VM
06-17 16:19:59.001  10605-10605/com.myapp.test.android W/dalvikvm﹕ threadid=1: thread exiting with uncaught exception (group=0x41849898)
06-17 16:19:59.001  10605-10605/com.myapp.test.android E/AndroidRuntime﹕ FATAL EXCEPTION: main
    java.lang.NoSuchMethodError: org.apache.http.client.utils.URLEncodedUtils.encPath
            at org.apache.http.client.utils.URIBuilder.encodePath(URIBuilder.java:175)
            at org.apache.http.client.utils.URIBuilder.buildString(URIBuilder.java:136)
            at org.apache.http.client.utils.URIBuilder.build(URIBuilder.java:104)
            at com.myapp.test.android.IHeart.makeGetRequest(IHeart.java:129)
            at com.myapp.test.android.IHeart.getMarketId(IHeart.java:119)
            at com.myapp.test.android.IHeart.setMarketId(IHeart.java:70)
            at com.myapp.test.android.IHeart.initializeIHeart(IHeart.java:60)
            at com.myapp.test.android.IHeart.<init>(IHeart.java:50)
            at com.myapp.test.android.IHeart.<clinit>(IHeart.java:35)
            at com.myapp.test.android.MainActivity.onCreate(MainActivity.java:21)
            at android.app.Activity.performCreate(Activity.java:5369)
            at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1104)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2257)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2348)
            at android.app.ActivityThread.access$700(ActivityThread.java:159)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1316)
            at android.os.Handler.dispatchMessage(Handler.java:99)
            at android.os.Looper.loop(Looper.java:137)
            at android.app.ActivityThread.main(ActivityThread.java:5414)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:525)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1187)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1003)
            at dalvik.system.NativeStart.main(Native Method)

看起来我的应用程序在尝试创建URI对象时崩溃了,特别是在尝试解析.setPath(path)代码片段时。

// Make the GET request and get the response JSON.
return makeGetRequest(
        SCHEME,
        HOST,
        PATH_MARKET,
        params
);
...
private JSONObject makeGetRequest(String scheme, String host, String path, List<NameValuePair> params) {
        try {
            URI uri = new URIBuilder()
                    .setScheme(scheme)
                    .setHost(host)
                    .setPath(path)  // <-- Where the crash is happening!
                    .setParameters(params)
                    .build();

这是我的代码样式。
MainActivity.java public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    IHeart.getInstance();
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(com.myapp.test.android.R.menu.main, menu);
    return true;
}

}

IHeart.java

import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.os.AsyncTask;
import android.util.Log;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;

public class IHeart {

    private static final String TAG = IHeart.class.getSimpleName();
    private static IHeart instance = new IHeart();

    private static final String SCHEME = "https";
    private static final String HOST = "api2.iheart.com";
    private static final String PATH_MARKET = "/api/v2/content/markets";

    private long mMarketId;

    public static IHeart getInstance() {
        return instance;
    }

    private IHeart() {
        initializeIHeart();
    }

    private void initializeIHeart() {
        setMarketId();
    }

    private void setMarketId() {
        try {
            JSONObject response = getMarketId("40.7127837", "-74.005941");

            if (response != null) {

                final String KEY_HITS = "hits";
                final String KEY_MARKET_ID = "marketId";

                if (response.isNull(KEY_HITS)) {
                    Log.e(TAG, KEY_HITS + " key doesn't exist in response JSON.");
                } else {
                    JSONArray hitsArray = response.getJSONArray(KEY_HITS);

                    if (hitsArray == null || hitsArray.length() == 0 || hitsArray.isNull(0)) {
                        Log.d(TAG, "Hits array is null/empty.");
                    } else {
                        JSONObject firstHitsObject = hitsArray.getJSONObject(0);

                        if (firstHitsObject == null || firstHitsObject.isNull(KEY_MARKET_ID)) {
                            Log.d(TAG, "Market ID value is null/empty/missing in JSON.");
                        } else {
                            mMarketId = firstHitsObject.getInt(KEY_MARKET_ID);
                            Log.d(TAG, "Market ID = " + mMarketId);
                        }

                    }
                }

            } else {
                Log.e(TAG, "Response JSON was null.");
            }

        } catch (JSONException e) {
            e.printStackTrace();
        }
    }

    private JSONObject getMarketId(String latitude, String longitude) throws JSONException {

        // Define the params
        ArrayList<NameValuePair> params = new ArrayList<NameValuePair>();
        params.add(new BasicNameValuePair("limit", "10"));
        params.add(new BasicNameValuePair("lat", latitude));
        params.add(new BasicNameValuePair("lng", longitude));

        // Make the GET request and get the response JSON.
        return makeGetRequest(
                SCHEME,
                HOST,
                PATH_MARKET,
                params
        );
    }

    private JSONObject makeGetRequest(String scheme, String host, String path, List<NameValuePair> params) {
        try {
            URI uri = new URIBuilder()
                    .setScheme(scheme)
                    .setHost(host)
                    .setPath(path)
                    .setParameters(params)
                    .build();

            Log.d(TAG, "URI = " + uri);

            // Make asyn REST call and return resulting in JSON.
            return new getRequestTask().execute(uri).get();

        } catch (URISyntaxException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }

        return null;
    }

    private class getRequestTask extends AsyncTask<URI, Void, JSONObject> {

        @Override
        protected JSONObject doInBackground(URI... params) {
            for (URI uri : params) {
                try {
                    CloseableHttpClient httpClient = HttpClients.createDefault();
                    HttpGet httpGet = new HttpGet(uri);

                    CloseableHttpResponse response = httpClient.execute(httpGet);

                    // Read the response
                    HttpEntity httpEntity = response.getEntity();

                    // Create and return JSONObject
                    if (httpEntity != null) {
                        String json = EntityUtils.toString(httpEntity);
                        return new JSONObject(json);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }

            return null;
        }
    }
}

我创建了另一个项目,但这次是一个Java应用程序,并且能够成功地执行此代码。特别是,Java应用程序在遇到以下代码时不会像Android应用程序那样崩溃。

// Make the GET request and get the response JSON.
return makeGetRequest(
        SCHEME,
        HOST,
        PATH_MARKET,
        params
);

我在构建安卓项目时没有遇到编译错误。实际上,我可以运行应用程序,但它会立即崩溃。如果有任何指示将不胜感激。Maven的Apache HTTP客户端依赖如下:pom.xml。
<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.3.4</version>
</dependency>
3个回答

3

Android在其SDK中包含了过时的Apache HttpClient实现,如果您添加了更新的Apache Http Client可能会发生冲突。

相反,您应该使用HttpClient for Android

Google Android 1.0发布时,包含了一个预发布版的Apache HttpClient。为了与第一个Android版本同时发布,Apache HttpClient 4.0 API不得不被过早地冻结,而许多接口和内部结构仍未完全解决。 [...] Apache HttpClient 4.3端口适用于Android,旨在通过提供与Google Android兼容的官方版本来解决这个问题。

使用此Gradle依赖项配置:

dependencies {
    /* ... */
    compile 'org.apache.httpcomponents:httpclient-android:4.3.3'
}

我不是maven的用户,但是maven的配置应该是这个样子:

我不是Maven的用户,但Maven的配置应该类似于这样

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient-android</artifactId>
    <version>4.3.3</version>
</dependency>

由于安卓移植的4.3.4版本尚未推出,建议使用4.3.3版本。

要调用HTTP方法,请稍微修改您的代码(注意HttpGetHC4)。

CloseableHttpClient httpClient = HttpClients.createDefault();
HttpGetHC4 httpGet = new HttpGetHC4(url);
CloseableHttpResponse response = httpClient.execute(httpGet);

它使用不同的URIBuilder实现,因此客户端代码无需更改。

非常感谢!您建议使用Apache HTTP组件的4.3.3版本并使用HttpGetHC4解决了问题。 - FilmiHero
对于依赖于httpclient(非Android)的库,我该怎么办? - Dan

1

对于Java,只需将HTTP库的顺序更改为最顶部位置。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接