I'm trying to make a GET request in Android using Apache HTTP Client library but I'm getting the following stacktrace back when I try to make a request.
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)
So it looks like the app crashes when it tries to create a URI
object in my code. In particular, when it tries to parse the .setPath(path)
piece of code.
// 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();
Here's what my code looks like.
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;
}
}
}
I've create another project, but this time as a Java application, and was able to execute this code just fine. In particular, the Java application didn't crash when it hit the following bit of code like it did in the Android app.
// Make the GET request and get the response JSON.
return makeGetRequest(
SCHEME,
HOST,
PATH_MARKET,
params
);
I'm also getting no compilation errors when I build by Android project. I'm actually able to run the app but it crashes right away.
Any pointers would be much appreciated.
If it helps, here's my Maven dependency for the Apache HTTP Client:
pom.xml
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.3.4</version>
</dependency>
Android include outdated Apache HttpClient implementation in their SDK which make it conflict if you add newer Apache Http Client
You should use the HttpClient for Android instead
Google Android 1.0 was released with a pre-BETA snapshot of Apache HttpClient. To coincide with the first Android release Apache HttpClient 4.0 APIs had to be frozen prematurely, while many of interfaces and internal structures were still not fully worked out. [...] Apache HttpClient 4.3 port for Android is intended to remedy the situation by providing official releases compatible with Google Android.
Use this gradle dependency configuration:
dependencies {
/* ... */
compile 'org.apache.httpcomponents:httpclient-android:4.3.3'
}
I'm not a maven user, but maven configuration should be something like this
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient-android</artifactId>
<version>4.3.3</version>
</dependency>
You really want to use 4.3.3 since android port of 4.3.4 is not available yet.
To call a HTTP method, slightly change your code (notice HttpGetHC4
)
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpGetHC4 httpGet = new HttpGetHC4(url);
CloseableHttpResponse response = httpClient.execute(httpGet);
It use different implementation of URIBuilder
so client code need not changed.
For java, just change the order of http library to the most top position.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With