Retrofit + GET method + www-form-urlencoded in Android - android

I am trying to fetch a list from a server. Problem is, Retrofit 2.0 is converting my request to an encoded request which is not acceptable to my server. So I need to remove that automatic encoding from the request. I have tried almost all solutions by putting encoded = true/false in the Request but it's not working at all.
Now, the situation is: All things are working good with "POST" Requests. Is there any similar way to do it with a "GET" Call? GET requests giving me "400 Bad Request" due to the encoded URL. The Main Issue with Encoding in GET.
POST call:
Working POST
#FormUrlEncoded
#POST("login")
Call<UserBean> getLogin(#FieldMap Map<String,String> params);
POST ENCODED URL:(working)
https://---.---.com/---/webservice/login?
jhobject=%7B%22data%22%3A%22%7B%5C%22username%5C%22%3A%5C%22abz%40cbv.com%5C%22%2C%5C%22password%5C%22%3A%5C%221234%40567%5C%22%2C%5C%22manufacturername%5C%22%3A%5C%22Android%5C%22%2C%5C%22modelname%5C%22%3A%5C%22XT1068%5C%22%2C%5C%22osversion%5C%22%3A%5C%223.4.42-g0a0ded4%5C%22%2C%5C%22countrycode%5C%22%3A%5C%22in%5C%22%2C%5C%22appversion%5C%22%3A%5C%221.0%5C%22%2C%5C%22imei%5C%22%3A%5C%22353325060286683%5C%22%2C%5C%22appfor%5C%22%3A%5C%22Sony%5C%22%7D%22%2C%22enc%22%3A%220%22%7D
Not Working GET
#Headers({"Content-Type:application/x-www-form-urlencoded"})
#GET("getlisting")
Call<MyBean> getListing(#QueryMap Map<String,String> params);
GET ENCODED URL:(Not working)
https://---.---.com/---/webservice/getlisting?
jhobject=%257B%2522data%2522%253A%257B%2522pageno%2522%253A%25221%2522%252C%2522totalpages%2522%253A%25220%2522%252C%2522recordperpages%2522%253A%252210%2522%252C%2522cstatus%2522%253A%25221%2522%252C%2522reportid%2522%253A%252253%2522%257D%252C%2522enc%2522%253A%25220%2522%252C%2522token%2522%253A%252209046d74-c047-4534-be0b-050dadad18b8%257E%257E23717%2522%257D

You are doing double encoding
in post
jhobject=%7B
in get
jhobject=%257B

I experienced same problem until I remove this line #FormUrlEncoded it seems like GET don't need to be encoded or what I don't understand that part
You may wanna remove this line on your code and try it #Headers({"Content-Type:application/x-www-form-urlencoded"})

I experienced same problem with GET and retrofit, here is the solution with retrofit
1- Load URL server :
Retrofit retrofit = new Retrofit.Builder().baseUrl("URL")
.addConverterFactory(GsonConverterFactory.create()).build();
service = retrofit.create(CallApiService.class);
2- Load config api :
public interface CallApiService {
#GET("URI")
Call<ResponseBody> getProfessions( #Header("x-req-user-id") String x_req_user_id);
}
3- Call api and mapping data:
RetrofitLoader retrofitLoader = new RetrofitLoader();
CallApiService service = retrofitLoader.getServiceLoader();
Call<ResponseBody> retrofitCall = service.getProfessions("8");
LOGGER.info("conncet to url : GET " + retrofitCall.request().url());
Response<ResponseBody> response;
try {
response = retrofitCall.execute();
if (!response.isSuccessful())
throw new IOException("Unexpected code " + response);
String responseData = response.body().string();
LOGGER.info("getProfessions Data : " + responseData);
try {
JSONObject jsonObject = new JSONObject(responseData);
return jsonObject.toString();
} catch (JSONException e) {
LOGGER.error("Error jsonObject : " + e);
}
} catch (IOException e) {
e.printStackTrace();
}
return "";

Related

post request with retrofit gets responce a s bad request in android

I am using https://docs.ngenius-payments.com/reference#hosted-payment-page for payment in android
Headers:
Add these headers to your request (note that you should replace 'your_api_key' with the service account API key in the Getting started section).
Header Value
Content-Type application/vnd.ni-identity.v1+json
Authorization Basic: your_api_key
Body / Form Data:
Add the following information to the form/body content of your request.
Example request (body):
JSON
{
‘realmName’: ‘ni’
}
these are the headers and content type and i created a post method using retrofit
public static Retrofit getRetrofitClient() {
//If condition to ensure we don't create multiple retrofit instances in a single application
if (retrofit == null) {
//Defining the Retrofit using Builder
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL) //This is the only mandatory call on Builder object.
.addConverterFactory(GsonConverterFactory.create()) // Convertor library used to convert response into POJO
.build();
}
return retrofit;
}
My api interface is
#POST("identity/auth/access-token")
Call<NgeniusPaymentAccessTokenModel> nGeniusAccessToken(#Header("content-type") String ContentType, #Header("authorization") String apiKey, #Body JsonObject object);
and i call it by
JsonObject postParam = new JsonObject();
try {
postParam.addProperty("realmName", "ni");
} catch (Exception e) {
e.printStackTrace();
}
Call call = apiService.nGeniusAccessToken(contentType, "Basic "+apiKey, postParam);
i am getting the responce as error telling its a bad request, how to solve this
You can try below code:
String contentType = "application/vnd.ni-identity.v1+json";
String authorization = "Basic: "+apiKey;
JSONObject postParam = new JSONObject();
try {
postParam.put("realmName", "ni");
} catch (JSONException e) {
e.printStackTrace();
}
Call call = apiService.nGeniusAccessToken(contentType, authorization, postParam);
this one worked for me i put all of the headers in a header map
creata a map
Map<String, String> stringMap = new HashMap<>();
try {
stringMap.put("Authorization", "auth");
stringMap.put("Content-Type", "CONTENT_TYPE");
stringMap.put("accept", "accept");
} catch (Exception e) {
e.printStackTrace();
}
api interface looks like
#POST("transactions/orders")
Call<ResponseBody> nCreateOrder(#HeaderMap Map<String, String> headers,String out, #Body JsonObject object);
now call it by
nCreateOrder(stringMap ,"out",jsonObject);

I want to send data to the server and retrieve data from server to device

I am new learner of android app, I want to send data to the server and retrieve data from server to device , how can i do it ? and which server is best? thanks
i think You are asking for send data from android app to web server and received data from web Server.
You can use php in server side and received post Or get method Parameter
and while sending data to Phone use Json.
json is light weighted and easy to parse in android
Search google For RestAPI for Android app using Php
You can use Network library to call server: (In this I used OkHttp3 library)
for request to server:
try {
OkHttpClient okHttpClient = new OkHttpClient();
String url = "url";
MultipartBody.Builder builder = new MultipartBody.Builder()
.setType(MultipartBody.FORM).addFormDataPart("key", value);
MultipartBody requestBody = builder.build();
Request request = new Request.Builder()
.url(url)
.post(requestBody).build();
Response response = okHttpClient.newCall(request).execute();
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);
data = response.body().string();
Log.d("msg", "TIcket Data : " + data);
} catch (Exception e) {
e.getStackTrace();
}
Now parse the data which you got from the server: (According to server response whether it's jsonobject or jsonarray or string)
try {
JSONObject jsonObject = new JSONObject(data);
Log.d("msg", jsonObject.toString());
} catch (Exception e) {
e.getStackTrace();
}

Okhttp Put method returning 'Method Not Allowed'

I am attempting to call a put method on my server using OkHttp from an Android application.
This is the api method signature:
public void Put(int userId, string regId)
{
}
This is the Android code to call the above method:
private boolean SendGCMRegIdToServer(String registrationId, Integer userId) throws IOException {
HttpUrl url = new HttpUrl.Builder()
.scheme("http")
.host(serverApiHost)
.addPathSegment("AppDashboard")
.addPathSegment("api")
.addPathSegment("GCM/")
.build();
MediaType JSON
= MediaType.parse("application/json; charset=utf-8");
String json = "{'userId':" + userId + ","
+ "'regId':'" + registrationId + "'"
+ "}";
RequestBody requestBody = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.url(url)
.put(requestBody)
.build();
//this should post the data to my server
Response response = client.newCall(request).execute();
if(response.code() == 400)
return false;
return true;
}
Now the problem is I am getting the error code 405 in the response saying Method not allowed, but I cannot see where the problem is because I can successfully call the method using Postman on the server itself as below:
http://localhost/AppDashboard/api/GCM?userId=5&regId=123
I'm thinking it may have something to do with an integer or string being passed incorrectly in the JSON string, but cannot see why this isn't working.
i had the same problem and server was returning 405 . after some search i realized that is a configuration problem on IIS that does not let put requests. so there is no problem in android code and you should config your server to let this kind of requests.
see this , this and this
Ok thanks for replies guys but seems I was getting a little confused between the two methods I was using to pass the params to my API.
Here's what I did:
changed the signature of the method to post with a param [FromBody] as a Model (only supports one paramater)...
public void Post([FromBody]UserGcmRegIdModel model)
{
}
I was then able to change my method call to the following using a nicer JSONBuilder and using .post in the request builder rather than .put
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("UserId", userId);
jsonObject.put("RegId", registrationId);
} catch (JSONException e) {
e.printStackTrace();
}
String json = jsonObject.toString();
RequestBody requestBody = RequestBody.create(JSON, json);
Request request = new Request.Builder()
.url(url)
.post(requestBody)
.build();
I still don't know if there is a problem with put() methods on IIS but using a post in my case was absolutely fine so I'm going with that...
I see two different approaches in your REST api calls. In the one of OkHttp you send a PUT method with a JSON object serialized, and in POSTMAN you send a PUT (although I guess you do a GET) request with the parameters within the URL, I mean not in JSON body structure.
Anyway, HTTP 405 is telling you that your backend does not support the PUT method, and probably it's expecting a POST method with the "X-HTTP-Method-Override:PUT" HTTP header since POST is more standard method in REST than PUT.
What would I do is check your POSTMAN request carefully and adjust the one of Android to be the same method, parameters and headers, not more.
Answer Update (as question has been updated)
Of course there is a problem with that verb, as I said above IIS handles only the standard methods and PUT is not one of those. You have three choices:
Change your PUT to POST.
Use POST with X-HTTP-Method-Override to PUT. (reference)
Modify IIS config to support non standard REST methods. I
personally wouldn't suggest the 3rd one, since it's attached to the
backend config (e.g. imagine you change IIS to NancyFX).

OkHttp Android JSonObject casting exception

When I use OkHttp to post I get a response like this (Instagram api)
{"access_token":"2222222.22222.2222222","user":{"username":"xxx","bio":"","website":"","profile_picture":"https:\/\/instagramimages-a.akamaihd.net\/profiles\/anonymousUser.jpg","full_name":"Test","id":"222222"}}
which I am unable to cast to a JsonObject (I think it is because of the weird way the urls are formatted).
But when I use HttpsUrlConnection everything works fine.
OkHTTP
private final OkHttpClient client = new OkHttpClient();
public static final MediaType MEDIA_TYPE_MARKDOWN
= MediaType.parse("text/plain");
//then in a function
String postBody="client_id="+Application.INSTAGRAM_CLIENT_ID
+"&client_secret="+Application.INSTAGRAM_SECRET_KEY
+"&grant_type=authorization_code"
+"&redirect_uri=" +Application.CALLBACKURL
+"&code=" + SharedPrefHelper.getSharedPerferenceData(context, SharedPrefHelper.SHARED_PREFERENCE_KEY_INSTAGRAM_CODE, "");
Request request = new Request.Builder()
.url(Application.TOKENURL)
.post(RequestBody.create(MEDIA_TYPE_MARKDOWN,postBody))
.build();
I use response.body.string() in the callback method to get the string and cast it to JsonObject.
if (response.code() == 200) {
try {
JSONObject jsonObject = new JSONObject(response.body().string());
} catch (JSONException e) {
}
}
How to fix this ?
ERROR :
org.json.JSONException: End of input at character 0 of
You can only use response.body().string() only once. I was calling it twice. First for logging the response and then again for json casting.
First thing:
You are probably getting a blank response. Its not null but the response is empty. So you are getting this error and not a NullPointerException
Have you logged it before converting in JSON? Checked it.
Second Thing:
You may have to try with GET if you are used POST currently or Vice Versa.

How do I send JSon as BODY In a POST request to server from an Android application?

I am working on my first Android Application. What I am trying to do is a POST request to a REST service I want the BODY of this request to be a JSON String.
I am using google's GSON to generate the JSON that is sent to the server. Here is the code doing POST request:
HttpPost requisicao = new HttpPost();
requisicao.setURI(new URI(uri));
requisicao.setHeader("User-Agent", sUserAgent);
requisicao.setHeader("Content-type", "application/json");
HttpResponse resposta = null;
//I can see the json correctly print on log with the following entry.
Log.d(TAG, "JSon String to send as body in this request ==>> " + jsonString);
//than I try to send JSon using setEntityMethod
StringEntity sEntity = new StringEntity(jsonString, "UTF-8");
requisicao.setEntity(sEntity);
resposta = httpClient.execute(requisicao);
resultado = HttpProxy.leRespostaServidor(resposta);
The response code is 400 BAD REQUEST and from the server log I can read the info. where it says the body was not correctly sent:
13:48:22,524 ERROR [SynchronousDispatcher] Failed executing POST /peso/cadastrar/maia.marcos#gmail.com
org.jboss.resteasy.spi.BadRequestException: Could not find message body reader for type: class java.io.Reader of content type: application/json
The code for the server side is a simple Seam Rest Service:
#POST
#Path("/cadastrar/{userEmail}")
#Consumes(MediaType.APPLICATION_JSON)
public String cadastraPeso(#PathParam("userEmail") String email, Reader jsonString)
{
LineNumberReader lnr = new LineNumberReader(jsonString);
try {
String json = lnr.readLine();
if(json != null)
{
log.debug("String json recebida do device ==>> " + json);
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return "OK - o e-mail processado foi ==>> " + email;
}
What could be wrong with the Android client code? I have researched the web and did not find any really useful information about this error.
[]s
Sorry folks, just turned out that the error was on the Rest service. I had change it and now it receives a String instead of the Reader object and it works as expected, the REST endpoint code on the server side now is:
#POST
#Path("/cadastrar/{userEmail}")
#Consumes(MediaType.APPLICATION_JSON)
public String cadastraPeso(#PathParam("userEmail") String email, String jsonString)
{
String json = jsonString;
if(json != null)
{
log.debug("String json received from device ==>> " + json);
}
return "OK - processed email ==>> " + email;
}
And the JSON string is correctly received on server side.
So de Android code above is working as expected.

Categories

Resources