I'm following a retrofit course in which I create a small backend with an api in which I have a POST method to perform a teacher's login. In the course what he does is create a teacher and with the set method he passes him the email and the password, which is what this method receives in the API.
I would like to do it in such a way that in the call to Retrofit you pass directly this email and password and I have done it in the following way:
public class LoginActivity extends AppCompatActivity {
private EditText etPasswordLogin, etEmailLogin;
private Button btLogin;
private TextView tvSignUp;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
setupView();
}
private void setupView() {
etPasswordLogin = findViewById(R.id.loginEditTextPassword);
etEmailLogin = findViewById(R.id.loginEditTextEmail);
btLogin = findViewById(R.id.buttonSignUp);
tvSignUp = findViewById(R.id.textViewSignUp);
btLogin.setOnClickListener(v -> userSignUp());
tvSignUp.setOnClickListener(v -> startActivity(new Intent(getApplicationContext(), SignUpActivity.class)));
}
private void userSignUp() {
String email = etEmailLogin.getText().toString().trim();
String password = etPasswordLogin.getText().toString().trim();
if (email.isEmpty()) {
etEmailLogin.setError(getResources().getString(R.string.email_error));
etEmailLogin.requestFocus();
return;
}
if (!Patterns.EMAIL_ADDRESS.matcher(email).matches()) {
etEmailLogin.setError(getResources().getString(R.string.email_doesnt_match));
etEmailLogin.requestFocus();
return;
}
if (password.isEmpty()) {
etPasswordLogin.setError(getResources().getString(R.string.password_error));
etPasswordLogin.requestFocus();
return;
}
if (password.length() < 4) {
etPasswordLogin.setError(getResources().getString(R.string.password_error_less_than));
etPasswordLogin.requestFocus();
return;
}
login(email, password);
}
private void login(String email, String password) {
String BASE_URL = "http://10.0.2.2:8040";
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
WebServiceApi api = retrofit.create(WebServiceApi.class);
Call<List<Profesor>> call = api.login(email, password);
call.enqueue(new Callback<List<Profesor>>() {
#Override
public void onResponse(Call<List<Profesor>> call, Response<List<Profesor>> response) {
if (response.code() == 200) {
Log.d("TAG1", "Profesor logeado");
} else if (response.code() == 404) {
Log.d("TAG1", "Profesor no existe");
} else {
Log.d("TAG1", "Error desconocido");
}
}
#Override
public void onFailure(Call<List<Profesor>> call, Throwable t) {
Log.d("TAG Error: ", Objects.requireNonNull(t.getMessage()));
}
});
}
}
And this would be my model teacher:
public class Profesor {
#SerializedName("id")
private Long id;
#SerializedName("nombre")
private String nombre;
#SerializedName("email")
private String email;
#SerializedName("password")
private String password;
#SerializedName("foto")
private String photo;
public Profesor(){}
public Profesor(Long id, String nombre, String email, String photo) {
this.id = id;
this.nombre = nombre;
this.email = email;
this.photo = photo;
}
public Profesor(String email, String password){
this.email = email;
this.password = password;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
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 getPhoto() {
return photo;
}
public void setPhoto(String photo) {
this.photo = photo;
}
}
Finally the call to Retrofit that I make is the following:
#FormUrlEncoded
#POST("api/login")
Call<List<Profesor>> login(#Field("email") String email, #Field("password") String password);
However when I run the application and pass through the form the email and password, in the log I return "Error desconocido", however in postman gives me answer without problems:
Any idea what I'm doing wrong?
Your postman request is not a form-urlencoded, but raw.
You need to send a json as a request, and not a field. So to fix this, you may change your API, to handle form-urlencoded requests, or change the Android code this way.
public class LoginCredentials {
#SerializedName("email")
private String email;
#SerializedName("password")
private String password;
public LoginCredentials(String email, String password) {
this.email = email;
this.password = password;
}
}
and change this
#FormUrlEncoded
#POST("api/login")
Call<List<Profesor>> login(#Field("email") String email, #Field("password") String password);
to this
#POST("api/login")
Call<List<Profesor>> login(#Body LoginCredentials credentials);
Hope this will help.
Related
I have a database from firebase. I want to retrieve some data using a user's email. suppose user put his/her email if the email exists in the firebase database then it shows his/her username and password. I am not using firebase authentication, I am using firebase realtime database.
here is my database structure:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_forgate_password);
emailf = findViewById(R.id.emailf);
userf = findViewById(R.id.usernamef);
passwordf = findViewById(R.id.passwordf);
ok = findViewById(R.id.okbtn);
database = FirebaseDatabase.getInstance();
users = database.getReference("Users").child("emailAddress");
ok.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
signInMethod(emailf.getText().toString());
}
});
}
private void signInMethod(final String email) {
users.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// This method is called once with the initial value and again
// whenever data at this location is updated.
if (dataSnapshot.child("emailAddress").exists()){
if (dataSnapshot.child(user.getUserName()).exists()){
Toast.makeText(ForgatePassword.this,"User already exists",Toast.LENGTH_LONG).show();
}
}
}
#Override
public void onCancelled(DatabaseError error) {
// Failed to read value
Log.w("Tag", "Email not exists", error.toException());
}
});
}
here is my model class:
public class SignInUpModel {
private String fullName;
private String userName;
private String schoolName;
private String className;
private String division;
private String phnNumber;
private String emailAddress;
private String reference;
private String password;
public SignInUpModel() {
}
public SignInUpModel(String fullName, String userName, String schoolName, String className, String division, String phnNumber, String emailAddress, String reference, String password) {
this.fullName = fullName;
this.userName = userName;
this.schoolName = schoolName;
this.className = className;
this.division = division;
this.phnNumber = phnNumber;
this.emailAddress = emailAddress;
this.reference = reference;
this.password = password;
}
public String getFullName() {
return fullName;
}
public void setFullName(String fullName) {
this.fullName = fullName;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getSchoolName() {
return schoolName;
}
public void setSchoolName(String schoolName) {
this.schoolName = schoolName;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public String getDivision() {
return division;
}
public void setDivision(String division) {
this.division = division;
}
public String getPhnNumber() {
return phnNumber;
}
public void setPhnNumber(String phnNumber) {
this.phnNumber = phnNumber;
}
public String getEmailAddress() {
return emailAddress;
}
public void setEmailAddress(String emailAddress) {
this.emailAddress = emailAddress;
}
public String getReference() {
return reference;
}
public void setReference(String reference) {
this.reference = reference;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
How can I do this?
Using firebase database to create your own authentication system is not a good idea.
What you want to do will require you to allow read of every user's email password stored in database. This will be a huge security risk for your app as anyone can read all the email passwords in your database.
Firebase provides easy to use firebase authentication with many options to use. You can easily delegate the security to firebase auth and store your user's profile and data in db. This way you can also restrict data access for each user (which is why you want email password login for your app).
Please see the authentication documents of firebase: https://firebase.google.com/docs/auth
It will help you create your app without implementing your own auth and focus on actual features development.
Why the object is returned empty? Android. Retrofit2.
I have a class User:
public class User{
#SerializedName("LOGIN")
String login;
#SerializedName("PASSWORD")
String password;
#SerializedName("NAME")
String name;
#SerializedName("SURNAME")
String surname;
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
}
This's my JSON:
[{
"LOGIN":"TEST",
"PASSWORD":"TEST",
"NAME":"TEST",
"SURNAME":"TEST"
}
]
Interface:
public interface Link {
#GET("93sZY0Xg")
Call<List<User>> listRepos();
}
and class LoginActivity where i use retrofit2:
public class LoginActivity extends AppCompatActivity implements Callback<List<User>>{
private Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.baseUrl("http://pastebin.com/raw/")
.build();
private Link service = retrofit.create(Link.class);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
Call<List<User>> us = service.listRepos();
us.enqueue(this);
}
#Override
public void onResponse(Call<List<User>> call, Response<List<User>> response) {
System.out.println(response.body());
System.out.println(response.code());
User us = response.body().get(0);
System.out.println(us.getName());
for(User m: response.body()){
System.out.println( m.getName());
}
}
#Override
public void onFailure(Call<List<User>> call, Throwable t) {
System.out.println(t.getLocalizedMessage());
}
}
I get this response: response.code() is 200;
I/System.out: [com.example.com.dataBase.User#b789a]
I tried getName from class User, but all variables is null.
Why are the values empty? Where's my mistakes?
Try following, expose annotation is important to set value in fields
#Expose
#SerializedName("movie_id")
private String movieId;
#Expose
#SerializedName("movie_name")
private String movieName;
#Expose
#SerializedName("movie_poster")
private String moviePoster;
#Expose
#SerializedName("movie_dialog_count")
private String movieDialogCount;
I want to register a user with their token, I want to register a user using retrofit in android but I keep getting this error:
ERROR::: Attempt to invoke virtual method 'void com.signup.User.setUsername(java.lang.String)' on a null object reference
Here is my code:
public class Session {
Context context;
private SharedPreferences prefs;
public Session(Context cntx) {
// TODO Auto-generated constructor stub
this.context = cntx;
prefs = PreferenceManager.getDefaultSharedPreferences(context);
}
public void setJwtToken(String token) {
prefs.edit().putString("JwtToken", token).commit();
}
public String getJwtToken() {
String token = prefs.getString("JwtToken", "");
if (token == null || token.isEmpty()) {
token = "Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjIxNzc0NTI3OTksImlhdCI6MTUxNjAyMjk5OSwiaXNzIjoiQmFzb2JhYXMgTmVwYWwiLCJuYmYiOjE1MTYwMjI5OTksImp0aSI6Ikd1ZXN0VG9rZW4iLCJzdWIiOjB9.QikmNgBYmqch5HREGFEpUs4Xk3x-zFfDg5mhYJO7jM8";
}
return token;
}
}
public interface ApiInterface {
#POST("/api/users/signup")
Call<ResponseBody> signMeUp(#Header("Authorization") String token ,#Body User user);
}
public class MainActivity extends AppCompatActivity {
private EditText et_name, et_address, et_phone, et_username, et_email, et_password, et_confipassword;
private Button register;
private User user;
private SharedPreferences prefs;
private ApiInterface apiInterface;
private Session session;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et_name = findViewById(R.id.edit_text_name);
et_address = findViewById(R.id.edit_text_address);
et_phone = findViewById(R.id.edit_text_phonenumber);
et_username = findViewById(R.id.edit_text_username);
et_email = findViewById(R.id.edit_text_email);
et_password = findViewById(R.id.edit_text_password);
et_confipassword = findViewById(R.id.edit_text_confirm_password);
register = findViewById(R.id.signupButton);
register.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Login();
}
});
}
private void Login() {
user.setUsername(et_name.getText().toString());
user.setAddress(et_address.getText().toString());
user.setPhone(et_phone.getText().toString());
user.setName(et_name.getText().toString());
user.setEmail(et_email.getText().toString());
user.setPassword(et_password.getText().toString());
user.setPasswordConfirmation(et_confipassword.getText().toString());
signupUser(user);
}
private void signupUser(final User user) {
// Set up progressbar before call
apiInterface = ApiClient.getClient().create(ApiInterface.class);
Call<ResponseBody> call1 = apiInterface.signMeUp(session.getJwtToken(),user);
final Gson gson = new Gson();
final String json = gson.toJson(user);
call1.enqueue(new Callback<ResponseBody>() {
#Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
if (response.code() == 201) {
try {
JSONObject jsonObject = new JSONObject(response.body().string());
//Starting main activity after user sees dialog
} catch (JSONException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} else if (response.code() == 500) {
try {
JSONObject jsonObject = new JSONObject(response.errorBody().string());
Log.e("SignupFragment", jsonObject.toString());
} catch (JSONException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}else
Log.e("SignupFragment", response.raw().toString());
}
#Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
}
});
}
}
public class User {
#SerializedName("name")
#Expose
private String name;
#SerializedName("email")
#Expose
private String email;
#SerializedName("password")
#Expose
private String password;
#SerializedName("password_confirmation")
#Expose
private String passwordConfirmation;
#SerializedName("image")
#Expose
private String image;
#SerializedName("phone")
#Expose
private String phone;
#SerializedName("address")
#Expose
private String address;
#SerializedName("username")
#Expose
private String username;
#SerializedName("pan_no")
#Expose
private String panNo;
#SerializedName("birthday")
#Expose
private String birthday;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
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 getPasswordConfirmation() {
return passwordConfirmation;
}
public void setPasswordConfirmation(String passwordConfirmation) {
this.passwordConfirmation = passwordConfirmation;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPanNo() {
return panNo;
}
public void setPanNo(String panNo) {
this.panNo = panNo;
}
public String getBirthday() {
return birthday;
}
public void setBirthday(String birthday) {
this.birthday = birthday;
}
}
public class ApiClient {
public static final String BASE_URL = "https://myapp.herokuapp.com/";
private static Retrofit retrofit = null;
public static Retrofit getClient() {
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
ApiInterface apiInterface=retrofit.create(ApiInterface.class);
}
I want to signup a user via my app but I keep getting the error. And, if I remove the auth from header from my Interface I get a message asking a token, and when I provide a token it give me a null object reference error !!
You should instantiate variable before access it: User user = new User();
Update: do it in void Login()
create an instance of User inside onCreate method or up there where it's declared
Try this
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
user = new User();
session = new Session(this);
}
I'm using Retrofit in Android to login with POST method to server with API and response it back. When I insert the data that already have in the server to login it will go to onResponse but when I insert the data that have no in the server in will to go onFailure but in my API I handled when have no data it will response status False. This is the message when it go to onFailure:
com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_OBJECT but was BEGIN_ARRAY at line 1 column 56 path $.data
SignInService.java
public interface SignInService {
#FormUrlEncoded
#POST("api/signIn/")
Call<SignInRespone> signIn(#Field("email") String email,
#Field("password") String password);
}
SignInResponse.java
public class SignInRespone {
#SerializedName("success")
private boolean success;
#SerializedName("message")
private String message;
#SerializedName("data")
private Data data;
public boolean getSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public Data getData() {
return data;
}
public void setData(Data data) {
this.data = data;
}
public static class Data {
#SerializedName("id")
private int id;
#SerializedName("username")
private String username;
#SerializedName("email")
private String email;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
}
SignInRequest.java
public class SignInRequest {
#SerializedName("email")
private String email;
#SerializedName("password")
private String password;
public SignInRequest(String email, String password) {
this.email = email;
this.password = password;
}
}
SignInActivity.java
public void signIn(){
signInService = ServiceGenerator.createService(SignInService.class);
Call<SignInRespone> call= signInService.signIn("jonh1#gmail.com","12345");
call.enqueue(new Callback<SignInRespone>() {
#Override
public void onResponse(Call<SignInRespone> call, Response<SignInRespone> response) {
Log.e(">>>>",response.body().getData().getEmail());
startActivity(new Intent(getApplicationContext(), MainActivity.class));
finish();
}
#Override
public void onFailure(Call<SignInRespone> call, Throwable t) {
Log.e(">>>>", t.toString());
}
});
}
As per comment when you have logged in success fully server returns correct object that's why no exception, but when email is not present on server it returns data[] instead of data object that's why you are getting exception because you are expecting an object but server returned an array.
Solution:
return data:null form server if email not exists
i'm trying to retrieve an inner object from a json response, my json pojo looks like this:
public class Pojo {
private String token;
private User user;
public Pojo()
{}
public Pojo(String username, String password,User user) {
user.setUsername(username);
user.setPassword(password);
this.user = user;
}
public String getToken() {return token;}
public void setToken(String token) {this.token = token;}
public User getUser() {return user;}
public void setUser(User user) {this.user = user;}
and my innerobjct User looks like this:
public class User {
private String username
;
private String name;
private String phone;
private String email;
private String password;
private String is_Active;
}
with their setters and getters
this is my login code:
public void onLogin(View view){
final ProgressDialog dialog = ProgressDialog.show(this, "", "loading...");
EndpointInterface loginService = ServiceAuthGenerator.createService(EndpointInterface.class);
Password = tv_Password.getText().toString();
Username = tv_Username.getText().toString();
User usr = new User();
Pojo user = new Pojo(Username,Password,usr);
Call<Pojo> call = loginService.getToken(usr);
call.enqueue(new Callback<Pojo>() {
#Override
public void onResponse(Response<Pojo> response, Retrofit retrofit) {
dialog.dismiss();
if (response.isSuccess()) {
Pojo user = response.body();
if(user.getUser().getIs_Active()=="True") {
Intent intent = new Intent(getApplicationContext(), MainMenu.class);
startActivity(intent);
}
else{
Toast.makeText(getApplicationContext(), "Wrong User or Password", Toast.LENGTH_SHORT).show();
}
}
}
#Override
public void onFailure(Throwable t) {
dialog.dismiss();
Toast.makeText(getApplicationContext(), "Error Conection", Toast.LENGTH_SHORT).show();
}
});
}
the response is comming like this:
{
"token":"tokengfsgfds"
"user":{
"username":"exmplename"
"email":"#gomail.com"
"is_active":"True"
}
}
i can retrieve the token, but when i try to get variables from the user inner object my app fails. thanks!
this just mirror code for model classes using Gson library
Pojo.java
import com.google.gson.annotations.SerializedName;
public class Pojo {
#SerializedName("token")
private String token;
#SerializedName("user")
private User user;
public Pojo(String username, String password,User user) {
// TODO Auto-generated constructor stub
user.setUsername(username);
user.setPassword(password);
this.token = "tokengfsgfds";
this.user = user;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
}
take User out of Pojo and make another class User.java
import com.google.gson.annotations.SerializedName;
public class User {
#SerializedName("username")
private String username;
#SerializedName("name")
private String name;
#SerializedName("phone")
private String phone;
#SerializedName("email")
private String email;
#SerializedName("password")
private String password;
#SerializedName("is_Active")
private boolean is_active;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
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 boolean isIs_active() {
return is_active;
}
public void setIs_active(boolean is_active) {
this.is_active = is_active;
}
}
I used Gson but the output should be the same
import com.google.gson.Gson;
public class TestTwo {
public static void main(String[] args) {
User user = new User();
user.setEmail("someone#gmailcom");
user.setIs_active(true);
user.setName("Cristian");
user.setPassword("Cam");
user.setPhone("1234123441");
user.setUsername("cam.cri");
Pojo pojo = new Pojo("cam.cri", "Cam", user);
String result = (new Gson()).toJson(pojo);
System.out.println(""+result);
Pojo pojo2 = (new Gson()).fromJson(result, Pojo.class);
System.out.println("Token: \t"+pojo2.getToken());
System.out.println("email: \t"+pojo2.getUser().getEmail());
System.out.println("is_active: \t"+pojo2.getUser().isIs_active());
System.out.println("Name: \t"+pojo2.getUser().getName());
System.out.println("Password: \t"+pojo2.getUser().getPassword());
System.out.println("phone: \t"+pojo2.getUser().getPhone());
System.out.println("Username: \t"+pojo2.getUser().getUsername());
}
}
Output
{
"token": "tokengfsgfds",
"user": {
"username": "cam.cri",
"name": "Cristian",
"phone": "1234123441",
"email": "someone#gmailcom",
"password": "Cam",
"is_Active": true
}
}
output
Token: tokengfsgfds
email: someone#gmailcom
is_active: true
Name: Cristian
Password: Cam
phone: 1234123441
Username: cam.cri