Android Retrofit adding shared preference value in end point - android

I am new in using retrofit in android. I have a get request which is working in a good manner but I want to include the value of shared preference in the endpoint of the URL. Suppose my end point Url is :
public interface Data{
#GET("/myphone/extra/pull/Sharedpreferencevalue") //add shared preference value here
}
Can I do this in retrofit or I have to do with some other way? or how it can be done in retrofit?

You can add parameters dynamically as follows:
#GET("/myphone/extra/pull/{Sharedpreferencevalue}")
Call<YourResponseClass> getData(#Path("Sharedpreferencevalue") String value);

You can use #Path annotation to programmatically add value to the endpoint, and do something like this in your with retrofit Service interface:
#GET("/myphone/extra/pull/{sharedprefValue}")
Call<EntityName> getPref(#Path("sharedprefValue") String pref);

Use urls dynamically to retrofit2 as follows.
in your interface
#GET
public Call<ResponseBody> fetchMileage(#Url String url);
use it this way
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl(ROOT_URL)
.addConverterFactory(GsonConverterFactory.create());
Retrofit retrofit = builder.client( httpClient.build()).build();
MyInterface myInterface = retrofit.create(MyInterface.class);
Call<ResponseBody> result = myInterface.fetchMileage(endpointUrl);
result.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
String output ="";
if (response.isSuccessful()) {
try {
output = response.body().string();
}catch (IOException e)
{
e.printStackTrace();
}
}else{
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable throwable) {
//Toast.makeText(context,"Error "+throwable.getMessage(),Toast.LENGTH_LONG).show();
throwable.printStackTrace();
}
});

Related

How to get data from Response Header using Retrofit,okHttp client [duplicate]

I am using Retrofit with the OkHttp Client and Jackson for Json Serialization and want to get the header of the response.
I know that i can extend the OkClient
and intercept it. But this comes before the deserialization process starts.
What i basically needs is to get the header alongside with the deserialized Json Object.
With Retrofit 1.9.0, if you use the Callback asynchronous version of the interface,
#GET("/user")
void getUser(Callback<User> callback)
Then your callback will receive a Response object
Callback<User> user = new Callback<User>() {
#Override
public void success(User user, Response response) {
}
#Override
public void failure(RetrofitError error) {
}
}
Which has a method called getHeaders()
Callback<User> user = new Callback<User>() {
#Override
public void success(User user, Response response) {
List<Header> headerList = response.getHeaders();
for(Header header : headerList) {
Log.d(TAG, header.getName() + " " + header.getValue());
}
}
For Retrofit 2.0's interface, you can do this with Call<T>.
For Retrofit 2.0's Rx support, you can do this with Observable<Result<T>>
In Retrofit 2.0.0, you can get header like this:
public interface Api {
#GET("user")
Call<User> getUser();
}
Call<User> call = api.getUser();
call.enqueue(new Callback<User>() {
#Override
public void onResponse(Call<User> call, Response<User> response) {
// get headers
Headers headers = response.headers();
// get header value
String cookie = response.headers().get("Set-Cookie");
// TODO
}
#Override
public void onFailure(Call<User> call, Throwable t) {
// TODO
}
});
Much like you I wanted the headers along side of the payload. I needed access to the Etag. It takes some retro-foo, but you can do it. here's what I did. It's a dirty sample so dont take this as a best practices sample.
public static RestAdapter.Builder getRestBuilder(Context context) {
GsonBuilder gsonBuilder = GsonBuilderUtils.getBuilder();
Gson gson = gsonBuilder.create();
// **
// 1. create our own custom deserializer here
// **
final MyGsonConverter gsonConverter = new MyGsonConverter(gson);
OkHttpClient httpClient = MyPersonalOkHttpFactory.getInstance().getAuthHttpClient(context);
httpClient.networkInterceptors().add(new Interceptor() {
#Override
public Response intercept(Chain chain) throws IOException {
Request originalRequest = chain.request();
Response response = chain.proceed(originalRequest);
// **
// 2. add the headers from the Interceptor to our deserializer instance
// **
gsonConverter.headers = response.headers();
return response;
}
});
RestAdapter.Builder builder = new RestAdapter.Builder()
.setClient(new OkClient(httpClient))
.setEndpoint(Common.getApiOriginUrl())
.setConverter(gsonConverter);
return builder;
}
private static class MyGsonConverter extends GsonConverter {
private Headers headers;
public MyGsonConverter(Gson gson) {
super(gson);
}
#Override
public Object fromBody(TypedInput body, Type type) throws ConversionException {
Object obj = super.fromBody(body, type);
// **
// 3. at this point, gson is called and you have access to headers
// do whatever you want here. I just set it on the return object.
// **
if (obj instanceof HeadersArrayList) {
((HeadersArrayList)obj).setHeaders(headers);
}
return obj;
}
}
public class HeadersArrayList<K> extends ArrayList<K>{
private Headers headers;
public Headers getHeaders() {
return headers;
}
public void setHeaders(Headers headers) {
this.headers = headers;
}
}
// the retrofit api for reference
#GET("/api/of/my/backend/{stuff}")
HeadersArrayList<String> getSomething(#Path("stuff") String stuff);
First print the entire response, body, code, message, header(by logging or something else) and try to find a clue from there.
I would recommend you to read the API docs and see the type of request it is asking for.
Use Postman to check which one of the following is working:
1.form-data
2.x-www-form-Urlencoded
3.raw
4.binary
And then accordingly set the annotations in the method declarations in the interface.
eg: in my case, it was taking x-www-form-Urlencoded so I had to mention it using
#FormUrlEncoded
#Headers("Content-Type: application/x-www-form-urlencoded")
in the method declaration.
Then used #Field annotations for individual value I was sending
like
Call<'ReturnObj'> Signup(#Field("name") String name, #Field("phoneNumber") long phoneNumber, #Field("password") String password, #Field("counter") int counter);

Retrofit server response is getting 307 in android

Step1:
Need to give input to server.as below image
step2:
get response from server ,as below image.
![enter image description here][2]
step3:
MainActivity.java
#RequiresApi(api = Build.VERSION_CODES.O)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ApiInterface.URL_BASE)
.addConverterFactory(GsonConverterFactory.create())
.build();
ApiInterface apiInterface = retrofit.create(ApiInterface.class);
// prepare call in Retrofit 2.0
try {
JSONObject paramObject = new JSONObject();
paramObject.put("merchant_id", "aaaaa");
paramObject.put("secret_key", "bbbbb");
Call<RequestBody> userCall = apiInterface.getUser(paramObject.toString());
userCall.enqueue(this);
} catch (JSONException e) {
e.printStackTrace();
}
}
#Override
public void onResponse(Call<RequestBody> call, Response<RequestBody> response) {
Log.d("TEST","TEST--onResponse1---"+call);
Log.d("TEST","TEST--onResponse2---"+response);
}
#Override
public void onFailure(Call<RequestBody> call, Throwable t) {
Log.d("TEST","TEST--onFailure1--"+call);
Log.d("TEST","TEST--onFailure1--"+t);
}
========================================================
step4: ApiInterface.hava
public interface ApiInterface {
#Headers("Content-Type: application/json")
Call<RequestBody> getUser(#Body String body);
}
Log is going to "onResponse.code()" is getting 307" but i count able
to get proper data.
I am new to Retrofit service.Can please help me.
You can't send String to Retrofit without using some other library.
Since you're using Gson already. Create a class that Gson can serialize.
class Credentials {
#SerializedName("merchant_id")
public String merchantId;
#SerializedName("secret_key")
public String secretKey;
}
Interface method. #Notice the input type.
#Headers("Content-Type: application/json")
Call<RequestBody> getUser(#Body Credentials credentials);
307 is Temporary Redirect - and you might have to follow that redirect.
Which means, that you need to configure the OkHttpClient to do so:
OkHttpClient client = new OkHttpClient.Builder()
.followSslRedirects(true)
.followRedirects(true)
.build();
and then set it as the client for retrofit2:
retrofit = new retrofit2.Retrofit.Builder()
.baseUrl(Constants.API_BASE_URL)
.client(client)
.build();

Result disappeared in retrofit 2.4.0

I want to use retrofit for fetching data from my server. My server send data as a string json.
I create a server like this:
public class ServiceGenerator {
public static final String BASE_URL = "http://192.168.100.73/ChartReport/Service1.svc/";
static OkHttpClient okHttpClient = new OkHttpClient.Builder()
.connectTimeout(1, TimeUnit.MINUTES)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(15, TimeUnit.SECONDS)
.build();
private static Retrofit.Builder builder =
new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(okHttpClient)
.addConverterFactory(GsonConverterFactory.create());
private static Retrofit retrofit = builder.build();
public static <S> S createService(Class<S> serviceClass) {
return retrofit.create(serviceClass);
}
}
And then i have created client like blow:
public interface IReportCLient {
#POST("json/GetDataReport")
Call<ResponseBody> getReporst();
}
And I have used into my activity :
IReportCLient service = ServiceGenerator.createService(IReportCLient.class);
Call<ResponseBody> reporst = service.getReporst();
reporst.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
try {
JsonObject post = new JsonObject().get(response.body().string()).getAsJsonObject();
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
}
});
When I run my app in debug mode for first time i fetch my data by this command:
response.body().string()
but immediately my result is null when i run response.body().string() again??
What is happens?
string() method can only be called once on RequestBody. So it will return empty string if you try to call it again. This is true for debugging as well. If you try to evaluate expressions response.body().string() while debugging, your actual methods will get empty string.
An HTTP response. Instances of this class are not immutable: the
response body is a one-shot value that may be consumed only once and
then closed. All other properties are immutable.
https://square.github.io/okhttp/3.x/okhttp/okhttp3/Response.html
Read this as well https://stackoverflow.com/a/32307866/6168272
This is how I get JsonObject from my response object. You can give it a try.
private JSONObject parseJsonFromResponse(Response response) {
ResponseBody responseBody = response.body();
if (responseBody != null) {
try {
return new JSONObject(responseBody.string());
} catch (JSONException | IOException e) {
e.printStackTrace();
return new JSONObject();
}
} else return new JSONObject();
}

How to send Json-rpc via retrofit2?

I tried send json-rpc via retrofit2.
This is my interface:
public interface ApiInterfaceJson {
#POST
#Headers( "Content-Type: application/json" )
Call<String> getDataJson(
#Url String url,
#Body RequestBody body);
}
Create retrofit:
retrofitJson = new Retrofit.Builder()
.addConverterFactory(ScalarsConverterFactory.create())
.baseUrl("http://localhost:8800")
.client(client)
.build();
apiInterfaceJson = retrofitJson.create(ApiInterfaceJson.class);
Call:
JSONObject paramObject = new JSONObject();
try {
paramObject.put("id", "0");
paramObject.put("name", "user");
paramObject.put("command", "finish");
}catch(Exception e){
}
RequestBody requestBody= RequestBody.create(MediaType.parse("application/json"), paramObject.toString());
MinersMonitorApplication.getApiJson().getDataJson("http://10.10.10.230:10000", requestBody).enqueue(new Callback<String>() {
#Override
public void onResponse(#NonNull Call<String> call, #NonNull Response<String> response) {}
#Override
public void onFailure(Call<String> call, Throwable t) {
}
});
The result is SocketTimeoutException.
You need RPC wrapped retrofit - https://github.com/segmentio/retrofit-jsonrpc
Also let service see that it should use json RPC by annotating:
interface MultiplicationService {
#JsonRPC("Arith.Multiply") #POST("/rpc")
Call<Integer> multiply(#Body MultiplicationArgs args);
}
Note that Retrofit is only REST Based library.

Simple login form with Retrofit

I'm starting to work with Retrofit but I'm stuck on this simple step. I have a login form and I'm trying to authenticate with the server but I just can't send the request.
This is what I've tried:
My Retrofit client:
private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
private static Retrofit.Builder builder =
new Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create());
public static <S> S createService(Class<S> serviceClass) {
Retrofit retrofit = builder.client(httpClient.build()).build();
return retrofit.create(serviceClass);
}
My login interface:
public interface Login {
#POST(LOGIN)
Call<String> loginWithCredentials(#Body LoginCredentials data);
}
The LoginCredentials class:
public class LoginCredentials {
private String name;
private String pass;
public LoginCredentials(String name, String pass) {
this.name = name;
this.pass = pass;
}
}
And the part where I call it:
#Override
public void onClick(View v) {
showProgress(true);
String username = userField.getText().toString();
String password = passField.getText().toString();
ApiController.Login loginClient = ApiController.createService(ApiController.Login.class);
Call<String> call =loginClient.loginWithCredentials(new LoginCredentials(username, password));
call.enqueue(new Callback<String>() {
#Override
public void onResponse(Call<String> call, Response<String> response) {
handleResponse(response.body());
}
#Override
public void onFailure(Call<String> call, Throwable t) {
showProgress(false);
Log.e(TAG, t.getLocalizedMessage());
}
});
}
And I keep getting the error Use JsonReader.setLenient(true) to accept malformed JSON at line 1 column 1 path $but I have no idea what it means.
I figured it out. It was easier than I thought. You can skip the parsing that Retrofit does by setting the response type of the method as ResponseBody. Them you just need to read the response and use the string() method that provides. That's it!
Example:
public interface Login {
#POST(LOGIN)
Call<ResponseBody> loginWithCredentials(#Body LoginCredentials data);
}
Then use like this:
String username = userField.getText().toString();
String password = passField.getText().toString();
ApiController.Login loginClient = ApiController.createService(ApiController.Login.class);
Call<ResponseBody> call = loginClient.loginWithCredentials(new LoginCredentials(username, password));
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if (response.isSuccessful()) {
try {
// get String from response
String stringResponse = response.body().string();
// Do whatever you want with the String
} catch (IOException e) {
e.printStackTrace();
}
}
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
// handle error
}
});
This error means that gson trying to parse string from server as JSON object and can't find the opening bracket.
I think you could return actual JSON from server like
{"api_token": "token"}
Also this bug could possibly be solved by importing latest GSON version mentioned here

Categories

Resources