If you are building an app that needs a user to login to the app, then you need to remember the user login for the subsequent sessions without entering him/her password until he/she choose to logout.
On the web, there is a session and cookies which preserve all the necessary user data. In Android, we have SharedPreferences that store the data until the user uninstalls the app or clears the data of the app from app settings.
In Kotlin, the use of SharedPreferences is very easy using an object class. First, we will create this object class.
object AppPreferences { private const val NAME = "AComputerEngineer" private const val MODE = Context.MODE_PRIVATE private lateinit var preferences: SharedPreferences fun init(context: Context) { preferences = context.getSharedPreferences(NAME, MODE) } }
Now we will add different properties to the above class so we can use them directly in our app wherever needed.
AppPreferences.kt
object AppPreferences { private const val NAME = "AComputerEngineer" private const val MODE = Context.MODE_PRIVATE private lateinit var preferences: SharedPreferences //SharedPreferences variables private val IS_LOGIN = Pair("is_login", false) private val USERNAME = Pair("username", "") private val PASSWORD = Pair("password", "") fun init(context: Context) { preferences = context.getSharedPreferences(NAME, MODE) } //an inline function to put variable and save it private inline fun SharedPreferences.edit(operation: (SharedPreferences.Editor) -> Unit) { val editor = edit() operation(editor) editor.apply() } //SharedPreferences variables getters/setters var isLogin: Boolean get() = preferences.getBoolean(IS_LOGIN.first, IS_LOGIN.second) set(value) = preferences.edit { it.putBoolean(IS_LOGIN.first, value) } var username: String get() = preferences.getString(USERNAME.first, USERNAME.second) ?: "" set(value) = preferences.edit { it.putString(USERNAME.first, value) } var password: String get() = preferences.getString(PASSWORD.first, PASSWORD.second) ?: "" set(value) = preferences.edit { it.putString(PASSWORD.first, value) } }
You may have noticed here that we used one inline function SharedPreferences.edit that will create the SharedPreferences.Editor object and then save the variable by apply(). In between those 2 lines, we will perform our putString, putInt, putBoolean, etc operation. This inline function is a very nice feature of Kotlin which helps us to reduce the code.
Now we will initialise the above class in our Application file.
AComputerEngineerApp.kt
class AComputerEngineerApp : Application() { override fun onCreate() { super.onCreate() AppPreferences.init(this) } }
Do not forget to add this file name in our manifest file in application tag.
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.acomputerengineer"> <application android:name=".Utils.AComputerEngineerApp" android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme" tools:ignore="GoogleAppIndexingWarning"> </application> </manifest>
Now we can use this anywhere in our app. Like the below example.
textViewUsername.text = AppPreferences.username //or AppPreferences.username = editTextUserName.text.toString()
How to maintain User Login-Logout Session in Android Kotlin
First, we create a simple login-logout layout for the session example.
activity_shared_preferences.xml
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.acomputerengineer.BottomNavigationViewActivity"> <TextView android:id="@+id/tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="10dp" android:text="@string/login_note" android:textSize="20sp" android:textStyle="bold" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <EditText android:id="@+id/etUsername" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_margin="10dp" android:hint="@string/username" android:inputType="text" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/tv" /> <EditText android:id="@+id/etPassword" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_margin="10dp" android:hint="@string/password" android:inputType="textPassword" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/etUsername" /> <Button android:id="@+id/btnLogin" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_margin="10dp" android:text="@string/login" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/etPassword" /> </androidx.constraintlayout.widget.ConstraintLayout>
It will look like this when login and logout respectively.
Now we will see the Kotlin code file on how to implement the session using SharedPreferences.
The first thing we check here is if the user is logged in or logged out. And according to that, we will set up the layout to display.
if (AppPreferences.isLogin) { tv.text = getString(R.string.welcome_note, AppPreferences.username) etUsername.visibility = GONE etPassword.visibility = GONE btnLogin.text = getString(R.string.logout) } else { tv.text = getString(R.string.login_note) etUsername.visibility = VISIBLE etPassword.visibility = VISIBLE btnLogin.text = getString(R.string.login) }
Here we checked if the user is logged in or not using AppPreferences.isLogin boolean. And then display the content according to it.
Now we will see the button click event for login and logout. I just displayed the whole activity so you can understand how it works.
SharedPreferencesActivity.kt
class SharedPreferencesActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_shared_preferences) setupLoginLayout() btnLogin.setOnClickListener { if (AppPreferences.isLogin) { AppPreferences.isLogin = false AppPreferences.username = "" AppPreferences.password = "" } else { val username = etUsername.text.toString() val password = etPassword.text.toString() if (username.isNotBlank() && password.isNotBlank()) { AppPreferences.isLogin = true AppPreferences.username = username AppPreferences.password = password } else { Toast.makeText(this, R.string.login_validation, Toast.LENGTH_SHORT).show() } } setupLoginLayout() } } private fun setupLoginLayout() { if (AppPreferences.isLogin) { tv.text = getString(R.string.welcome_note, AppPreferences.username) etUsername.visibility = GONE etPassword.visibility = GONE btnLogin.text = getString(R.string.logout) } else { tv.text = getString(R.string.login_note) etUsername.visibility = VISIBLE etPassword.visibility = VISIBLE btnLogin.text = getString(R.string.login) } } }
Here when the user clicks on login, we checked if the user is already logged in or not. If not, then we saved the username and password to the SharedPreferences using AppPreferences class and then change the text of the login button to Logout.
And if the user is already logged in, we cleared out the username and password and display the layout of login using the function we have created.
You can find the whole code in my github repo: https://github.com/dakshbhatt21/a-computer-engineer