Let’s Build Signup, SignIn, and Role-Based Access in Our E-Commerce App
Published: 2021-01-10 08:10:54

In this article, we are going to implement basic SignUp and SignIn functionality in the Spring backend and Android UI.

An Overview Of The Tutorial!
Introduction
Database Design
API Design
Demo overview
Signup
Dealing with the Android Application
Our Intention
Requirements
Dependencies
Permissions
Creating Models
Updating the API
Creating Activities
The Main Page
Signing Up Users
Signing In Users
Constructing the Dashboard
Running the Application
Resources

Introduction
This is a series of tutorials we are building to demonstrate how to build an E-Commerce App, one component at a time.
We are going to implement a basic authentication which will be extended to role-based access i.e. Admin can change anything, add new Users, a manager can only add/update Category and Products, users can only see the products and Category.
When users/admin sign in, we will generate an authentication token, which will be used to verify the users, when they are going to access an API later.

Database Design
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/pg10bw711pjcdrj1r5mk.png)
We will have a user table and tokens table. For every user, when they signUp and sign in, we will generate a token, which will have an expiry date. After the expiry day has passed, we should generate a new token, although we will not cover it in the tutorial.

API Design
@PostMapping("/signup")
    public ResponseDto Signup(@RequestBody SignupDto signupDto) throws CustomException {
        return userService.signUp(signupDto);
    }

    //TODO token should be updated
    @PostMapping("/signIn")
    public SignInResponseDto Signup(@RequestBody SignInDto signInDto) throws CustomException {
        return userService.signIn(signInDto);
    }
UserController will have two methods, Signup, and SignIn, which will be POST requests.

SignUp
Let's look at signUp API. It takes SignupDto as Input and returns True or False as output depending upon if SignUp succeeds.
package com.webtutsplus.ecommerce.dto.userDTOs;

public class SignupDto {
    private String firstName;
    private String lastName;
    private String email;
    private String password;

    // Getters and setters
    ...
}

We follow these steps for signup
Encrypt the password
Save the User
Generate auth token and save it in database
Return Success
public ResponseDto signUp(SignupDto signupDto)  throws CustomException {
        // first encrypt the password
        String encryptedPassword = signupDto.getPassword();
        try {
            encryptedPassword = hashPassword(signupDto.getPassword());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            logger.error("hashing password failed {}", e.getMessage());
        }


        User user = new User(signupDto.getFirstName(), signupDto.getLastName(), signupDto.getEmail(), Role.user, encryptedPassword );

        User createdUser;
        try {
            // save the User
            createdUser = userRepository.save(user);
            // generate token for user
            final AuthenticationToken authenticationToken = new AuthenticationToken(createdUser);
            // save token in database
            authenticationService.saveConfirmationToken(authenticationToken);
            // success in creating 
            return new ResponseDto(ResponseStatus.success.toString(), USER_CREATED);
        } catch (Exception e) {
            // handle signup error
            throw new CustomException(e.getMessage());
        }
    }

We will now look at models that are mapped as a table in the database
@Entity
@Table(name = "tokens")
public class AuthenticationToken {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    private String confirmationToken;

    private Date createdDate;

    @OneToOne(targetEntity = User.class, fetch = FetchType.EAGER)
    @JoinColumn(nullable = false, name = "user_id")
    private User user;
    
  // getter setters
  // contructors
}

User and Tokens are linked by user_id field in tokens table, which has one to one relationship, i.e one user can have one token and vice versa.
@Entity
@Table(name = "users")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @Column(name = "first_name")
    private String firstName;

    @Column(name = "last_name")
    private String lastName;

    @Column(name = "email")
    private String email;

    @Enumerated(EnumType.STRING)
    @Column(name = "role")
    private Role role;

    @Column(name = "password")
    private String password;

Start building the Android Application
Next, we are going to use the same REST API to perform the user authentication process in the same android application that we have created and deployed in the last tutorial. If you have not followed up, please check out the tutorial using the link given below.
https://medium.com/technology-hits/lets-add-products-in-android-for-e-commerce-app-b8468e055001

Our Intention
In our last tutorial above, we have created ways in our application to view, add, and update our products by communicating with our REST API service.
Now we are going to limit the access of adding and updating products only to the authenticated users. Non-authenticated users can simply checkout all products we have, but they are not permitted to edit.
Our intention is to achieve such functionality mentioned above in our application. Get ready to explore!

Requirements
Though we have no new requirements for the application to achieve basic authentication, let’s revise them for the new readers’ convenience.
Android Studio (Completely Setup with SDK)
Android Virtual Device
Cloud Hosted E-Commerce Backend API
Retrofit- to interact with the API
Glide- to load images
Steps to set up your work environment in Android Studio can be found here.

Dependencies
No new dependencies are needed for extending the user authentication functionality in our application. Anyway, I’ll showcase all dependencies we have used in our application.
Recycler View
Card View
Retrofit
Gson converter
Glide
Permissions
Same as dependencies, we don’t need any extra permissions to extend the required functionality to our application.
We only need internet permissions to communicate with the RESTful service. It was added during the last-mentioned tutorial.
You can check out the app/src/main/AndroidManifest.xml file of our application below-

Please check the contents of the given app/src/main/AndroidManifest.xml file with yours.
Creating Models
We already have a model for the Product to send and receive through the API. Likewise, we need to create a model for the user to pass their credentials through our API.
Our user model accepts the credentials first name, last name, email id, and a password to save a user to the backend and the respective user’s email id and password to sign in them into the application.
Therefore, create a class User, that has four fields firstName, lastName, email, and password, as shown below-

And now we have all the required models to interact with our API. Let’s go ahead with making the user objects interact with our RESTful service.
Updating the API
We need to update the interface API that we have created so that it also interacts with the Users API in our backend.
We already have the interaction with the products API. Without disturbing that, we need to establish interaction with the Users API in our RESTful service. For the same, we are gonna update the API.java in our project.
You can update the same as below-
package com.webtutsplus.ecommerce;

import java.util.List;

import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.GET;
import retrofit2.http.POST;
import retrofit2.http.Path;

public interface API {

    @GET("product/")
    Call<List<Product>> getProducts();

    @POST("product/add/")
    Call<ResponseBody> addProduct(@Body Product p);

    @POST("product/update/{id}")
    Call<ResponseBody> updateProduct(@Path("id") long productId, @Body Product p);

    @POST("user/signup")
    Call<ResponseBody> signup(@Body User user);

    @POST("user/signIn")
    Call<ResponseBody> signin(@Body User user);
}
Now we can interact with the Users API of our backend. Let’s move further!

Creating Activities
We all know that activities are the basic building blocks of the application. An activity consists of a layout file and a java class to control the same.
We are provided with the pre-built activity called Main Activity. And also, we have added the following working activities to our application.
ListProducts Activity
AddProduct Activity
UpdateProduct Activity
For this tutorial, we need three more activities to sign up a user, sign in a user, and show the dashboard to the users respectively. Go ahead and create the following activities by following the steps: Right-click on the MainActivity residing package -> New -> Activity -> Empty Activity
SignupActivity
SigninActivity
DashboardActivity

The Main Page
The previous main page consisted mainly of buttons that navigate to add or update products and list products. But the functionalities of adding and updating products should be available only after the user is signing in. So, we are removing it from the main activity’s layout file.
Instead of that, we are adding two buttons that navigate to the user signup and user sign-in activity. The respective layout file is as below-
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorAccent"
    android:padding="20dp"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/tvTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:fontFamily="cursive"
        android:padding="10dp"
        android:text="E-Commerce"
        android:textColor="@color/colorPrimaryDark"
        android:textSize="60sp"
        android:textStyle="bold"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="PRODUCTS"
        android:textColor="#000"
        android:textSize="20sp"
        android:textStyle="bold"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/tvTitle" />


    <Button
        android:id="@+id/btnToViewProducts"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimary"
        android:text="VIEW PRODUCTS"
        android:textColor="#fff"
        android:textSize="16sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.4"
        app:layout_constraintStart_toStartOf="parent" />

    <Button
        android:id="@+id/btnToSignIn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="60dp"
        android:background="@color/colorPrimary"
        android:text="SIGN IN"
        android:textColor="#fff"
        android:textSize="16sp"
        app:layout_constraintBottom_toBottomOf="@+id/btnToViewProducts"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent" />

    <Button
        android:id="@+id/btnToSignUp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="60dp"
        android:background="@color/colorPrimary"
        android:text="SIGN UP"
        android:textColor="#fff"
        android:textSize="16sp"
        app:layout_constraintBottom_toBottomOf="@+id/btnToSignIn"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

Now, we need to make those newly created buttons to navigate to respective activities. For that, add on click listeners to the buttons in the MainActivity.java as below-
package com.webtutsplus.ecommerce;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        findViewById(R.id.btnToViewProducts).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                startActivity(new Intent(MainActivity.this, ListProductsActivity.class));
            }
        });

        findViewById(R.id.btnToSignUp).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                startActivity(new Intent(MainActivity.this, SignupActivity.class));
            }
        });

        findViewById(R.id.btnToSignIn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                startActivity(new Intent(MainActivity.this, SigninActivity.class));
            }
        });

    }
}
Now, let’s concentrate on signing up and signing in users through our application.
https://miro.medium.com/max/500/1*nvwHI_xI9KiUiDcvC2ukQA.jpeg
https://miro.medium.com/max/500/1*rkEkqec7TK_K2XyaHgs0_A.jpeg

Signing Up Users
We need mainly four edit texts — one for getting the first name, one for getting the last name, one for getting the email id and the last one for getting the password.
And finally, we need a button to submit these data. The layout for the signup activity is modified as follows-
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorAccent"
    android:padding="20dp"
    tools:context=".SignupActivity">

    <TextView
        android:id="@+id/tvTitleSignup"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="40dp"
        android:text="USER SIGN UP"
        android:textStyle="bold"
        android:textSize="28sp"
        android:textColor="@color/colorPrimaryDark"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <EditText
        android:id="@+id/etFirstName"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="76dp"
        android:hint="First Name"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/tvTitleSignup" />

    <EditText
        android:id="@+id/etLastName"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10"
        android:hint="Last Name"
        android:inputType="textPersonName"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/etFirstName" />

    <EditText
        android:id="@+id/etEmail"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10"
        android:hint="Email"
        android:inputType="textEmailAddress"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/etLastName" />

    <EditText
        android:id="@+id/etPassword"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10"
        android:hint="Password"
        android:inputType="textPassword"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/etEmail" />

    <Button
        android:id="@+id/btnSignUpUser"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimary"
        android:text="SIGN UP USER"
        android:textColor="#fff"
        android:textSize="16sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

The input data has to be trimmed, validated and verified before we pass it to the backend. All these are done in the SignupActivity.java.
An On Click Listener is added to the button that submit the data. Once the data is submitted, it is validated. After validation, a user object is created with the data and the object is passed through the API to Signup.
Once the signup is completed successfully, the application navigates to the signin activity. The controlling file of the signup activity as below-
https://miro.medium.com/max/600/1*VAiilXaeIVt_RUM4Mnk3og.jpeg

package com.webtutsplus.ecommerce;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class SignupActivity extends AppCompatActivity {

    private EditText etFirstName, etLastName, etEmail, etPassword;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_signup);

        etFirstName = findViewById(R.id.etFirstName);
        etLastName = findViewById(R.id.etLastName);
        etEmail = findViewById(R.id.etEmail);
        etPassword = findViewById(R.id.etPassword);

        findViewById(R.id.btnSignUpUser).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                signUpUser();
            }
        });
    }

    private void signUpUser() {
        String firstName = etFirstName.getText().toString().trim();
        String lastName = etLastName.getText().toString().trim();
        String email = etEmail.getText().toString().trim();
        String password = etPassword.getText().toString().trim();

        if (firstName.isEmpty()) {
            etFirstName.setError("First Name is required!");
            etFirstName.requestFocus();
            return;
        } else if (lastName.isEmpty()) {
            etLastName.setError("Last Name is required!");
            etLastName.requestFocus();
            return;
        } else if (email.isEmpty()) {
            etEmail.setError("Email is required!");
            etEmail.requestFocus();
            return;
        } else if (password.isEmpty()) {
            etPassword.setError("Password is required!");
            etPassword.requestFocus();
            return;
        }

        User user = new User(email, firstName, lastName, password);
        API api = RetrofitClient
                .getInstance()
                .getAPI();

        Call<ResponseBody> call = api.signup(user);
        call.enqueue(new Callback<ResponseBody>() {
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                try {
                    String test = response.body().string().toLowerCase();
                    if (test.contains("user created successfully"))
                    {
                        Toast.makeText(SignupActivity.this, "Successfully registered! ", Toast.LENGTH_LONG).show();
                        startActivity(new Intent(SignupActivity.this, SigninActivity.class));
                    }

                    else
                        Toast.makeText(SignupActivity.this, "Some error has occurred", Toast.LENGTH_LONG).show();
                } catch (Exception e) {
                    Toast.makeText(SignupActivity.this, "User already exists!", Toast.LENGTH_LONG).show();
                }
            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
                Toast.makeText(SignupActivity.this, t.getMessage(), Toast.LENGTH_LONG).show();
            }
        });
    }
}

We have the sign up part all ready. Let’s move to the sign in part of our application!

Signing In Users
For signing in users, we need just the user’s email to identify them and their password to verify them. To get them, we need two edit text views.
And also, a button is needed to submit the data. Below given is the layout file for sign-in activity.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorAccent"
    android:padding="20dp"
    tools:context=".SigninActivity">

    <TextView
        android:id="@+id/tvTitleSignin"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="40dp"
        android:text="USER SIGN IN"
        android:textStyle="bold"
        android:textSize="28sp"
        android:textColor="@color/colorPrimaryDark"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <EditText
        android:id="@+id/etEmail1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ems="10"
        android:hint="Email"
        android:layout_marginTop="40dp"
        android:inputType="textEmailAddress"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/tvTitleSignin" />

    <EditText
        android:id="@+id/etPassword1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:ems="10"
        android:hint="Password"
        android:inputType="textPassword"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/etEmail1" />

    <Button
        android:id="@+id/btnSignInUser"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimary"
        android:text="SIGN IN USER"
        android:textColor="#fff"
        android:textSize="16sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

The data from this layout is fetched, processed and verified with the backend API by the SigninActivity.java. It also should contain the on click listener for the button to submit the data.
Through the on click listener added, we receive the data from the fields and process it to create a user object. The object is then passed to the REST API, which verifies it and sends us a response to authenticate the user.
After successful authentication of the user, they are directed to the dashboard activity of the application.
https://miro.medium.com/max/600/1*XM5IDnpxGXC-31sbu0tTag.jpeg

package com.webtutsplus.ecommerce;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;

import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;

public class SigninActivity extends AppCompatActivity {

    private EditText etEmail, etPassword;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_signin);

        etEmail = findViewById(R.id.etEmail1);
        etPassword = findViewById(R.id.etPassword1);

        findViewById(R.id.btnSignInUser).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                signInUser();
            }
        });
    }

    private void signInUser() {
        String email = etEmail.getText().toString().trim();
        String password = etPassword.getText().toString().trim();

        if (email.isEmpty()) {
            etEmail.setError("Email is required!");
            etEmail.requestFocus();
            return;
        } else if (password.isEmpty()) {
            etPassword.setError("Password is required!");
            etPassword.requestFocus();
            return;
        }

        User user = new User(email, password);
        API api = RetrofitClient
                .getInstance()
                .getAPI();

        Call<ResponseBody> call = api.signin(user);
        call.enqueue(new Callback<ResponseBody>() {
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                try {
                    String test = response.body().string();
                    if (test.contains("success"))
                    {
                        Toast.makeText(SigninActivity.this, "Successfully logged in! ", Toast.LENGTH_LONG).show();
                        startActivity(new Intent(SigninActivity.this, DashboardActivity.class));
                    }

                    else
                        Toast.makeText(SigninActivity.this, "Check the credentials! ", Toast.LENGTH_LONG).show();
                } catch (Exception e) {
                    try {
                        Toast.makeText(SigninActivity.this, response.errorBody().string() + response.code(), Toast.LENGTH_LONG).show();
                    } catch (Exception e1) {
                        Toast.makeText(SigninActivity.this, e1.getMessage(), Toast.LENGTH_LONG).show();
                    }
                }
            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
                Toast.makeText(SigninActivity.this, t.getMessage(), Toast.LENGTH_LONG).show();
            }
        });
    }
}

The only remaining task before us is to make the dashboard activity. Without any delay, let’s do that!
Constructing the Dashboard
The dashboard activity seems similar to that of our main activity. It can also be called the main activity for authenticated users.
Authenticated users must be able to edit the products or add new products. For that sake, add the buttons for adding and updating the products. Also, add a button for viewing the products.
The layout file of the dashboard activity should be constructed as follows-
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorAccent"
    android:padding="20dp"
    tools:context=".DashboardActivity">

    <TextView
        android:id="@+id/tvTitle1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:fontFamily="cursive"
        android:padding="10dp"
        android:text="E-Commerce"
        android:textColor="@color/colorPrimaryDark"
        android:textSize="60sp"
        android:textStyle="bold"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="USER DASHBOARD"
        android:textColor="#000"
        android:textSize="20sp"
        android:textStyle="bold"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/tvTitle1" />

    <Button
        android:id="@+id/btnToAddProduct"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimary"
        android:text="ADD PRODUCT"
        android:textColor="#fff"
        android:textSize="16sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent" />

    <Button
        android:id="@+id/btnToUpdateProduct"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="60dp"
        android:background="@color/colorPrimary"
        android:text="UPDATE PRODUCT"
        android:textColor="#fff"
        android:textSize="16sp"
        app:layout_constraintBottom_toBottomOf="@id/btnToAddProduct"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent" />

    <Button
        android:id="@+id/btnToViewProducts1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="60dp"
        android:background="@color/colorPrimary"
        android:text="VIEW PRODUCTS"
        android:textColor="#fff"
        android:textSize="16sp"
        app:layout_constraintBottom_toBottomOf="@+id/btnToUpdateProduct"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

Let’s make these buttons in the dashboard activity functional! Go to the file DashboardActivity.java that controls the functioning of the activity. Add on click listeners to the buttons that we have added previously.
Set up the navigation correctly so that the user is navigated to the respective activities from the buttons.
The corresponding DashboardActivity.java file is as follows-
https://miro.medium.com/max/600/1*XM5IDnpxGXC-31sbu0tTag.jpeg

package com.webtutsplus.ecommerce;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Intent;
import android.os.Bundle;
import android.view.View;

public class DashboardActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_dashboard);

        findViewById(R.id.btnToViewProducts1).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                startActivity(new Intent(DashboardActivity.this, ListProductsActivity.class));
            }
        });

        findViewById(R.id.btnToAddProduct).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                startActivity(new Intent(DashboardActivity.this, AddProductActivity.class));
            }
        });

        findViewById(R.id.btnToUpdateProduct).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                startActivity(new Intent(DashboardActivity.this, UpdateProductActivity.class));
            }
        });
    }
}

Hurray! we have completed the coding section! Let’s run the application now!
Running the Application
Now, it’s time for running the application, after adding the required functionalities. Select the required Android Virtual Device from the toolbar and click on the run button on the same(Green triangle icon)
After a certain amount of time, your android virtual device will get the application installed and opened. You can completely use it now!

Resources
Bitbucket link for Spring Backend Project Repository
Bitbucket link for Android Application Project Repository
Spring Backend Swagger UI hosted on cloud
REST API of our Spring Backend
Tutorial for the creating Spring Backend API
Tutorial for creating the products application
Steps to install and set up Android Studio
Yahoo! That’s it! Hope you have learned many things from this tutorial. Stay tuned for such an awesome series of tutorials!
Happy Learning!