April 26, 2018

Android[Kotlin] Login and Register with SQLite Database Tutorial

By Lalit Vasan


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.

DownloadCode
 
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

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

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 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

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

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

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 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

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 login screen on the click of login link and shows snackbar with 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

Register Screen with Input Validation

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

Register Screen with input fields filled

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

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

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>() {

        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

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>
DownloadCode
 
github

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