Building User-Authentication Android Application Using Android Studio and Spring-Boot backend
In this post, we are going to build an android application using Java and mysql which will help us to authenticate user and interact with our database using springboot.
Requirements
- Android Studio
- Android Virtual Device (AVD)
- MySQL
- Spring Boot
- Retrofit Dependency
- Android SDK Tools
- Programming IDE (eg. VS Code, IntelliJ IDEA)
Getting started with Project
Open android studio -> click new project -> click on empty activity -> select java as language -> select a suitable android SDK which ensures that your app runs on all devices -> click Finish -> wait until gradle gets successfully build.
Getting started with Spring Initializr
Visit the spring boot initialiser and follow the following steps -
Select Maven as project -> select Java as langauge -> pick an appropriate Spring boot version (eg. 2.4.5) -> give appropriate names to your project metadata -> select Jar for packaging -> select corresponding Java version which you have in your system environment -> add MySQL Driver , Spring Web and Spring Data JPA in the dependencies and hit the generate button.
A zip file will be downloaded which you need to extract and open the extracted folder in your programming IDE (eg. VS Code, IntelliJ IDEA).
Once the folder is successfully opened in our IDE, open the application.properties file and add the following command
spring.datasource.url=jdbc:mysql://localhost:3306/"your database name"?useSSL=false&allowPublicKeyRetrieval=true
spring.datasource.username="your username"
spring.datasource.password="your password"
Enter your MySQL root username, password and database name at the appropriate places in the above command.
Create a table User inside your database having following schema
Now, create a package named Entity inside which, create a java file as User which will act as an entity for us while communicating with the database.
import javax.persistence.*;
@Entity
@Table(name = "user")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private int id;
@Column(name = "username")
private String username;
@Column(name = "password")
private String password;
public User() {
}
public User(String username, String password) {
this.username = username;
this.password = password;
}
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 getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
'}';
}
}
Now, create a package named Dao (Data Access Object) inside which, create a UserDao java interface which will act as DAO.
Extend the following interface with CrudRepository which will help us performing basic database operations.
import com.authUser.AuthenticateUser.entity.User;
import org.springframework.data.repository.CrudRepository;
public interface UserDao extends CrudRepository<User,String> {
}
Now, create a package named Service inside which, create a UserService java interface. This interface creates abstract functions such as getUser and addUser
import com.authUser.AuthenticateUser.entity.User;
import org.springframework.stereotype.Component;
@Component
public interface UserService {
public User getUser(User user);
public User insertIntoDatabase(User user);
}
Now, inside Service package, create a java class named UserServiceImp which will implement the Service interface.
import com.authUser.AuthenticateUser.dao.UserDao;
import com.authUser.AuthenticateUser.entity.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
@Service
public class UserServiceImp implements UserService {
private final EntityManager entityManager;
@Autowired
public UserServiceImp(EntityManager theEntityManager) {
entityManager = theEntityManager;
}
@Autowired
private UserDao userDao;
@Override
public User getUser(User userDetails) {
TypedQuery<User> typedQuery = entityManager.createQuery(
"FROM User WHERE password = :password AND username = :username", User.class);
try {
User user = typedQuery.setParameter("password", userDetails.getPassword()).setParameter("username", userDetails.getUsername()).getSingleResult();
return user;
} catch (Exception e) {
return null;
}
}
@Override
public User insertIntoDatabase(User user) {
return userDao.save(user);
}
}
In this class, we have used the TypedQuery interface which helps us to perform our own custom MySQL queries.
Finally, create a package named Controller in which, create a MainController java class which will be our main restController.
import com.authUser.AuthenticateUser.entity.User;
import com.authUser.AuthenticateUser.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping
public class MainController {
@Autowired
UserService userService;
@PostMapping("/getUser")
public User getUser(@RequestBody User user) {
return userService.getUser(user);
}
@PutMapping("/addUser")
public User addUser(@RequestBody User user) {
return userService.insertIntoDatabase(user);
}
}
We are using two methods getUser which will retrieve existing users from the database and addUser which will add a new user in our local database.
We are done with our database setup and our backend.
Time for the Front-End now.
Let’s open Android studio and start creating out layouts, here we will create some basic designs for our layouts using Constraint Layout.
The activity_main xml layout is our main landing page which will ask for username and password from the user. If user is not registered in our database, he/she can register using the Register now button.
We will be using REST api for communicating with springboot for which we will need Retrofit dependency. Include the following dependency in your build.gradle file and rebuild your project.
implementation 'com.squareup.retrofit2:retrofit:2.5.0'
implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
Create a package named Remote in which create a java file Network which will help us to build the Retrofit.Builder
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class Network {
private static HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY);
public static Retrofit getInstance() {
Retrofit.Builder builder = new Retrofit.Builder().baseUrl("http://192.168.43.126:8080/")
.addConverterFactory(GsonConverterFactory.create())
.client(new OkHttpClient.Builder().addInterceptor(httpLoggingInterceptor).build());
return builder.build();
}
}
Here, 192.168.43.126.8080/ is my local IP address for my system, replace this by your own system’s IP address.
Now, create a java interface ApiService in the remote package which will actually make the REST API calls for us.
import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.GET;
import retrofit2.http.POST;
import retrofit2.http.PUT;
import retrofit2.http.Path;
public interface ApiService {
@PUT("/addUser")
Call<ResponseClass> addUser(@Body ResponseRegisterClass responseRegisterClass);
@POST("/getUser")
Call<ResponseClass> getUser(@Body ResponseRegisterClass responseRegisterClass);
}
We have created two abstract methods having the @PUT and @POST annotations for getting the users from the database and inserting new users into database.
Both of the methods will have a BODY which will be of JSON type having username and password which we will receive from the EditText.
Now, install any pojo plugin from the android marketplace which will help us to convert the JSON response into GSON format.
We have also validated the input which we will get from the EditText such as the EditText fields should not be empty. While registering, the username should be of a email type and should contain @gmail.com at the end. The password should have at-least 6 digits of characters etc.
Once the data is validated, we make an retrofit API call using the @POST method and according, the user will be added inside the database
Now, as the user has successfully registered in our database, they can enter the username and the password which they entered during the registration and will be able to see the welcome page which will display their username with a Hello greeting with a Toast message of login successful.
MainActivity
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.rahul.authenticateusingspring.R;
import com.rahul.authenticateusingspring.remote.ApiService;
import com.rahul.authenticateusingspring.remote.Network;
import com.rahul.authenticateusingspring.responseClasses.ResponseClass;
import com.rahul.authenticateusingspring.responseClasses.ResponseRegisterClass;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class MainActivity extends AppCompatActivity {
TextView tvRegister;
EditText etUsername, etPassword;
Button btnLogin;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initializeListeners();
onClickListeners();
}
private void onClickListeners() {
btnLogin.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (validateUsername() && validatePassword()) {
ResponseRegisterClass responseRegisterClass = new ResponseRegisterClass(etUsername.getText().toString(), etPassword.getText().toString());
ApiService apiService = Network.getInstance().create(ApiService.class);
apiService.getUser(responseRegisterClass).enqueue(new Callback<ResponseClass>() {
@Override
public void onResponse(Call<ResponseClass> call, Response<ResponseClass> response) {
if (response.body() != null) {
Toast.makeText(MainActivity.this, "Login successful", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(MainActivity.this, SuccessfulLogin.class);
intent.putExtra("username", response.body().getUsername());
startActivity(intent);
}
}
@Override
public void onFailure(Call<ResponseClass> call, Throwable t) {
Toast.makeText(MainActivity.this, "Invalid credentials", Toast.LENGTH_SHORT).show();
}
});
}
}
});
tvRegister.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
startActivity(new Intent(MainActivity.this, RegisterActivity.class));
}
});
}
private boolean validateUsername() {
if (TextUtils.isEmpty(etUsername.getText().toString())) {
etUsername.setError("username cannot be empty");
etUsername.requestFocus();
return false;
}
return true;
}
private boolean validatePassword() {
if (TextUtils.isEmpty(etPassword.getText().toString())) {
etPassword.setError("password cannot be empty");
etPassword.requestFocus();
return false;
}
return true;
}
private void initializeListeners() {
etUsername = findViewById(R.id.etUserName);
etPassword = findViewById(R.id.etPassword);
tvRegister = findViewById(R.id.tvRegister);
btnLogin = findViewById(R.id.btnLogin);
}
}
RegisterActivity
public class RegisterActivity extends AppCompatActivity {
EditText etRegisterUsername, etRegisterPassword;
Button btnRegister;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register);
initializeListeners();
onClickListeners();
}
private void onClickListeners() {
btnRegister.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (validateUserName() && validatePassword()) {
ResponseRegisterClass responseRegisterClass = new ResponseRegisterClass(etRegisterUsername.getText().toString(), etRegisterPassword.getText().toString());
ApiService apiService = Network.getInstance().create(ApiService.class);
apiService.addUser(responseRegisterClass).enqueue(new Callback<ResponseClass>() {
@Override
public void onResponse(Call<ResponseClass> call, Response<ResponseClass> response) {
if (response.body() != null) {
Toast.makeText(RegisterActivity.this, "Registration successful", Toast.LENGTH_SHORT).show();
finish();
} else {
Toast.makeText(RegisterActivity.this, "something went wrong! please try again", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onFailure(Call<ResponseClass> call, Throwable t) {
}
});
}
}
});
}
private boolean validatePassword() {
if (etRegisterPassword.getText().toString().length() < 6) {
etRegisterPassword.setError("password must be atleast 6 characters");
etRegisterPassword.requestFocus();
return false;
} else if (TextUtils.isEmpty(etRegisterPassword.getText().toString())) {
etRegisterPassword.setError("password cannot be empty");
etRegisterPassword.requestFocus();
return false;
}
return true;
}
private boolean validateUserName() {
if (TextUtils.isEmpty(etRegisterUsername.getText().toString())) {
etRegisterUsername.setError("username cannot be empty");
etRegisterUsername.requestFocus();
return false;
} else if (!etRegisterUsername.getText().toString().contains("@gmail.com")) {
etRegisterUsername.setError("email must contain @gmail.com");
etRegisterUsername.requestFocus();
return false;
}
return true;
}
private void initializeListeners() {
etRegisterUsername = findViewById(R.id.etRegisterUsername);
etRegisterPassword = findViewById(R.id.etRegisterPassword);
btnRegister = findViewById(R.id.btnRegister);
}
}
SuccessfulLogin
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;
import com.rahul.authenticateusingspring.R;
import javax.annotation.Resource;
public class SuccessfulLogin extends AppCompatActivity {
TextView tvUsername;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_successful_login);
String username = getIntent().getStringExtra("username");
tvUsername = findViewById(R.id.tvUserName);
tvUsername.setText(getString(R.string.hello) + " " + username);
}
}
Checkout the complete project by clicking here.
And that’s all for this interesting project. Now what are you waiting for ? Hurry up and starting implementing your programming skills to make this world a better place! Peace.