Android[Kotlin] Login and Register with SQLite Database Tutorial
In software applications, it is mostly required to store users and app data locally. Android SDK provides several API’s for developers to save user and app data, So SQLite is one of the ways of storing data. For many applications, SQLite is the app’s backbone whether it’s used directly or via some third-party wrapper. In this tutorial, we will write code in Kotlin and also see how to use SQLite in our app directly.
What is SQLite?
SQLite is a lightweight database which comes with android. It is an Open-Source embedded SQL database engine. This provides relational database management structure for storing user-defined records in the form of tables.
Key point to understand regarding SQLite :-
– SQLite is RDBMS (Relational Database Management System)
– SQLite is written in C programming language
– SQLite is embedded within the Android Operating System, so you don’t need anything external on Android to use SQLite
– To manipulate data (insert, update, delete) in SQLite database – we’ll use SQL (Structured Query Language)
Let’s Get it Working
In this tutorial, we are going to learn how to use SQLite. To really understand the usage of SQLite we will create an app using Kotlin. The App contains simple Login form, Registration form, and a listing of a registered user. This app shows how SQLite database operations are performed. I assume that you have created a new android project. Source Code is available on GitHub.
Step 1) Update build.gradle file.
Before you can use Material Design in your projects you need to add the following compile line to your Gradle dependencies block in your build.gradle file and rebuilt the project .
dependencies {
    compile 'com.android.support:appcompat-v7:23.4.0'
    compile 'com.android.support:design:23.4.0'
    compile 'com.android.support:cardview-v7:23.4.0'
}
Step 2) Update strings.xml.
Add the below string values to the string.xml located in res ⇒ values ⇒ strings.xml.
<resources>
    <string name="app_name">Login Register</string>
    <string name="text_accounts">All Accounts</string>
    <string name="hint_name">Name</string>
    <string name="hint_email">Email</string>
    <string name="hint_password">Password</string>
    <string name="hint_confirm_password">Confirm Password</string>
    <string name="text_login">Login</string>
    <string name="text_register">Register</string>
    <string name="error_message_name">Enter Full Name</string>
    <string name="error_message_email">Enter Valid Email</string>
    <string name="error_message_age">Enter Age</string>
    <string name="error_message_password">Enter Password</string>
    <string name="success_message">Registration Successful</string>
    <string name="text_not_member">No account yet? Create one</string>
    <string name="text_already_member">Already a member? Login</string>
    <string name="error_email_exists">Email Already Exists</string>
    <string name="error_password_match">Password Does Not Matches</string>
    <string name="error_valid_email_password">Wrong Email or Password</string>
    <string name="action_settings">Settings</string>
    <string name="text_hello">Hello,</string>
    <string name="text_title">Android Tutorials Hub</string>
</resources>
Step 3) Update colors.xml.
Add the below color values to the colors.xml located in res ⇒ values ⇒ colors.xml.
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#51d8c7</color>
    <color name="colorPrimaryDark">#51d8c7</color>
    <color name="colorAccent">#FFFFFF</color>
    <color name="colorBackground">#413e4f</color>
    <color name="colorText">#FFFFFF</color>
    <color name="colorTextHint">#51d8c7</color>
</resources>
Step 4) Update styles.xml.
Add the below style values to the styles.xml located in res ⇒ values ⇒ styles.xml.
<resources>
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="android:textColor">@color/colorText</item>
        <item name="android:textColorHint">@color/colorText</item>
        <item name="colorControlNormal">@color/colorText</item>
        <item name="colorControlActivated">@color/colorText</item>
    </style>
</resources>
Step 5) Add Logo Image.
Download the below logo image and add it to the drawable folder located in res ⇒ drawable.

Android Tutorials Hub Logo
Step 6) Create User data class.
Create a new package named modal and create a Kotlin file/class named User to maintain single contact as an object.
package com.androidtutorialshub.loginregisterkotlin.model // model class data class User(val id: Int = -1, val name: String, val email: String, val password: String)
Step 7) Create DatabaseHelper class.
Create a new package named sql and create Kotlin class named DatabaseHelper. Extend this class with SQLiteOpenHelper to manage database creation and version management. I have also written some method to manipulate data in database.
Methods and functionality
– addUser :- add user to database.
– getAllUser :- fetch users data from database.
– updateUser :- update user in database on the basis of user id.
– deleteUser :- delete user from database on the basis of user id.
– checkUser :- check whether user exists in database.

User Table Schema
package com.androidtutorialshub.loginregisterkotlin.sql
import android.content.ContentValues
import android.content.Context
import android.database.sqlite.SQLiteDatabase
import android.database.sqlite.SQLiteOpenHelper
import com.androidtutorialshub.loginregisterkotlin.model.User
import java.util.*
class DatabaseHelper(context: Context) : SQLiteOpenHelper(context, DATABASE_NAME, null, DATABASE_VERSION) {
    // create table sql query
    private val CREATE_USER_TABLE = ("CREATE TABLE " + TABLE_USER + "("
            + COLUMN_USER_ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + COLUMN_USER_NAME + " TEXT,"
            + COLUMN_USER_EMAIL + " TEXT," + COLUMN_USER_PASSWORD + " TEXT" + ")")
    // drop table sql query
    private val DROP_USER_TABLE = "DROP TABLE IF EXISTS $TABLE_USER"
    override fun onCreate(db: SQLiteDatabase) {
        db.execSQL(CREATE_USER_TABLE)
    }
    override fun onUpgrade(db: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
        //Drop User Table if exist
        db.execSQL(DROP_USER_TABLE)
        // Create tables again
        onCreate(db)
    }
    /**
     * This method is to fetch all user and return the list of user records
     *
     * @return list
     */
    fun getAllUser(): List {
        // array of columns to fetch
        val columns = arrayOf(COLUMN_USER_ID, COLUMN_USER_EMAIL, COLUMN_USER_NAME, COLUMN_USER_PASSWORD)
        // sorting orders
        val sortOrder = "$COLUMN_USER_NAME ASC"
        val userList = ArrayList()
        val db = this.readableDatabase
        // query the user table
        val cursor = db.query(TABLE_USER, //Table to query
                columns,            //columns to return
                null,     //columns for the WHERE clause
                null,  //The values for the WHERE clause
                null,      //group the rows
                null,       //filter by row groups
                sortOrder)         //The sort order
        if (cursor.moveToFirst()) {
            do {
                val user = User(id = cursor.getString(cursor.getColumnIndex(COLUMN_USER_ID)).toInt(),
                        name = cursor.getString(cursor.getColumnIndex(COLUMN_USER_NAME)),
                        email = cursor.getString(cursor.getColumnIndex(COLUMN_USER_EMAIL)),
                        password = cursor.getString(cursor.getColumnIndex(COLUMN_USER_PASSWORD)))
                userList.add(user)
            } while (cursor.moveToNext())
        }
        cursor.close()
        db.close()
        return userList
    }
    /**
     * This method is to create user record
     *
     * @param user
     */
    fun addUser(user: User) {
        val db = this.writableDatabase
        val values = ContentValues()
        values.put(COLUMN_USER_NAME, user.name)
        values.put(COLUMN_USER_EMAIL, user.email)
        values.put(COLUMN_USER_PASSWORD, user.password)
        // Inserting Row
        db.insert(TABLE_USER, null, values)
        db.close()
    }
    /**
     * This method to update user record
     *
     * @param user
     */
    fun updateUser(user: User) {
        val db = this.writableDatabase
        val values = ContentValues()
        values.put(COLUMN_USER_NAME, user.name)
        values.put(COLUMN_USER_EMAIL, user.email)
        values.put(COLUMN_USER_PASSWORD, user.password)
        // updating row
        db.update(TABLE_USER, values, "$COLUMN_USER_ID = ?",
                arrayOf(user.id.toString()))
        db.close()
    }
    /**
     * This method is to delete user record
     *
     * @param user
     */
    fun deleteUser(user: User) {
        val db = this.writableDatabase
        // delete user record by id
        db.delete(TABLE_USER, "$COLUMN_USER_ID = ?",
                arrayOf(user.id.toString()))
        db.close()
    }
    /**
     * This method to check user exist or not
     *
     * @param email
     * @return true/false
     */
    fun checkUser(email: String): Boolean {
        // array of columns to fetch
        val columns = arrayOf(COLUMN_USER_ID)
        val db = this.readableDatabase
        // selection criteria
        val selection = "$COLUMN_USER_EMAIL = ?"
        // selection argument
        val selectionArgs = arrayOf(email)
        // query user table with condition
        /**
         * Here query function is used to fetch records from user table this function works like we use sql query.
         * SQL query equivalent to this query function is
         * SELECT user_id FROM user WHERE user_email = 'jack@androidtutorialshub.com';
         */
        val cursor = db.query(TABLE_USER, //Table to query
                columns,        //columns to return
                selection,      //columns for the WHERE clause
                selectionArgs,  //The values for the WHERE clause
                null,  //group the rows
                null,   //filter by row groups
                null)  //The sort order
        val cursorCount = cursor.count
        cursor.close()
        db.close()
        if (cursorCount > 0) {
            return true
        }
        return false
    }
    /**
     * This method to check user exist or not
     *
     * @param email
     * @param password
     * @return true/false
     */
    fun checkUser(email: String, password: String): Boolean {
        // array of columns to fetch
        val columns = arrayOf(COLUMN_USER_ID)
        val db = this.readableDatabase
        // selection criteria
        val selection = "$COLUMN_USER_EMAIL = ? AND $COLUMN_USER_PASSWORD = ?"
        // selection arguments
        val selectionArgs = arrayOf(email, password)
        // query user table with conditions
        /**
         * Here query function is used to fetch records from user table this function works like we use sql query.
         * SQL query equivalent to this query function is
         * SELECT user_id FROM user WHERE user_email = 'jack@androidtutorialshub.com' AND user_password = 'qwerty';
         */
        val cursor = db.query(TABLE_USER, //Table to query
                columns, //columns to return
                selection, //columns for the WHERE clause
                selectionArgs, //The values for the WHERE clause
                null,  //group the rows
                null, //filter by row groups
                null) //The sort order
        val cursorCount = cursor.count
        cursor.close()
        db.close()
        if (cursorCount > 0)
            return true
        return false
    }
    companion object {
        // Database Version
        private val DATABASE_VERSION = 1
        // Database Name
        private val DATABASE_NAME = "UserManager.db"
        // User table name
        private val TABLE_USER = "user"
        // User Table Columns names
        private val COLUMN_USER_ID = "user_id"
        private val COLUMN_USER_NAME = "user_name"
        private val COLUMN_USER_EMAIL = "user_email"
        private val COLUMN_USER_PASSWORD = "user_password"
    }
}
Step 8) Create activity_login.xml.
Now create a layout file for the LoginActivity.kt i.e activity_login.xml and add the below code in your layout file. The code will create a simple login form containing a logo on the top, 2 input fields email and password, login button, and registration screen navigation link.
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/nestedScrollView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorBackground"
    android:paddingBottom="20dp"
    android:paddingLeft="20dp"
    android:paddingRight="20dp"
    android:paddingTop="20dp"
    tools:context=".activities.LoginActivity">
    <android.support.v7.widget.LinearLayoutCompat
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <android.support.v7.widget.AppCompatImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:layout_marginTop="40dp"
            android:src="@drawable/logo" />
        <android.support.design.widget.TextInputLayout
            android:id="@+id/textInputLayoutEmail"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="40dp">
            <android.support.design.widget.TextInputEditText
                android:id="@+id/textInputEditTextEmail"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="@string/hint_email"
                android:inputType="text"
                android:maxLines="1"
                android:textColor="@android:color/white" />
        </android.support.design.widget.TextInputLayout>
        <android.support.design.widget.TextInputLayout
            android:id="@+id/textInputLayoutPassword"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp">
            <android.support.design.widget.TextInputEditText
                android:id="@+id/textInputEditTextPassword"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="@string/hint_password"
                android:inputType="textPassword"
                android:maxLines="1"
                android:textColor="@android:color/white" />
        </android.support.design.widget.TextInputLayout>
        <android.support.v7.widget.AppCompatButton
            android:id="@+id/appCompatButtonLogin"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="40dp"
            android:background="@color/colorTextHint"
            android:text="@string/text_login" />
        <android.support.v7.widget.AppCompatTextView
            android:id="@+id/textViewLinkRegister"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="30dp"
            android:gravity="center"
            android:text="@string/text_not_member"
            android:textSize="16dp" />
    </android.support.v7.widget.LinearLayoutCompat>
</android.support.v4.widget.NestedScrollView>
activity_login.xml would result a screen like this:

Login Screen
Step 8) Create InputValidation class.
Create a package named helpers and create a Kotlin class in it named InputValidation.kt and add below code in it. The code will create validation methods for input field. Validation like empty input, valid email and etc.
package com.androidtutorialshub.loginregisterkotlin.helpers
import android.app.Activity
import android.content.Context
import android.support.design.widget.TextInputEditText
import android.support.design.widget.TextInputLayout
import android.view.View
import android.view.WindowManager
import android.view.inputmethod.InputMethodManager
class InputValidation
/**
 * constructor
 *
 * @param context
 */
(private val context: Context) {
    /**
     * method to check InputEditText filled .
     *
     * @param textInputEditText
     * @param textInputLayout
     * @param message
     * @return
     */
    fun isInputEditTextFilled(textInputEditText: TextInputEditText, textInputLayout: TextInputLayout, message: String): Boolean {
        val value = textInputEditText.text.toString().trim()
        if (value.isEmpty()) {
            textInputLayout.error = message
            hideKeyboardFrom(textInputEditText)
            return false
        } else {
            textInputLayout.isErrorEnabled = false
        }
        return true
    }
    /**
     * method to check InputEditText has valid email .
     *
     * @param textInputEditText
     * @param textInputLayout
     * @param message
     * @return
     */
    fun isInputEditTextEmail(textInputEditText: TextInputEditText, textInputLayout: TextInputLayout, message: String): Boolean {
        val value = textInputEditText.text.toString().trim()
        if (value.isEmpty() || !android.util.Patterns.EMAIL_ADDRESS.matcher(value).matches()) {
            textInputLayout.error = message
            hideKeyboardFrom(textInputEditText)
            return false
        } else {
            textInputLayout.isErrorEnabled = false
        }
        return true
    }
    /**
     * method to check both InputEditText value matches.
     *
     * @param textInputEditText1
     * @param textInputEditText2
     * @param textInputLayout
     * @param message
     * @return
     */
    fun isInputEditTextMatches(textInputEditText1: TextInputEditText, textInputEditText2: TextInputEditText, textInputLayout: TextInputLayout, message: String): Boolean {
        val value1 = textInputEditText1.text.toString().trim()
        val value2 = textInputEditText2.text.toString().trim()
        if (!value1.contentEquals(value2)) {
            textInputLayout.error = message
            hideKeyboardFrom(textInputEditText2)
            return false
        } else {
            textInputLayout.isErrorEnabled = false
        }
        return true
    }
    /**
     * method to Hide keyboard
     *
     * @param view
     */
    private fun hideKeyboardFrom(view: View) {
        val imm = context.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager
        imm.hideSoftInputFromWindow(view.windowToken, WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN)
    }
}
Step 9) Create LoginActivity class.
Now create a package named activities and create a kotlin class named LoginActivity and add below code. Here i have written the code to validate the input fields Email and Password using the InputValidation class which i described above. Also code for navigation to registration screen on the click of registration link and to user list screen after click on login button if credentials are valid.
package com.androidtutorialshub.loginregisterkotlin.activities
import android.content.Intent
import android.os.Bundle
import android.support.design.widget.Snackbar
import android.support.design.widget.TextInputEditText
import android.support.design.widget.TextInputLayout
import android.support.v4.widget.NestedScrollView
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.AppCompatButton
import android.support.v7.widget.AppCompatTextView
import android.view.View
import com.androidtutorialshub.loginregisterkotlin.R
import com.androidtutorialshub.loginregisterkotlin.helpers.InputValidation
import com.androidtutorialshub.loginregisterkotlin.sql.DatabaseHelper
class LoginActivity : AppCompatActivity(), View.OnClickListener {
    private val activity = this@LoginActivity
    private lateinit var nestedScrollView: NestedScrollView
    private lateinit var textInputLayoutEmail: TextInputLayout
    private lateinit var textInputLayoutPassword: TextInputLayout
    private lateinit var textInputEditTextEmail: TextInputEditText
    private lateinit var textInputEditTextPassword: TextInputEditText
    private lateinit var appCompatButtonLogin: AppCompatButton
    private lateinit var textViewLinkRegister: AppCompatTextView
    private lateinit var inputValidation: InputValidation
    private lateinit var databaseHelper: DatabaseHelper
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_login)
        // hiding the action bar
        supportActionBar!!.hide()
        // initializing the views
        initViews()
        // initializing the listeners
        initListeners()
        // initializing the objects
        initObjects()
    }
    /**
     * This method is to initialize views
     */
    private fun initViews() {
        nestedScrollView = findViewById(R.id.nestedScrollView) as NestedScrollView
        textInputLayoutEmail = findViewById(R.id.textInputLayoutEmail) as TextInputLayout
        textInputLayoutPassword = findViewById(R.id.textInputLayoutPassword) as TextInputLayout
        textInputEditTextEmail = findViewById(R.id.textInputEditTextEmail) as TextInputEditText
        textInputEditTextPassword = findViewById(R.id.textInputEditTextPassword) as TextInputEditText
        appCompatButtonLogin = findViewById(R.id.appCompatButtonLogin) as AppCompatButton
        textViewLinkRegister = findViewById(R.id.textViewLinkRegister) as AppCompatTextView
    }
    /**
     * This method is to initialize listeners
     */
    private fun initListeners() {
        appCompatButtonLogin!!.setOnClickListener(this)
        textViewLinkRegister!!.setOnClickListener(this)
    }
    /**
     * This method is to initialize objects to be used
     */
    private fun initObjects() {
        databaseHelper = DatabaseHelper(activity)
        inputValidation = InputValidation(activity)
    }
    /**
     * This implemented method is to listen the click on view
     *
     * @param v
     */
    override fun onClick(v: View) {
        when (v.id) {
            R.id.appCompatButtonLogin -> verifyFromSQLite()
            R.id.textViewLinkRegister -> {
                // Navigate to RegisterActivity
                val intentRegister = Intent(applicationContext, RegisterActivity::class.java)
                startActivity(intentRegister)
            }
        }
    }
    /**
     * This method is to validate the input text fields and verify login credentials from SQLite
     */
    private fun verifyFromSQLite() {
        if (!inputValidation!!.isInputEditTextFilled(textInputEditTextEmail!!, textInputLayoutEmail!!, getString(R.string.error_message_email))) {
            return
        }
        if (!inputValidation!!.isInputEditTextEmail(textInputEditTextEmail!!, textInputLayoutEmail!!, getString(R.string.error_message_email))) {
            return
        }
        if (!inputValidation!!.isInputEditTextFilled(textInputEditTextPassword!!, textInputLayoutPassword!!, getString(R.string.error_message_email))) {
            return
        }
        if (databaseHelper!!.checkUser(textInputEditTextEmail!!.text.toString().trim { it <= ' ' }, textInputEditTextPassword!!.text.toString().trim { it <= ' ' })) {
            val accountsIntent = Intent(activity, UsersListActivity::class.java)
            accountsIntent.putExtra("EMAIL", textInputEditTextEmail!!.text.toString().trim { it <= ' ' })
            emptyInputEditText()
            startActivity(accountsIntent)
        } else {
            // Snack Bar to show success message that record is wrong
            Snackbar.make(nestedScrollView!!, getString(R.string.error_valid_email_password), Snackbar.LENGTH_LONG).show()
        }
    }
    /**
     * This method is to empty all input edit text
     */
    private fun emptyInputEditText() {
        textInputEditTextEmail!!.text = null
        textInputEditTextPassword!!.text = null
    }
}
The Screen below shows the login form with input validation display the error message if values entered in input fields are not valid.

Login Screen with Input Validation
The Screen below shows the login form with input validation display the snack bar with message if values entered in input fields are not validated from SQLite database.

Login Screen With SQLite Validation
Step 10) Create activity_register.xml.
Now create a layout file for the RegisterActivity.kt i.e activity_register.xml and add the below code in your layout file. The code will create a simple registration form containing a logo on the top, 4 input fields name, email, password, and confirm password, register button, and login screen navigation link.
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/nestedScrollView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorBackground"
    android:paddingBottom="20dp"
    android:paddingLeft="20dp"
    android:paddingRight="20dp"
    android:paddingTop="20dp"
    tools:context=".activities.LoginActivity">
    <android.support.v7.widget.LinearLayoutCompat
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <android.support.v7.widget.AppCompatImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"
            android:layout_marginTop="40dp"
            android:src="@drawable/logo" />
        <android.support.design.widget.TextInputLayout
            android:id="@+id/textInputLayoutName"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="40dp">
            <android.support.design.widget.TextInputEditText
                android:id="@+id/textInputEditTextName"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="@string/hint_name"
                android:inputType="text"
                android:maxLines="1"
                android:textColor="@android:color/white" />
        </android.support.design.widget.TextInputLayout>
        <android.support.design.widget.TextInputLayout
            android:id="@+id/textInputLayoutEmail"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp">
            <android.support.design.widget.TextInputEditText
                android:id="@+id/textInputEditTextEmail"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="@string/hint_email"
                android:inputType="text"
                android:maxLines="1"
                android:textColor="@android:color/white" />
        </android.support.design.widget.TextInputLayout>
        <android.support.design.widget.TextInputLayout
            android:id="@+id/textInputLayoutPassword"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp">
            <android.support.design.widget.TextInputEditText
                android:id="@+id/textInputEditTextPassword"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="@string/hint_password"
                android:inputType="textPassword"
                android:maxLines="1"
                android:textColor="@android:color/white" />
        </android.support.design.widget.TextInputLayout>
        <android.support.design.widget.TextInputLayout
            android:id="@+id/textInputLayoutConfirmPassword"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp">
            <android.support.design.widget.TextInputEditText
                android:id="@+id/textInputEditTextConfirmPassword"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="@string/hint_confirm_password"
                android:inputType="textPassword"
                android:maxLines="1"
                android:textColor="@android:color/white" />
        </android.support.design.widget.TextInputLayout>
        <android.support.v7.widget.AppCompatButton
            android:id="@+id/appCompatButtonRegister"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="40dp"
            android:background="@color/colorTextHint"
            android:text="@string/text_register" />
        <android.support.v7.widget.AppCompatTextView
            android:id="@+id/appCompatTextViewLoginLink"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="30dp"
            android:gravity="center"
            android:text="Already a member? Login"
            android:textSize="16dp" />
    </android.support.v7.widget.LinearLayoutCompat>
</android.support.v4.widget.NestedScrollView>
activity_register.xml would result a screen like this:

Registration Screen
Step 11) Create RegisterActivity class.
Now create a package named activities and create a kotlin class named RegisterActivity and add below code. Here I have written the code to validate the input fields Name, Email, Password, and Confirm Password using the InputValidation class which I described above. Also, code for navigation to the login screen on the click of the login link and shows a snack bar with a success message for registration.
package com.androidtutorialshub.loginregisterkotlin.activities
import android.os.Bundle
import android.support.design.widget.Snackbar
import android.support.design.widget.TextInputEditText
import android.support.design.widget.TextInputLayout
import android.support.v4.widget.NestedScrollView
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.AppCompatButton
import android.support.v7.widget.AppCompatTextView
import android.view.View
import com.androidtutorialshub.loginregisterkotlin.R
import com.androidtutorialshub.loginregisterkotlin.helpers.InputValidation
import com.androidtutorialshub.loginregisterkotlin.model.User
import com.androidtutorialshub.loginregisterkotlin.sql.DatabaseHelper
class RegisterActivity : AppCompatActivity(), View.OnClickListener {
    private val activity = this@RegisterActivity
    private lateinit var nestedScrollView: NestedScrollView
    private lateinit var textInputLayoutName: TextInputLayout
    private lateinit var textInputLayoutEmail: TextInputLayout
    private lateinit var textInputLayoutPassword: TextInputLayout
    private lateinit var textInputLayoutConfirmPassword: TextInputLayout
    private lateinit var textInputEditTextName: TextInputEditText
    private lateinit var textInputEditTextEmail: TextInputEditText
    private lateinit var textInputEditTextPassword: TextInputEditText
    private lateinit var textInputEditTextConfirmPassword: TextInputEditText
    private lateinit var appCompatButtonRegister: AppCompatButton
    private lateinit var appCompatTextViewLoginLink: AppCompatTextView
    private lateinit var inputValidation: InputValidation
    private lateinit var databaseHelper: DatabaseHelper
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_register)
        // hiding the action bar
        supportActionBar!!.hide()
        // initializing the views
        initViews()
        // initializing the listeners
        initListeners()
        // initializing the objects
        initObjects()
    }
    /**
     * This method is to initialize views
     */
    private fun initViews() {
        nestedScrollView = findViewById(R.id.nestedScrollView) as NestedScrollView
        textInputLayoutName = findViewById(R.id.textInputLayoutName) as TextInputLayout
        textInputLayoutEmail = findViewById(R.id.textInputLayoutEmail) as TextInputLayout
        textInputLayoutPassword = findViewById(R.id.textInputLayoutPassword) as TextInputLayout
        textInputLayoutConfirmPassword = findViewById(R.id.textInputLayoutConfirmPassword) as TextInputLayout
        textInputEditTextName = findViewById(R.id.textInputEditTextName) as TextInputEditText
        textInputEditTextEmail = findViewById(R.id.textInputEditTextEmail) as TextInputEditText
        textInputEditTextPassword = findViewById(R.id.textInputEditTextPassword) as TextInputEditText
        textInputEditTextConfirmPassword = findViewById(R.id.textInputEditTextConfirmPassword) as TextInputEditText
        appCompatButtonRegister = findViewById(R.id.appCompatButtonRegister) as AppCompatButton
        appCompatTextViewLoginLink = findViewById(R.id.appCompatTextViewLoginLink) as AppCompatTextView
    }
    /**
     * This method is to initialize listeners
     */
    private fun initListeners() {
        appCompatButtonRegister!!.setOnClickListener(this)
        appCompatTextViewLoginLink!!.setOnClickListener(this)
    }
    /**
     * This method is to initialize objects to be used
     */
    private fun initObjects() {
        inputValidation = InputValidation(activity)
        databaseHelper = DatabaseHelper(activity)
    }
    /**
     * This implemented method is to listen the click on view
     *
     * @param v
     */
    override fun onClick(v: View) {
        when (v.id) {
            R.id.appCompatButtonRegister -> postDataToSQLite()
            R.id.appCompatTextViewLoginLink -> finish()
        }
    }
    /**
     * This method is to validate the input text fields and post data to SQLite
     */
    private fun postDataToSQLite() {
        if (!inputValidation!!.isInputEditTextFilled(textInputEditTextName, textInputLayoutName, getString(R.string.error_message_name))) {
            return
        }
        if (!inputValidation!!.isInputEditTextFilled(textInputEditTextEmail, textInputLayoutEmail, getString(R.string.error_message_email))) {
            return
        }
        if (!inputValidation!!.isInputEditTextEmail(textInputEditTextEmail, textInputLayoutEmail, getString(R.string.error_message_email))) {
            return
        }
        if (!inputValidation!!.isInputEditTextFilled(textInputEditTextPassword, textInputLayoutPassword, getString(R.string.error_message_password))) {
            return
        }
        if (!inputValidation!!.isInputEditTextMatches(textInputEditTextPassword, textInputEditTextConfirmPassword,
                        textInputLayoutConfirmPassword, getString(R.string.error_password_match))) {
            return
        }
        if (!databaseHelper!!.checkUser(textInputEditTextEmail!!.text.toString().trim())) {
            var user = User(name = textInputEditTextName!!.text.toString().trim(),
                    email = textInputEditTextEmail!!.text.toString().trim(),
                    password = textInputEditTextPassword!!.text.toString().trim())
            databaseHelper!!.addUser(user)
            // Snack Bar to show success message that record saved successfully
            Snackbar.make(nestedScrollView!!, getString(R.string.success_message), Snackbar.LENGTH_LONG).show()
            emptyInputEditText()
        } else {
            // Snack Bar to show error message that record already exists
            Snackbar.make(nestedScrollView!!, getString(R.string.error_email_exists), Snackbar.LENGTH_LONG).show()
        }
    }
    /**
     * This method is to empty all input edit text
     */
    private fun emptyInputEditText() {
        textInputEditTextName!!.text = null
        textInputEditTextEmail!!.text = null
        textInputEditTextPassword!!.text = null
        textInputEditTextConfirmPassword!!.text = null
    }
}
The Screen below shows the register form with input validation display the error message if values entered in input fields are not valid.

Register Screen with Input Validation
The Screen below shows the filled register form with valid values.

Register Screen with filled input fields
The Screen below shows the register form display the snackbar with registration success message.

Register Screen with Registration Success Message
Step 12) Create activity_users_list.xml.
Now create a layout file for the UsersListActivity.kt i.e activity_users_list.xml and add the below code in your layout file. The code will create a simple view containing two views one view i.e LinearLayout shows the welcome message with email id of the logged-in user and other views i.e RecyclerView shows the list of registered users in the app.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <android.support.v7.widget.LinearLayoutCompat
        android:layout_width="match_parent"
        android:layout_height="150dp"
        android:background="@color/colorPrimary"
        android:gravity="center"
        android:orientation="vertical">
        <android.support.v7.widget.AppCompatTextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/text_title"
            android:textSize="20sp" />
        <android.support.v7.widget.AppCompatTextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="10dp"
            android:text="@string/text_hello" />
        <android.support.v7.widget.AppCompatTextView
            android:id="@+id/textViewName"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </android.support.v7.widget.LinearLayoutCompat>
    <android.support.v7.widget.AppCompatTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingBottom="5dp"
        android:paddingLeft="16dp"
        android:paddingTop="5dp"
        android:text="@string/text_accounts"
        android:textColor="@android:color/black" />
    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerViewUsers"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>
activity_users_list.xml would result a screen like this:

User List Screen
Step 13) Writing the Adapter Class.
Now create a package named adapters and create a kotlin class named UsersRecyclerAdapter and add below code. Here onCreateViewHolder() method inflates item_user_recycler.xml. In onBindViewHolder() method the appropriate User data (name,email and password) set to each row.
package com.androidtutorialshub.loginregisterkotlin.adapters
import android.support.v7.widget.AppCompatTextView
import android.support.v7.widget.RecyclerView
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import com.androidtutorialshub.loginregisterkotlin.R
import com.androidtutorialshub.loginregisterkotlin.model.User
class UsersRecyclerAdapter(private val listUsers: List) : RecyclerView.Adapter() {
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserViewHolder {
        // inflating recycler item view
        val itemView = LayoutInflater.from(parent.context)
                .inflate(R.layout.item_user_recycler, parent, false)
        return UserViewHolder(itemView)
    }
    override fun onBindViewHolder(holder: UserViewHolder, position: Int) {
        holder.textViewName.text = listUsers[position].name
        holder.textViewEmail.text = listUsers[position].email
        holder.textViewPassword.text = listUsers[position].password
    }
    override fun getItemCount(): Int {
        return listUsers.size
    }
    /**
     * ViewHolder class
     */
    inner class UserViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        var textViewName: AppCompatTextView
        var textViewEmail: AppCompatTextView
        var textViewPassword: AppCompatTextView
        init {
            textViewName = view.findViewById(R.id.textViewName) as AppCompatTextView
            textViewEmail = view.findViewById(R.id.textViewEmail) as AppCompatTextView
            textViewPassword = view.findViewById(R.id.textViewPassword) as AppCompatTextView
        }
    }
}
item_user_recycler.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    card_view:cardCornerRadius="4dp">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:padding="16dp">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal">
            <android.support.v7.widget.AppCompatTextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_weight="2"
                android:text="@string/hint_name"
                android:textColor="@color/colorTextHint" />
            <android.support.v7.widget.AppCompatTextView
                android:id="@+id/textViewName"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="@string/hint_name"
                android:textColor="@android:color/darker_gray" />
        </LinearLayout>
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="5dp"
            android:orientation="horizontal">
            <android.support.v7.widget.AppCompatTextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_weight="2"
                android:text="@string/hint_email"
                android:textColor="@color/colorTextHint" />
            <android.support.v7.widget.AppCompatTextView
                android:id="@+id/textViewEmail"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="@string/hint_email"
                android:textColor="@android:color/darker_gray" />
        </LinearLayout>
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginTop="5dp"
            android:orientation="horizontal">
            <android.support.v7.widget.AppCompatTextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_weight="2"
                android:text="@string/hint_password"
                android:textColor="@color/colorTextHint" />
            <android.support.v7.widget.AppCompatTextView
                android:id="@+id/textViewPassword"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:text="@string/hint_password"
                android:textColor="@android:color/darker_gray" />
        </LinearLayout>
    </LinearLayout>
</android.support.v7.widget.CardView>
Step 14) Create UsersListActivity class.
Now create a package named activities and create a kotlin class named UsersListActivity and add below code. Here I have written the code to show the email id of the logged in user and the list of registered users.
package com.androidtutorialshub.loginregisterkotlin.activities
import android.os.AsyncTask
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.AppCompatTextView
import android.support.v7.widget.DefaultItemAnimator
import android.support.v7.widget.LinearLayoutManager
import android.support.v7.widget.RecyclerView
import android.view.View
import com.androidtutorialshub.loginregisterkotlin.R
import com.androidtutorialshub.loginregisterkotlin.adapters.UsersRecyclerAdapter
import com.androidtutorialshub.loginregisterkotlin.model.User
import com.androidtutorialshub.loginregisterkotlin.sql.DatabaseHelper
class UsersListActivity : AppCompatActivity() {
    private val activity = this@UsersListActivity
    private lateinit var textViewName: AppCompatTextView
    private lateinit var recyclerViewUsers: RecyclerView
    private lateinit var listUsers: MutableList
    private lateinit var usersRecyclerAdapter: UsersRecyclerAdapter
    private lateinit var databaseHelper: DatabaseHelper
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_users_list)
        supportActionBar!!.title = ""
        initViews()
        initObjects()
    }
    /**
     * This method is to initialize views
     */
    private fun initViews() {
        textViewName = findViewById(R.id.textViewName) as AppCompatTextView
        recyclerViewUsers = findViewById(R.id.recyclerViewUsers) as RecyclerView
    }
    /**
     * This method is to initialize objects to be used
     */
    private fun initObjects() {
        listUsers = ArrayList()
        usersRecyclerAdapter = UsersRecyclerAdapter(listUsers)
        val mLayoutManager = LinearLayoutManager(applicationContext)
        recyclerViewUsers.layoutManager = mLayoutManager
        recyclerViewUsers.itemAnimator = DefaultItemAnimator()
        recyclerViewUsers.setHasFixedSize(true)
        recyclerViewUsers.adapter = usersRecyclerAdapter
        databaseHelper = DatabaseHelper(activity)
        val emailFromIntent = intent.getStringExtra("EMAIL")
        textViewName.text = emailFromIntent
        var getDataFromSQLite = GetDataFromSQLite()
        getDataFromSQLite.execute()
    }
    /**
     * This class is to fetch all user records from SQLite
     */
    inner class GetDataFromSQLite : AsyncTask<Void, Void, List>() {
        override fun doInBackground(vararg p0: Void?): List {
            return databaseHelper.getAllUser()
        }
        override fun onPostExecute(result: List?) {
            super.onPostExecute(result)
            listUsers.clear()
            listUsers.addAll(result!!)
        }
    }
}
The Screen below after user login shows the brand name, email id of logged in user and registered users list.

User List Screen After Login
Step 15) Update AndroidManifest.xml.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.androidtutorialshub.loginregister">
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".activities.LoginActivity"
            android:screenOrientation="portrait">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".activities.RegisterActivity"
            android:screenOrientation="portrait" />
        <activity
            android:name=".activities.UsersListActivity"
            android:screenOrientation="portrait" />
    </application>
</manifest>
Please feel free to comment as well as ask questions. And, yeah! If this post helps you please do share!
Enjoy Coding and Share Knowledge
 
    
