Post data to server with okhttp - java

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

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();
}

Go from OkHttp to HttpURLConnection

For reasons of library compatibility issues I would like to use HttpURLConnection to call requests on an API.
Here is the code I use with OkHttp to get a token access:
private void getAccessToken(){
OkHttpClient okHttpClient = new OkHttpClient();
RequestBody requestBody = new FormEncodingBuilder().add("grant_type", "authorization_code")
.add("client_id", "1568xxxxxxxxxxxxxxxxxjro.apps.googleusercontent.com")
.add("client_secret", "AMe0xxxxxxxxxxxx")
.add("redirect_uri", "")
.add("code", serverCode)
.build();
Request request = new Request.Builder()
.url("https://www.googleapis.com/oauth2/v4/token")
.post(requestBody)
.build();
okHttpClient.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(Request request, IOException e) {
Log.i("severcode","failure");
}
#Override
public void onResponse(Response response) throws IOException {
try {
JSONObject jsonObject = new JSONObject(response.body().string());
token = jsonObject.optString("access_token");
tokenExpired = SystemClock.elapsedRealtime() + jsonObject.optLong("expires_in") * 1000;
Log.i("severcode",String.valueOf(token));
createGooglePhotosClient();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
So I would like to know how to get the equivalent of requestbody to pass it in setRequestProperty ()?
Thanks for your help
The request body is not a request property (header), it's the body of the request, and without OkHttp or other supporting libraries you have to format it yourself, encode any special characters that need to be encoded etc.
String requestBody = "grant_type=authorization_code&client_id=1568xxxxxxxxxxxxxxxxxjro.apps.googleusercontent.com&"
+ "client_secret=AMe0xxxxxxxxxxxx&redirect_uri=&code=" + serverCode + "\n\n";
byte[] requestBodyBytes = requestBody.getBytes("UTF-8");
Once you have the request body, you write it to the connection's output stream. For example:
connection.setRequestProperty("content-type", "application/x-www-form-urlencoded");
connection.setDoOutput(true);
out = connection.getOutputStream();
out.write(requestBodyBytes)
out.flush();

Retrofit POST. Add JSON parameter to every post request

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);
}

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

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!

Categories

Resources