Retrofit response returning null in get method - android

I have a url like this
http://182.72.198.001:8080/MyLogin/login/xxxxxx/yyyyyy
userName : xxxxxx
password : yyyyyy
I am using retrofit to get the above url response but it returning null my retrofit class is
public class ApiClient {
public static Retrofit retrofit = null;
public static Retrofit getApiCLient() {
if (retrofit == null) {
retrofit = new Retrofit.Builder().baseUrl("http://182.72.198.001:8080/MyLogin/").addConverterFactory
(GsonConverterFactory.create()).build();
}
return retrofit;
}
}
and myInterface class is
public interface MyInterface {
#GET("login/")
Call<ResponseBody> LoginValidation(#Query("userName") String username, #Query("password") String password);
}
My main class is
MyInterface loginInterface;
loginInterface = ApiClient.getApiCLient().create(MyInterface.class);
private void LoginUser()
{
final String usedrname = username1.getText().toString();
final String password = password1.getText().toString();
Call<ResponseBody> call = loginInterface.LoginValidation(usedrname,password);
Log.i("Tag","Interface" + usedrname+password);
call.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
Log.i("Tag","Respose" + response.body()); // this body returns null
Toast.makeText(getApplicationContext(), "Thank You!", Toast.LENGTH_SHORT).show();
editor.putString("username",usedrname);
editor.putString("password",password);
editor.putBoolean("isLoginKey",true);
editor.commit();
Intent i=new Intent(MainActivity.this,Navigation.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
Toast.makeText(getApplicationContext(),"Username or password Mismatch",Toast.LENGTH_LONG).show();
}
});
}
How can i solve this am i did anything wrong in this code?

http://182.72.198.001:8080/MyLogin/login/xxxxxx/yyyyyy
If you have to form the above url then you have to send the username and password in url path. So, your Retrofit interface should look like this:
public interface MyInterface {
#GET("login/{userName}/{password}")
Call<ResponseBody> LoginValidation(#Path("userName") String username,
#Path("password") String password);
}

Using
#GET("login/")
Call<ResponseBody> LoginValidation(#Query("userName") String username, #Query("password") String password);
Your URL becomes: http://182.72.198.001:8080/MyLogin/login/?userName=xxxxxx&password=yyyyyy
To exact call as you need, use this (as answered by #Avijit Karmakar )
public interface MyInterface {
#GET("login/{userName}/{password}")
Call<ResponseBody> LoginValidation(#Path("userName") String username,
#Path("password") String password);
}
Using this method you will get the exact result which you want.

Related

How to convert POJO object to json string using gson for a specified field?

I'm using retrofit2 for password recovery, an API request is sent to the server with an email address which is entered by the user.
I'm only setting the email in the POJO ,and after the conversion, the JSON string looks like this:
{"email":"email#email.com", "password":"", "password_confirmation":"", "token":""}
But the JSON I need to send out, should look like this:
{"email":"email#email.com"}
If I'll create another POJO class with an email param then I'll get the required string, but I just want to know if it is possible, using the current POJO.
How would one convert a POJO object to a JSON string using gson for a specified field?
Please Refer to the below code:
public class User {
private String email;
private String password;
private String password_confirmation;
private String token;
public User() {
this.email="";
this.password="";
this.password_confirmation="";
this.token="";
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getPassword_confirmation() {
return password_confirmation;
}
public void setPassword_confirmation(String password_confirmation) {
this.password_confirmation = password_confirmation;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
}
My Api interface
public interface Api{
#POST("/api/password/create")
#Headers({"Accept:application/json", "Content-Type:application/json"})
Call<User> Create(#Body RequestBody requestBody);
}
My Retrofit method
private void authenticateEmail(final Context context) {
User user=new User();
Api api=new Api();
String email = edt_forgot_email.getText().toString().trim();
Gson gson = new GsonBuilder()
.setDateFormat(SERVICE_DATE_FORMAT)
.setLenient()
.create();
api = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
user.setEmail(email);
Gson lGson = new GsonBuilder().setDateFormat(SERVICE_DATE_FORMAT).create();
String jsonString = lGson.toJson(user);
Log.d("debug", "jsonString==>" + jsonString);
final RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), jsonString);
Call<User> call = api.Create(requestBody);
Log.d("debug", "url: " + call.request().url().toString());
call.enqueue(new Callback<User>() {
#Override
public void onResponse(#NonNull Call<User> call, #NonNull Response<User> response) {
Log.d("debug", "responsecode==>" + response.code());
Log.d("debug", "responsebody==>" + response.body());
if (response.code() == 200) {
String msg = "We have emailed you OTP";
Toast.makeText(activity, msg, Toast.LENGTH_SHORT).show();
}
}
#Override
public void onFailure(#NonNull Call<User> call, #NonNull Throwable t) {
Toast.makeText(activity, "server error",Toast.LENGTH_SHORT).show();
}
});
}
Remove this code from constructor :
public User() {
this.email="";
this.password="";
this.password_confirmation="";
this.token="";
}
If you want to exclude empty values from output json, you should make it as null.
Good luck!
You can just create a JSON Object for the single field like this:
JSONObject data =new JSONObject();
data.put("email", email#email.com)
send data object to the retrofit.

Android retrofit response body, jwt in response, how do to get it?

I am using android as my front-end application and Spring boot as server part. I am using android retrofit library to connect with server.
When user logs onto server, he gets response like this.
So how do I extract "accessToken" and "tokenType" from body response?
Here is my login method in android:
private void login(LoginRequest loginRequest) {
OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder();
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
okHttpClientBuilder.addInterceptor(logging);
Retrofit.Builder builder = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.client(okHttpClientBuilder.build());
Retrofit retrofit = builder.build();
RestAPI client = retrofit.create(RestAPI.class);
Call<LoginRequest> call = client.signIn(loginRequest);
call.enqueue(new Callback<LoginRequest>() {
#Override
public void onResponse(Call<LoginRequest> call, Response<LoginRequest> response) {
if (response.code() == 200) {
Toast.makeText(getApplicationContext(), response.body().toString(),
Toast.LENGTH_LONG).show();
Intent i = new Intent(LoginActivity.this, PostsActivity.class);
//response.body should be somewhere here
startActivity(i);
}else{
Toast.makeText(getApplicationContext(), "Uneti podaci nisu dobri",
Toast.LENGTH_LONG).show();
}
}
#Override
public void onFailure(Call<LoginRequest> call, Throwable t) {
}
});
}
This is my LoginRequest class
public class LoginRequest {
private String username;
private String password;
public LoginRequest(String username, String password) {
this.username = username;
this.password = password;
}
}
Create model class for response like below
public class Token {
#SerializedName("tokenType")
private String tokenType;
#SerializedName("accessToken")
private String accessToken;
public String getTokenType() {
return tokenType;
}
public void setTokenType(String tokenType) {
this.tokenType = tokenType;
}
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
}
Then change the Api return type to Call<Token>
Accordingly you also need to modify the call
call.enqueue(new Callback<Token>() {
#Override
public void onResponse(Call<Token> call, Response<Token> response) {
if(response.isSuccessful()) {
Token token = response.body();
}
}
#Override
public void onFailure(Call<Token> call, Throwable t) {
}
});

Is this the right way to set up Basic Authentication with Retrofit 2?

I'm doing a side project and all I know is I should use Basic Authentication. Since I don't have experience using it, I found some stuff online and I want to ask you for your opinion, is this the right way to do it...
So, first thing is from Retrofit's documentation:
This is the Retrofit(network) setup:
public class RetrofitSetup {
public static final String API_BASE_URL = "----";
private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
private static Retrofit.Builder builder =
new Retrofit.Builder()
.baseUrl(API_BASE_URL)
.addConverterFactory(GsonConverterFactory.create());
private static Retrofit retrofit = builder.build();
public static <S> S createService(Class<S> serviceClass) {
return createService(serviceClass, null, null);
}
public static <S> S createService(
Class<S> serviceClass, String username, String password) {
if (!TextUtils.isEmpty(username)
&& !TextUtils.isEmpty(password)) {
String authToken = Credentials.basic(username, password);
return createService(serviceClass, authToken);
}
return createService(serviceClass, null);
}
public static <S> S createService(
Class<S> serviceClass, final String authToken) {
if (!TextUtils.isEmpty(authToken)) {
AuthenticationInterceptor interceptor =
new AuthenticationInterceptor(authToken);
if (!httpClient.interceptors().contains(interceptor)) {
httpClient.addInterceptor(interceptor);
builder.client(httpClient.build());
retrofit = builder.build();
}
}
return retrofit.create(serviceClass);
}
}
And Authentication Interceptor:
public class AuthenticationInterceptor implements Interceptor {
private String authToken;
public AuthenticationInterceptor(String token) {
this.authToken = token;
}
#Override
public Response intercept(#NonNull Chain chain) throws IOException {
Request original = chain.request();
Request.Builder builder = original.newBuilder()
.header("Authorization", authToken);
Request request = builder.build();
return chain.proceed(request);
}
}
This is my RetrofitSerive class:
public interface RetrofitService {
#GET("login")
Call<Void> basicLogin();
#GET("contact")
Call<List<Contacts>> getContacts(#Header("Authorization") String authkey);
#GET("product")
Call<List<Products>> getProducts(#Header("Authorization") String authkey);
}
And the class I found online for generating auth key:
public class Helper {
public static String getAuthToken(String username, String password) {
byte[] data = new byte[0];
try {
data = (username + ":" + password).getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
return "Failed to authenticate";
}
return "Basic " + Base64.encodeToString(data, Base64.NO_WRAP);
}
}
And I believe there is nothing to be changed here... So first thing is to login (check authentication), here is the couple of stuff I want to know how to do right:
private void login(final String username, final String password) {
RetrofitService loginService =
RetrofitSetup.createService(RetrofitService.class, username, password);
Call<Void> call = loginService.basicLogin();
call.enqueue(new Callback<Void>() {
#Override
public void onResponse(#NonNull Call<Void> call, #NonNull Response<Void> response) {
progressBar.setVisibility(View.GONE);
if (response.isSuccessful()) {
// user object available
editor.putString("username", username);
editor.putString("password", password);
editor.apply();
startActivity(new Intent(LoginActivity.this, MainActivity.class));
finish();
} else {
Toast.makeText(LoginActivity.this, response.message(), Toast.LENGTH_SHORT).show();
}
}
#Override
public void onFailure(#NonNull Call<Void> call, #NonNull Throwable t) {
progressBar.setVisibility(View.GONE);
Toast.makeText(LoginActivity.this, t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
If response is successfull, I save those credentials in SharedPreferences..
Next page shuld call another request, so I wonder if there is any difference if I send both username/password or auth key?
This is how I did it:
private void getContacts() {
prefs = getActivity().getSharedPreferences(KEY, MODE_PRIVATE);
String username = prefs.getString("username", null);
String password = prefs.getString("password", null);
RetrofitService loginService =
RetrofitSetup.createService(RetrofitService.class, Helper.getAuthToken(username, password));
Call<List<Contacts>> call = loginService.getContacts(Helper.getAuthToken(username, password));
call.enqueue(new Callback<List<Contacts>>() {
#Override
public void onResponse(#NonNull Call<List<Contacts>> call, #NonNull Response<List<Contacts>> response) {
if (response.isSuccessful()) {
kontaktiAdapter.setKontakti(response.body());
} else {
Toast.makeText(getActivity(), response.message(), Toast.LENGTH_SHORT).show();
}
}
#Override
public void onFailure(#NonNull Call<List<Contacts>> call, #NonNull Throwable t) {
Toast.makeText(getActivity(), t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
So in this call, instead of sending username/password to RetrofitSetup.createService, I'm sending Helper.getAuthToken(username, password) with username and password from SharedPreferences.
Is this the right way to do this? If you exit the app, in login screen I'm checking if SharedPreferences contains username/password and try login with those parameteres.. If I want to log out, I clear those parameters from SharedPreferences so next time user opens the app, SharedPreferences won't contain them, so user won't be logged in, he/she would have to type those again...
What are your thoughts about this, is there anything I should do differently?
Regards!
This is so far the easiest method i have ever tried for "Basic Authentication".
Use the below code to generate the auth header (API/Repository class)
var basic = Credentials.basic("YOUR_USERNAME", "YOUR_PASSWORD")
Pass this as header to the webservice call (API/Repository class)
var retrofitCall = myWebservice.getNewsFeed(basic)
Add the basic header as parameter (Retrofit Webservice interface class)
#GET("newsfeed/daily")
fun getNewsFeed(#Header("Authorization") h1:String):Call<NewsFeedResponse>
Sorry, my code is in Kotlin, but can be easily translated to Java.

Retrofit Post request

I want to post user credentials to following url
: http://myurl/authenticate
Parameters : login. Type (JSON)
username : string
password : string
"login":{"username": "JohnDoe","password": "eoDnhoJ" }
If success
{
" r e s u l t " : " S u c c e s s " ,
"response": "Users Session ID"
}
Here is my code
public interface APIService {
#POST("/authenticate")
#FormUrlEncoded
Call<Login> savePost(#Field("username") String username,
#Field("password") String password);
}
public class ApiUtils {
private ApiUtils() {}
public static final String BASE_URL = "http://myurl/";
public static APIService getAPIService() {
return RetrofitClient.getClient(BASE_URL).create(APIService.class);
}
}
public class Login {
#SerializedName("username")
#Expose
private String username;
#SerializedName("password")
#Expose
private String password;
//getters and setters
}
public class RetrofitClient {
private static Retrofit retrofit = null;
public static Retrofit getClient(String baseUrl) {
if (retrofit==null) {
retrofit = new Retrofit.Builder()
.baseUrl(baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
public class LoginActivity extends AppCompatActivity {
private EditText usernameEditText,passwordEditText;
private Button button;
private APIService mAPIService;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
usernameEditText=(EditText)findViewById(R.id.username);
passwordEditText=(EditText)findViewById(R.id.password);
button=(Button)findViewById(R.id.signup);
mAPIService = ApiUtils.getAPIService();
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String uname=usernameEditText.getText().toString();
String pass=passwordEditText.getText().toString();
if(TextUtils.isEmpty(uname)){
Toast.makeText(LoginActivity.this, "Username cannot be empty", Toast.LENGTH_SHORT).show();
return;
}
if(TextUtils.isEmpty(pass)){
Toast.makeText(LoginActivity.this, "Password cannot be empty", Toast.LENGTH_SHORT).show();
return;
}
if(pass.length()<4){
Toast.makeText(LoginActivity.this, "Password should be greater than four characters", Toast.LENGTH_SHORT).show();
return;
}
sendPost(uname, new StringBuilder(uname).reverse().toString());
}
});
}
public void sendPost(String username, String password) {
mAPIService.savePost(username, password).enqueue(new Callback<Login>() {
#Override
public void onResponse(Call<Login> call, Response<Login> response) {
if(response.isSuccessful()) {
showResponse(response.body().toString());
Log.i("Pritish", "post submitted to API." + response.body().toString());
Intent intent=new Intent(getApplicationContext(), MainActivity.class);
startActivity(intent);
finish();
}
}
#Override
public void onFailure(Call<Login> call, Throwable t) {
Log.e("Pritish", "Unable to submit post to API.");
}
});
}
public void showResponse(String response) {
Log.i("Abbu",response);
}
}
Whenever i submit username and password i get null values,can some body please help me?And how can iget the sessionId.I tried looking for various egs but i am so confsued right now.
Instead of follwing code
#POST("/authenticate")
#FormUrlEncoded
Call<Login> savePost(#Field("username") String username,
#Field("password") String password);
Use this code
#POST("/authenticate")
Call<Login> savePost(#Query("username") String username,
#Query("password") String password);
Step 1: instead of this code
public interface APIService {
#POST("/authenticate")
#FormUrlEncoded
Call<Login> savePost(#Field("username") String username,
#Field("password") String password);
}
Use this code:
public interface APIService {
#POST("/authenticate")
Call<Login> savePost(#Body RequestBody body);
}
Step 2: instead of this code in LoginActivity
public void sendPost(String username, String password) {
mAPIService.savePost(username, password).enqueue(new Callback<Login>() {
#Override
public void onResponse(Call<Login> call, Response<Login> response) {
if(response.isSuccessful()) {
showResponse(response.body().toString());
Log.i("Pritish", "post submitted to API." + response.body().toString());
Intent intent=new Intent(getApplicationContext(), MainActivity.class);
startActivity(intent);
finish();
}
}
#Override
public void onFailure(Call<Login> call, Throwable t) {
Log.e("Pritish", "Unable to submit post to API.");
}
});
}
Change to this code :
public void sendPost(String username, String password) {
HashMap<String, String> params = new HashMap<>();
params.put("username", username);
params.put("password", password);
String strRequestBody = new Gson().toJson(params);
//create requestbody
final RequestBody requestBody = RequestBody.create(MediaType.
parse("application/json"),strRequestBody);
mAPIService.savePost(requestBody).enqueue(new Callback<Login>() {
#Override
public void onResponse(Call<Login> call, Response<Login> response) {
if(response.isSuccessful()) {
showResponse(response.body().toString());
Log.i("Pritish", "post submitted to API." + response.body().toString());
Intent intent=new Intent(getApplicationContext(), MainActivity.class);
startActivity(intent);
finish();
}
}
#Override
public void onFailure(Call<Login> call, Throwable t) {
Log.e("Pritish", "Unable to submit post to API.");
}
});
}
Replace your Login class by following
#SerializedName("result")
#Expose
private String rESULT;
#SerializedName("response")
#Expose
private String response;
public String getRESULT() {
return rESULT;
}
public void setRESULT(String rESULT) {
this.rESULT = rESULT;
}
public String getResponse() {
return response;
}
public void setResponse(String response) {
this.response = response;
}
Add ServiceGenerator class :
public class ServiceGenerator {
private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
private static Retrofit.Builder builder =
new Retrofit.Builder()
.baseUrl(BASEURL)
.addConverterFactory(ScalarsConverterFactory.create());
public static <S> S createService(Class<S> serviceClass) {
Retrofit retrofit = builder.client(httpClient.build()).build();
return retrofit.create(serviceClass);
}
public static Retrofit getRetrofit()
{
return builder.client(httpClient.build()).build();
}
}
2.Add interface RetrofitAPI :
public interface RetrofitApi {
#POST("/api/v1/user")
Call<ResponseBody> login(#Body RequestBody loginBody);
}
3.Add method for login in your manager class :
public void retrofitLogin(JSONObject login, final String tag) {
RetrofitApi service = ServiceGenerator.createService(RetrofitApi.class);
Call<ResponseBody> result = service.login(convertJsonToRequestBody(login));
result.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, retrofit2.Response<ResponseBody> response) {
retrofitCheckResponse(response, tag);
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
if (t instanceof IOException) {
Log.e("retrofit error", "retrofit error");
sendErrorRetrofit(mContext.getString(R.string.ERROR), 500, tag);
}
}
});
}
Method to convert JSONObject to RequestBody :
private RequestBody convertJsonToRequestBody(JSONObject jsonObject) {
if (jsonObject != null) {
return RequestBody.create(okhttp3.MediaType.parse("application/json; charset=utf-8"), jsonObject.toString());
} else {
return null;
}
}
4.Now call your retrofitLogin method :
JSONObject mLoginParams = new JSONObject();
JSONObject mLoginObj = new JSONObject();
mLoginParams.put("username", uname);
mLoginParams.put("password", pass);
mLoginObj.put("appType","mobile");
mLoginObj.put("user", mLoginParams);
volleyRequest.retrofitLogin(mLoginObj, "Login");

Android Send String to Server via retrofit

i want to send string from app to server with retrofit 2, and get back return values. what is the problem?
but it doesn't work.
Retrofit retrofit = new Retrofit.Builder().baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
RatingApiService retrofitService=retrofit.create(RatingApiService.class);
Call<String> call = retrofitService.registration("saeed","ali");
call.enqueue(new Callback<String>() {
#Override
public void onResponse(Call<String> call, Response<String> response) {
if(response!=null){
Log.i("upload","is success:" +response.body());
}else{
Log.i("upload","response is null");
}
}
#Override
public void onFailure(Call<String> call, Throwable t) {
Log.i("upload","onFailure: "+t.getMessage());
}
});
Interface:
public interface RatingApiService {
#FormUrlEncoded
#POST("android/add2/{email}{password}")
Call<String> registration(#Path("email") String email, #Path("password") String password);
}
Instead of using parameters to pass your data; put it in a req.body, then send it. By doing so, you can bypass the URL string limit and the code is much more organized.
public interface RatingApiService {
#Headers("Content-Type: application/json") //Must be set to application/json so req.body can be read.
#POST("android")
Call<String> registration(#Body UserRegistrationRequest body);
}
Now, you might ask what is the " UserRegistrationRequest" class? that will be the object class that will be sent as a JSON object. We define it by:
public class UserRegistrationRequest {
final String email;
final String password;
UserRegistrationRequest(String email, String password){
this.email = email;
this.password = password;
}
}
And then the final step. This is how you convert the object to a JSON object and send it to your server.
UserRegistrationRequest userRegistrationRequest = new UserRegistrationRequest(
RegisterNameFragment.sFirstName, RegisterNameFragment.sLastName, RegisterEmailFragment.sEmail,
RegisterPasswordFragment.sPassword, RegisterAgeFragment.sAge);
Call<Void> call = retrofit.insertUserRegistration(userRegistrationRequest);
call.enqueue(new Callback<UserRegistration>() {
#Override
public void onResponse(Call<UserRegistration> call, Response<UserRegistration> response) {
Log.d("blue", "Data is sent");
}
#Override
public void onFailure(Call<UserRegistration> call, Throwable t) {
Log.d("blue", "fail");
}
});
You need to add #Body annotation to your method like below.
#POST("users/new")
Call<User> createUser(#Body User user);
The content of #Body is sent to server as request body.
If you want to send email and password to server, you should create object that contains such data and use the object in the #Body annotation.

Categories

Resources