I am using okHttp to make an http request to fetch for JSONdata from an API, however, the response is very slow. Sometimes it takes 15-20 seconds, and sometimes it takes just 1-2 seconds. What can be causing this lag in requests, and how can I fix it?
Here is the code of my function where I am using okHttp to make the request. The lag is after I instantiate the request here Request request = new Request.Builder().url(url).build();
Here is the code of the whole function -
private void doGetRequest(String[] time_duration) {
OkHttpClient client = new OkHttpClient();
OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.connectTimeout(10, TimeUnit.MINUTES)
.writeTimeout(10, TimeUnit.MINUTES)
.readTimeout(10,TimeUnit.MINUTES);
ArrayList<JSONObject> departureObject = new ArrayList<>();
String url = "my_http_url";
client = builder.build();
Request request = new Request.Builder().url(url).build(); //here is the lag
Log.v("called here", "made the request");
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
}
#Override
public void onResponse(Call call, Response response) throws IOException {
if(response.isSuccessful()) {
try {
String jsonData = response.body().string();
JSONObject Jobject = new JSONObject(jsonData);
JSONArray jarray = Jobject.getJSONArray("Flights");
departure_flights.clear();
for (int i = 0; i < jarray.length(); i++) {
JSONObject object = jarray.getJSONObject(i)
departure_flights.add(object);
}
} catch (Exception e) {
e.printStackTrace();
}
DeparturesActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
try {
for (int i = 0; i < departure_flights.size(); i++) {
String departure_date = departure_flights.get(i).getString("FldaDT");
String flight_number = departure_flights.get(i).getString("Flno");
flightItems.add(new FlightItem(strDate, flight_number));
}
} catch (JSONException e) {
e.printStackTrace();
}
}
});
}
}
});
You shouldn't be creating a new client per request. Read up on https://square.github.io/okhttp/4.x/okhttp/okhttp3/-ok-http-client/#okhttpclients-should-be-shared
Look at EventListener to log out the different events that contribute to the call latency https://square.github.io/okhttp/events/
Hi guys I was trying to post a JSONArray using OkHttp. I want to do like this:
[
{
"name": "john"
},
{
"food": "burger"
}
]
Can anyone help me out?
You can try adding a JSONObject in an array and then pass it to your JSONArray.
Something like this:
JSONArray list = new JSONArray();
JSONObject js = new JSONObject();
try {
js.put("name", "john");
} catch (JSONException e) {
e.printStackTrace();
}
list.put(js);
js = new JSONObject();
try {
js.put("food", "burger");
} catch (JSONException e) {
e.printStackTrace();
}
list.put(js);
Log.e(TAG, "found json array " + list);
and if you have more items, then run the `js' in a loop until you are done with it.
Something like this:
public void sendRequest(String route) {
OkHttpClient client = new OkHttpClient();
String url = baseUrl + route;
RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("username", String.valueOf(username.getText()))
.addFormDataPart("password", String.valueOf(password.getText()))
.build();
Request request = new Request.Builder()
.url(url)
.post(requestBody)
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
Log.d("Error", "Something Went Wrong");
}
#Override
public void onResponse(Call call, Response response) throws IOException {
if (response.isSuccessful()) {
String myresponse = response.body().string();
try {
JSONArray all = new JSONArray(myresponse);
// Do whatever
} catch (JSONException e) {
e.printStackTrace();
}
} else {
String errorBodyString = response.body().string();
Log.d("Error", errorBodyString);
}
}
});
}
I'm trying to make a request and get the json response to a json string but every time i execute this it gives me an exception. Please help me.
public String login(String json) throws IOException {
OkHttpClient client = new OkHttpClient();
Gson gson = new Gson();
Agent agent = gson.fromJson(json, Agent.class);
json = gson.toJson(agent, Agent.class);
String url = "http://laravel-zona-azul.herokuapp.com/api/v1/login";
Request.Builder builder = new Request.Builder();
builder.url(url);
MediaType mediaType =
MediaType.parse("application/json; charset=utf-8");
RequestBody body = RequestBody.create(mediaType, json);
builder.post(body)
.addHeader("login", agent.login)
.addHeader("cache-control", agent.password);
Log.d("MYAPP", "Body: " + body);
Request request = builder.build();
try{
Response response = client.newCall(request).execute();
return response.body().string();
}
catch (IOException e){
e.printStackTrace();
}
return "";
}
Use this it's working fine for me.
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
}
#Override
public void onResponse(Call call, Response response) throws IOException {
if (response != null)
try {
response.body().string();
} catch (IOException e) {
e.printStackTrace();
}
}
});
Instead of Using this
try{
Response response = client.newCall(request).execute();
return response.body().string();
}
catch (IOException e){
e.printStackTrace();
}
I read some examples which are posting jsons to the server.
some one says :
OkHttp is an implementation of the HttpUrlConnection interface
provided by Java. It provides an input stream for writing content and
doesn't know (or care) about what format that content is.
Now I want to make a normal post to the URL with params of name and password.
It means I need to do encode the name and value pair into stream by myself?
As per the docs, OkHttp version 3 replaced FormEncodingBuilder with FormBody and FormBody.Builder(), so the old examples won't work anymore.
Form and Multipart bodies are now modeled. We've replaced the opaque
FormEncodingBuilder with the more powerful FormBody and
FormBody.Builder combo.
Similarly we've upgraded MultipartBuilder into
MultipartBody, MultipartBody.Part, and MultipartBody.Builder.
So if you're using OkHttp 3.x try the following example:
OkHttpClient client = new OkHttpClient();
RequestBody formBody = new FormBody.Builder()
.add("message", "Your message")
.build();
Request request = new Request.Builder()
.url("https://www.example.com/index.php")
.post(formBody)
.build();
try {
Response response = client.newCall(request).execute();
// Do something with the response.
} catch (IOException e) {
e.printStackTrace();
}
The current accepted answer is out of date. Now if you want to create a post request and add parameters to it you should user MultipartBody.Builder as Mime Craft now is deprecated.
RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("somParam", "someValue")
.build();
Request request = new Request.Builder()
.url(BASE_URL + route)
.post(requestBody)
.build();
private final OkHttpClient client = new OkHttpClient();
public void run() throws Exception {
RequestBody formBody = new FormEncodingBuilder()
.add("search", "Jurassic Park")
.build();
Request request = new Request.Builder()
.url("https://en.wikipedia.org/w/index.php")
.post(formBody)
.build();
Response response = client.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
System.out.println(response.body().string());
}
You need to encode it yourself by escaping strings with URLEncoder and joining them with "=" and "&". Or you can use FormEncoder from Mimecraft which gives you a handy builder.
FormEncoding fe = new FormEncoding.Builder()
.add("name", "Lorem Ipsum")
.add("occupation", "Filler Text")
.build();
You can make it like this:
MediaType JSON = MediaType.parse("application/json; charset=utf-8");
RequestBody body = RequestBody.create(JSON, "{"jsonExample":"value"}");
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(url)
.post(body)
.addHeader("Authorization", "header value") //Notice this request has header if you don't need to send a header just erase this part
.build();
Call call = client.newCall(request);
call.enqueue(new Callback() {
#Override
public void onFailure(Request request, IOException e) {
Log.e("HttpService", "onFailure() Request was: " + request);
e.printStackTrace();
}
#Override
public void onResponse(Response r) throws IOException {
response = r.body().string();
Log.e("response ", "onResponse(): " + response );
}
});
OkHttp POST request with token in header
RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("search", "a")
.addFormDataPart("model", "1")
.addFormDataPart("in", "1")
.addFormDataPart("id", "1")
.build();
OkHttpClient client = new OkHttpClient();
okhttp3.Request request = new okhttp3.Request.Builder()
.url("https://somedomain.com/api")
.post(requestBody)
.addHeader("token", "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiIkMnkkMTAkZzZrLkwySlFCZlBmN1RTb3g3bmNpTzltcVwvemRVN2JtVC42SXN0SFZtbzZHNlFNSkZRWWRlIiwic3ViIjo0NSwiaWF0IjoxNTUwODk4NDc0LCJleHAiOjE1NTM0OTA0NzR9.tefIaPzefLftE7q0yKI8O87XXATwowEUk_XkAOOQzfw")
.addHeader("cache-control", "no-cache")
.addHeader("Postman-Token", "7e231ef9-5236-40d1-a28f-e5986f936877")
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Call call, IOException e) {
e.printStackTrace();
}
#Override
public void onResponse(Call call, okhttp3.Response response) throws IOException {
if (response.isSuccessful()) {
final String myResponse = response.body().string();
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
Log.d("response", myResponse);
progress.hide();
}
});
}
}
});
To add okhttp as a dependency do as follows
right click on the app on android studio open "module settings"
"dependencies"-> "add library dependency" -> "com.squareup.okhttp3:okhttp:3.10.0" -> add -> ok..
now you have okhttp as a dependency
Now design a interface as below so we can have the callback to our activity once the network response received.
public interface NetworkCallback {
public void getResponse(String res);
}
I create a class named NetworkTask so i can use this class to handle all the network requests
public class NetworkTask extends AsyncTask<String , String, String>{
public NetworkCallback instance;
public String url ;
public String json;
public int task ;
OkHttpClient client = new OkHttpClient();
public static final MediaType JSON
= MediaType.parse("application/json; charset=utf-8");
public NetworkTask(){
}
public NetworkTask(NetworkCallback ins, String url, String json, int task){
this.instance = ins;
this.url = url;
this.json = json;
this.task = task;
}
public String doGetRequest() throws IOException {
Request request = new Request.Builder()
.url(url)
.build();
Response response = client.newCall(request).execute();
return response.body().string();
}
public String doPostRequest() throws IOException {
RequestBody body = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
Response response = client.newCall(request).execute();
return response.body().string();
}
#Override
protected String doInBackground(String[] params) {
try {
String response = "";
switch(task){
case 1 :
response = doGetRequest();
break;
case 2:
response = doPostRequest();
break;
}
return response;
}catch (Exception e){
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
instance.getResponse(s);
}
}
now let me show how to get the callback to an activity
public class MainActivity extends AppCompatActivity implements NetworkCallback{
String postUrl = "http://your-post-url-goes-here";
String getUrl = "http://your-get-url-goes-here";
Button doGetRq;
Button doPostRq;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = findViewById(R.id.button);
doGetRq = findViewById(R.id.button2);
doPostRq = findViewById(R.id.button1);
doPostRq.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
MainActivity.this.sendPostRq();
}
});
doGetRq.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
MainActivity.this.sendGetRq();
}
});
}
public void sendPostRq(){
JSONObject jo = new JSONObject();
try {
jo.put("email", "yourmail");
jo.put("password","password");
} catch (JSONException e) {
e.printStackTrace();
}
// 2 because post rq is for the case 2
NetworkTask t = new NetworkTask(this, postUrl, jo.toString(), 2);
t.execute(postUrl);
}
public void sendGetRq(){
// 1 because get rq is for the case 1
NetworkTask t = new NetworkTask(this, getUrl, jo.toString(), 1);
t.execute(getUrl);
}
#Override
public void getResponse(String res) {
// here is the response from NetworkTask class
System.out.println(res)
}
}
This is one of the possible solutions to implementing an OKHTTP post request without a request body.
RequestBody reqbody = RequestBody.create(null, new byte[0]);
Request.Builder formBody = new Request.Builder().url(url).method("POST",reqbody).header("Content-Length", "0");
clientOk.newCall(formBody.build()).enqueue(OkHttpCallBack());
You should check tutorials on lynda.com. Here is an example of how to encode the parameters, make HTTP request and then parse response to json object.
public JSONObject getJSONFromUrl(String str_url, List<NameValuePair> params) {
String reply_str = null;
BufferedReader reader = null;
try {
URL url = new URL(str_url);
OkHttpClient client = new OkHttpClient();
HttpURLConnection con = client.open(url);
con.setDoOutput(true);
OutputStreamWriter writer = new OutputStreamWriter(con.getOutputStream());
writer.write(getEncodedParams(params));
writer.flush();
StringBuilder sb = new StringBuilder();
reader = new BufferedReader(new InputStreamReader(con.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
sb.append(line + "\n");
}
reply_str = sb.toString();
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
}
// try parse the string to a JSON object. There are better ways to parse data.
try {
jObj = new JSONObject(reply_str);
} catch (JSONException e) {
Log.e("JSON Parser", "Error parsing data " + e.toString());
}
return jObj;
}
//in this case it's NameValuePair, but you can use any container
public String getEncodedParams(List<NameValuePair> params) {
StringBuilder sb = new StringBuilder();
for (NameValuePair nvp : params) {
String key = nvp.getName();
String param_value = nvp.getValue();
String value = null;
try {
value = URLEncoder.encode(param_value, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
if (sb.length() > 0) {
sb.append("&");
}
sb.append(key + "=" + value);
}
return sb.toString();
}
protected Void doInBackground(String... movieIds) {
for (; count <= 1; count++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Resources res = getResources();
String web_link = res.getString(R.string.website);
OkHttpClient client = new OkHttpClient();
RequestBody formBody = new FormBody.Builder()
.add("name", name)
.add("bsname", bsname)
.add("email", email)
.add("phone", phone)
.add("whatsapp", wapp)
.add("location", location)
.add("country", country)
.add("state", state)
.add("city", city)
.add("zip", zip)
.add("fb", fb)
.add("tw", tw)
.add("in", in)
.add("age", age)
.add("gender", gender)
.add("image", encodeimg)
.add("uid", user_id)
.build();
Request request = new Request.Builder()
.url(web_link+"edit_profile.php")
.post(formBody)
.build();
try {
Response response = client.newCall(request).execute();
JSONArray array = new JSONArray(response.body().string());
JSONObject object = array.getJSONObject(0);
hashMap.put("msg",object.getString("msgtype"));
hashMap.put("msg",object.getString("msg"));
// Do something with the response.
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
return null;
}
Here is my method to do post request
first pass in method map and data like
HashMap<String, String> param = new HashMap<String, String>();
param.put("Name", name);
param.put("Email", email);
param.put("Password", password);
param.put("Img_Name", "");
final JSONObject result = doPostRequest(map,Url);
public static JSONObject doPostRequest(HashMap<String, String> data, String url) {
try {
RequestBody requestBody;
MultipartBuilder mBuilder = new MultipartBuilder().type(MultipartBuilder.FORM);
if (data != null) {
for (String key : data.keySet()) {
String value = data.get(key);
Utility.printLog("Key Values", key + "-----------------" + value);
mBuilder.addFormDataPart(key, value);
}
} else {
mBuilder.addFormDataPart("temp", "temp");
}
requestBody = mBuilder.build();
Request request = new Request.Builder()
.url(url)
.post(requestBody)
.build();
OkHttpClient client = new OkHttpClient();
Response response = client.newCall(request).execute();
String responseBody = response.body().string();
Utility.printLog("URL", url);
Utility.printLog("Response", responseBody);
return new JSONObject(responseBody);
} catch (UnknownHostException | UnsupportedEncodingException e) {
JSONObject jsonObject=new JSONObject();
try {
jsonObject.put("status","false");
jsonObject.put("message",e.getLocalizedMessage());
} catch (JSONException e1) {
e1.printStackTrace();
}
Log.e(TAG, "Error: " + e.getLocalizedMessage());
} catch (Exception e) {
e.printStackTrace();
JSONObject jsonObject=new JSONObject();
try {
jsonObject.put("status","false");
jsonObject.put("message",e.getLocalizedMessage());
} catch (JSONException e1) {
e1.printStackTrace();
}
Log.e(TAG, "Other Error: " + e.getLocalizedMessage());
}
return null;
}
Add the following to the build.gradle
compile 'com.squareup.okhttp3:okhttp:3.7.0'
Create a new thread, in the new thread add the following code.
OkHttpClient client = new OkHttpClient();
MediaType MIMEType= MediaType.parse("application/json; charset=utf-8");
RequestBody requestBody = RequestBody.create (MIMEType,"{}");
Request request = new Request.Builder().url(url).post(requestBody).build();
Response response = client.newCall(request).execute();
As for Kotlin in 2022 (POST request) works:
val client = OkHttpClient()
val formBody: RequestBody = MultipartBody.Builder()
.addFormDataPart("phone", editText1.text.toString())
.addFormDataPart("email", editText2.text.toString())
.build()
val request: Request = Request.Builder()
.url("https://hellokitty.com/users")
.post(formBody)
.build()
try {
// Do something with the response.
val response = client.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: okio.IOException) {
print(e.message)
}
override fun onResponse(call: Call, response: Response) {
print(response.message)
print("XXX \n" + response.body)
}
})
editTextResponse.text = response.toString()
} catch (e: java.io.IOException) {
editTextResponse.text = e.toString()
e.printStackTrace()
}
Gradle:
implementation("com.squareup.okhttp3:okhttp:5.0.0-alpha.6")
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.jaskierltd.blablaApp">
<uses-permission android:name="android.permission.INTERNET"/>
...
If you want to post parameter in okhttp as body content which can be encrypted string with content-type as "application/x-www-form-urlencoded" you can first use URLEncoder to encode the data and then use :
final MediaType MEDIA_TYPE_MARKDOWN = MediaType.parse("application/x-www-form-urlencoded");
okhttp3.Request request = new okhttp3.Request.Builder()
.url(urlOfServer)
.post(RequestBody.create(MEDIA_TYPE_MARKDOWN, yourBodyDataToPostOnserver))
.build();
you can add header according to your requirement.
public static JSONObject doPostRequestWithSingleFile(String url,HashMap<String, String> data, File file,String fileParam) {
try {
final MediaType MEDIA_TYPE_PNG = MediaType.parse("image/png");
RequestBody requestBody;
MultipartBuilder mBuilder = new MultipartBuilder().type(MultipartBuilder.FORM);
for (String key : data.keySet()) {
String value = data.get(key);
Utility.printLog("Key Values", key + "-----------------" + value);
mBuilder.addFormDataPart(key, value);
}
if(file!=null) {
Log.e("File Name", file.getName() + "===========");
if (file.exists()) {
mBuilder.addFormDataPart(fileParam, file.getName(), RequestBody.create(MEDIA_TYPE_PNG, file));
}
}
requestBody = mBuilder.build();
Request request = new Request.Builder()
.url(url)
.post(requestBody)
.build();
OkHttpClient client = new OkHttpClient();
Response response = client.newCall(request).execute();
String result=response.body().string();
Utility.printLog("Response",result+"");
return new JSONObject(result);
} catch (UnknownHostException | UnsupportedEncodingException e) {
Log.e(TAG, "Error: " + e.getLocalizedMessage());
JSONObject jsonObject=new JSONObject();
try {
jsonObject.put("status","false");
jsonObject.put("message",e.getLocalizedMessage());
} catch (JSONException e1) {
e1.printStackTrace();
}
} catch (Exception e) {
Log.e(TAG, "Other Error: " + e.getMessage());
JSONObject jsonObject=new JSONObject();
try {
jsonObject.put("status","false");
jsonObject.put("message",e.getLocalizedMessage());
} catch (JSONException e1) {
e1.printStackTrace();
}
}
return null;
}
public static JSONObject doGetRequest(HashMap<String, String> param,String url) {
JSONObject result = null;
String response;
Set keys = param.keySet();
int count = 0;
for (Iterator i = keys.iterator(); i.hasNext(); ) {
count++;
String key = (String) i.next();
String value = (String) param.get(key);
if (count == param.size()) {
Log.e("Key",key+"");
Log.e("Value",value+"");
url += key + "=" + URLEncoder.encode(value);
} else {
Log.e("Key",key+"");
Log.e("Value",value+"");
url += key + "=" + URLEncoder.encode(value) + "&";
}
}
/*
try {
url= URLEncoder.encode(url, "utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}*/
Log.e("URL", url);
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url(url)
.build();
Response responseClient = null;
try {
responseClient = client.newCall(request).execute();
response = responseClient.body().string();
result = new JSONObject(response);
Log.e("response", response+"==============");
} catch (Exception e) {
JSONObject jsonObject=new JSONObject();
try {
jsonObject.put("status","false");
jsonObject.put("message",e.getLocalizedMessage());
return jsonObject;
} catch (JSONException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}
return result;
}