Retrofit POST. Add JSON parameter to every post request - java

I have four static parameters which i need to set to every post retrofit request only once, because i don't need to put them with every request every time. This is my code:
public interface Login {
#POST("login")
#Headers("Content-Type: application/json")
Call<String> login(#Body JsonObject json);
}
then i call it and pass email and password as body parameters like this:
private void sendLoginRequest() {
API.login().login(CommandLogin.getInputParamsAsJSON(mStrEmail, Utils.md5(mStrPassword))).enqueue(this);
}
then in intercept body i tried to pass this static parameters, but when i check the log it seems to pass only this two static params without email and password. In my situation i want to put in body email,password,os,version.
public class API {
private static <T> T builder(Class<T> endpoint) {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.addInterceptor(
new Interceptor() {
#Override
public Response intercept(Interceptor.Chain chain){
try {
Request original = chain.request();
JSONObject params = new JSONObject();
params.put("version" , "6");
params.put("os" , "2");
MediaType JSON = MediaType.parse("application/json; charset=utf-8");
RequestBody body = RequestBody.create(JSON, params.toString());
Request.Builder requestBuilder = original.newBuilder()
.post(body);
Request request = requestBuilder.build();
return chain.proceed(request);
} catch (Exception e) {
e.printStackTrace();
}
//TODO
return null;
}
})
.addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY))
.build();
return new Retrofit.Builder()
.baseUrl(Utils.BASE_COMPONENT_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(okHttpClient)
.build()
.create(endpoint);
}
public static Login login() {
return builder(Login.class);
}
}

That's because, you are basically overwriting original Login Post Request Body with new params. What you should do instead is, get the post body from original request and append new params to it.
Something like below (code not tested)
try {
// Create new buffer
final Buffer buffer = new Buffer();
// Copy original request's json body to buffer
chain.request().body().writeTo(buffer);
// Convert buffer to JSONObject
JSONObject params = new JSONObject(buffer.readUtf8());
// Append new params
params.put("version", "6");
params.put("os", "2");
// Now the params json object will have all 4 values: email,password,os,version
// TODO: Your remaining code
} catch (Exception ex) {
Log.d("Login","Error creating post body", ex);
}

Related

Getting bad response trying to send a request

I'm trying to send a request to a NodeJS server, I'm always getting Bad Request message with status code 400.
I tried using Postman to check if the problem was on the server, but in Postman it worked correctly.
I'm using OkHttp and trying to send a request like this:
private Request request;
private final OkHttpClient client = new OkHttpClient();
private void makePost(String nameOfProduct, String serialOfProduct, String priceOfProduct, String gender, String uriList, String colors, String sizes) {
RequestBody requestBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("name", nameOfProduct)
.addFormDataPart("serial",serialOfProduct)
.addFormDataPart("price",priceOfProduct)
.addFormDataPart("gender",gender)
.addFormDataPart("color", colors)
.addFormDataPart("size", sizes)
.addFormDataPart("imagesUri",uriList)
.build();
Log.d("COLROS", colors);
request = new Request.Builder()
.url("http://10.0.2.2:4000/products/add")
.header("Content-Type", "application/json")
.post(requestBody)
.build();
try{
Response response = client.newCall(request).execute();
if (!response.isSuccessful()) {
throw new IOException("Unexpected code " + response);
}
Headers responeHeaders = response.headers();
for (int i = 0; i < responeHeaders.size(); i++) {
Log.d("iu", "makePost: "+responeHeaders.name(i) + ": " + responeHeaders.value(i));
}
Log.d("iu", "makePost: "+response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
You are sending Form data (application/x-www-form-urlencoded) but setting the header as json
Try to remove the line:
.header("Content-Type", "application/json")
and use:
.header("Content-Type", "application/x-www-form-urlencoded")
To send JSON data, you must build a JSON string. I'll use Gson library here, make sure you include it in your module level gradle file as follows:
implementation 'com.google.code.gson:gson:2.8.6'
Next you need a class to serialize into JSON:
public class Order {
public String name;
public String serial;
public int price;
public String gender;
//Other fields go here...
//This empty constructor is required by Gson
public Order() {}
}
Now you build an object of this class as you require:
private void makePost(String nameOfProduct, String serialOfProduct, String priceOfProduct, String gender, String uriList, String colors, String sizes) {
Order order = new Order();
order.name = nameOfTheProduct;
order.price = priceOfTheProduct;
//Fill in other fields here...
//Now get a JSON data string from this object using Gson:
Gson gson = new Gson();
String jsonData = gson.toJson(order);
public static final MediaType mediaTypeJSON = MediaType.get("application/json; charset=utf-8");
RequestBody requestBody = RequestBody.create(mediaTypeJSON, jsonData);
//Build the request
Request request = new Request.Builder()
.url("http://10.0.2.2:4000/products/add")
.post(requestBody)
.build();
//Finally send the request as you already do in your code
//Using the call: Response response = client.newCall(request).execute();
}

cannot resolve method create 'com.google.common.net.MediaType,java.lang.String)

I want to send a device to device Firebase notification using OkHttp 3, but am getting the following error when posting the JSON:
cannot resolve method create 'com.google.common.net.MediaType,java.lang.String)
Here is my code:
final String legacyServerKey = "";
final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
OkHttpClient client = new OkHttpClient();
JSONObject json = new JSONObject();
JSONObject dataJson = new JSONObject();
dataJson.put("body", "Hi this is sent from device to device");
dataJson.put("title", "dummy title");
json.put("notification", dataJson);
json.put("to", reg_token);
RequestBody body = RequestBody.create(JSON, json.toString());
Request request = new Request.Builder()
.header("Authorization", "key=" + legacyServerKey)
.url("https://fcm.googleapis.com/fcm/send")
.post(body)
.build();
try {
Response response = client.newCall(request).execute();
String finalResponse = response.body().string();
} catch (IOException e) {
e.printStackTrace();
}
It looks like you imported com.google.common.net.MediaType. You need okhttp3.MediaType

How to change body in OkHttp Response?

I'm using retrofit. To catch response i'm using Interceptor:
OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.interceptors().add(myinterceptor);
here is code of interceptor:
new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
Response response = chain.proceed(request);
if (path.equals("/user")){
String stringJson = response.body().string();
JSONObject jsonObject = new JSONObject(stringJson);
jsonObject.put("key",1);
//here I need to set this new json to response and then return this response
How to change body in OkHttp Response?
Add this
MediaType contentType = response.body().contentType();
ResponseBody body = ResponseBody.create(contentType, jsonObject);
return response.newBuilder().body(body).build();
after your response modification. jsonObject is the modified JSON you want to return.
Below is Response Intercepter class where you can intercept okkhttp responce and add your own response. and send it to retrofit.
import org.json.JSONException;
import org.json.JSONObject;
import java.io.IOException;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.Request;
import okhttp3.ResponseBody;
import retrofit2.Response;
public class ApiResponseInterceptor implements Interceptor {
#Override
public okhttp3.Response intercept(Chain chain) throws IOException {
Request request = chain.request();
okhttp3.Response response = chain.proceed(request);
if(response.code() == 200) {
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("code",200);
jsonObject.put("status","OK");
jsonObject.put("message","Successful");
MediaType contentType = response.body().contentType();
ResponseBody body = ResponseBody.create(contentType, jsonObject.toString());
return response.newBuilder().body(body).build();
} catch (JSONException e) {
e.printStackTrace();
}
} else if(response.code() == 403) {
}
return response;
}
}
Yow will get your modified response here in your retrofit callback
call.enqueue(new Callback<EventResponce>() {
#Override
public void onResponse(Call<EventResponce> call, Response<EventResponce> response) {
// you will get your own modified responce here
}
#Override
public void onFailure(Call<EventResponce> call, Throwable t) {
}
});
As a minor change I wouldn't use the string() method cause it can be called only once on this request. You do use the response.newBuilder() so other interceptors down the chain will be able to call string() on your new one but I found myself wasting a couple of hours because I was actually calling it twice :P.
So i suggest something like the following
BufferedSource source = response.body().source();
source.request(Long.MAX_VALUE); // Buffer the entire body.
Buffer buffer = source.buffer();
String responseBodyString = buffer.clone().readString(Charset.forName("UTF-8"));
Here's a tight, complete example of adding an interceptor that modifies JSON to an OkHttpClient. It uses GSON to manage the JSON.
client.addInterceptor(chain -> {
final Request request = chain.request();
final String path = request.url().uri().getPath();
final Response response = chain.proceed(request);
String body = response.body().string();
final JsonElement element = new JsonParser().parse(body);
if ("/the/endpoint/you/want/to/modify".equals(path)){
final JsonObject object = element.getAsJsonObject();
// v v v v v v All this for these lines v v v v v v v
object.addProperty("some_json_name","some_json_value");
object.addProperty("existing_property","updated_value");
object.addProperty("numbers_work_too",1.2);
// ^ ^ ^ ^ ^ ^ All this for these lines ^ ^ ^ ^ ^ ^ ^
body = object.toString();
}
return response.newBuilder().body(ResponseBody.create(response.body().contentType(), body)).build();
});
JSONObject postdata = new JSONObject();
try {
postdata.put("citizenId", "2222222222222");
postdata.put("accuracy", 3043.323);
postdata.put("provider", "wifi");
postdata.put("gpsTime", 1111111111111L);
postdata.put("lat", 23434.564);
postdata.put("lng", 34343.5445);
postdata.put("appId", "201");
} catch(JSONException e){
// TODO Auto-generated catch block
e.printStackTrace();
}
RequestBody body = RequestBody.create(MEDIA_TYPE,postdata.toString());
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
final OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();
// final OkHttpClient client = new OkHttpClient.Builder().addInterceptor(interceptor).build();
final Request request = new Request.Builder()
.url(base_url)
.post(body)
.addHeader("Content-Type", "application/json")
.addHeader("Authorization", "JWT eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJvd25lcklkIjoyLCJvd25lclR5cGUiOiJMRUFERVIiLCJpYXQiOjE1MDE4Mjc4MDMsImV4cCI6MzMwMzc4Mjc4MDMsImF1ZCI6InNlbmRpdC5hc2lhIiwiaXNzIjoic2VsZiJ9.3Gpn3beZfdYsMOLTjksLwmxyfbrfqiojdm1n-gh6CXY")
.addHeader("cache-control", "no-cache")
.build();
client.newCall(request).enqueue(new Callback() {
#SuppressLint("LongLogTag")
#Override
public void onResponse(Call call, Response response) throws IOException {
try {
// response = client.newCall(request).execute();
// Protocol protocol = response.protocol();
// assertEquals(Protocol.HTTP_1_1, protocol);
// BufferedSource source = response.body().source();
// source.request(Long.MAX_VALUE); // Buffer the entire body.
// Buffer buffer = source.buffer();
// String responseBodyString = buffer.clone().readString(Charset.forName("UTF-8"));
if(response.code() == 200) {
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("code",200);
jsonObject.put("status","OK");
jsonObject.put("message","Successful");
MediaType contentType = response.body().contentType();
ResponseBody body = ResponseBody.create(contentType, jsonObject.toString());
BufferedSource source = response.body().source();
source.request(Long.MAX_VALUE); // Buffer the entire body.
Buffer buffer = source.buffer();
String responseBodyString = buffer.clone().readString(Charset.forName("UTF-8"));
Log.e("response body responseBodyString ", body.string());
Log.e("response body responseBodyString ", responseBodyString);
} catch (JSONException e) {
e.printStackTrace();
}
Log.e("response", String.valueOf(response));
Log.e("response body", String.valueOf(response.body()));
} }catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void onFailure(Call call, IOException e) {
Log.e("response onFailure ", String.valueOf(e));
}
});

Perform OkHttp network actions in background thread

I am using OKHttp to perform Post request to server, as follow:
public class NetworkManager {
public static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
OkHttpClient client = new OkHttpClient();
String post(String url, JSONObject json) throws IOException {
try {
JSONArray array = json.getJSONArray("d");
RequestBody body = new FormEncodingBuilder()
.add("m", json.getString("m"))
.add("d", array.toString())
.build();
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
Response response = client.newCall(request).execute();
return response.body().string();
} catch (JSONException jsone) {
return "ERROR: " + jsone.getMessage();
}
}
}
and call it with:
NetworkManager manager = new NetworkManager();
String response = manager.post("http://www.example.com/api/", jsonObject);
When I try to run the App, it prompts an error in the logcat:
android.os.NetworkOnMainThreadException
at
android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1273)
With reference to other questions in SO, I added this to override the policy:
if (android.os.Build.VERSION.SDK_INT > 9)
{
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}
Yet I think this is unhealthy and I would like to put the NetworkManager actions to background. How can I do so?
Since OkHttp supports async way too, so IMO you can refer to the following GET request sample, then apply for your POST request:
OkHttpClient client = new OkHttpClient();
// GET request
Request request = new Request.Builder()
.url("http://google.com")
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Request request, IOException e) {
Log.e(LOG_TAG, e.toString());
}
#Override
public void onResponse(Response response) throws IOException {
Log.w(LOG_TAG, response.body().string());
Log.i(LOG_TAG, response.toString());
}
});
Hope it helps!

Post data to server with okhttp

How can I post data from my android app to php server with okhttp? Is it even possible? I've been able to retrieve data from the server, but I need to send String from my application to the server.
Thanks.
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder().url(requestUrl).build();
Call call = client.newCall(request);
try {
Response response = call.execute();
if(response.isSuccessful()){
Log.v("LOGV", response.body().string());
}
} catch (IOException e) {
e.printStackTrace();
Log.v("LOGV", e.getMessage().toString());
}
Here is example from okhttp website:
public static final MediaType JSON
= MediaType.parse("application/json; charset=utf-8"); //defines the type of the body
OkHttpClient client = new OkHttpClient();
String post(String url, String json) throws IOException {
RequestBody body = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.url(url)
.post(body) //include the body in the request with the POST method
.build();
Response response = client.newCall(request).execute();
return response.body().string();
}
And a link to their github repo with similar example: https://raw.githubusercontent.com/square/okhttp/master/samples/guide/src/main/java/com/squareup/okhttp/guide/PostExample.java

Categories

Resources