This article will guide you on everything you need to know to create your own custom password strength calculator using android studio with kotlin, and at the end of this article you will be provided with a link to the source code. Kindly read on.
In Modern day Application Development, security is always an issue to be on the lookout for.
That is why most application developers need a way to guide their users who sign up with their applications on the best way to create secure passwords.
Developers often employ different tools and libraries to check the strength of a password. Today we’ll be showing you how to build and customize a password strength calculator in Kotlin for Android Applications.
In this tutorial we would be building a password strength calculator to check our passwords and this can further be deployed for use in our applications.
We’ll do this by creating a kotlin enum class, and this is basically just a class with an enum modifier in front of the class, and they are data types that hold a set of constants. An instance of an enum class is shown below.
enum class Months{
January,
February,
March
}
Pre-requisites
- Android Studio 3.0 or later and a fair knowledge around it.
- An Up-to-date Android Studio
- A device or emulator that runs API level 26
- A Good level of familiarity with Kotlin Programming Language.
An Understanding of Basic Android Fundamentals such as the following is also required.
- Kotlin Control Structures such as for Loops and While Loops
- If Statements
- Basic Understanding of Enumerations in Kotlin
- It helps to be familiar with software architectural patterns that separate data from the user interface, such as MVP or MVC.
Let’s get Started
1.We’ll start by creating an enum class and naming it PasswordStrenght. This is what our enum interface will look like.
enum class PasswordStrength private constructor(internal var resId: Int, color: Int) {
WEAK(R.string.password_strength_weak, Color.RED),
MEDIUM(R.string.password_strength_medium, Color.argb(255, 220, 185, 0)),
STRONG(R.string.password_strength_strong, Color.GREEN),
VERY_STRONG(R.string.password_strength_very_strong, Color.BLUE);
var color: Int = 0
internal set
init {
this.color = color
}
fun getText(ctx: android.content.Context): CharSequence {
return ctx.getText(resId)
}
companion object {
//This value defines the minimum length for the password
internal var REQUIRED_LENGTH = 8
//This value determines the maximum length of the password
internal var MAXIMUM_LENGTH = 15
//This value determines if the password should contain special characters. set it as "false" if you
//do not require special characters for your password field.
internal var REQUIRE_SPECIAL_CHARACTERS = true
//This value determines if the password should contain digits. set it as "false" if you
//do not require digits for your password field.
internal var REQUIRE_DIGITS = true
//This value determines if the password should require low case. Set it as "false" if you
//do not require lower cases for your password field.
internal var REQUIRE_LOWER_CASE = true
//This value determines if the password should require upper case. Set it as "false" if you
//do not require upper cases for your password field.
internal var REQUIRE_UPPER_CASE = false
fun calculateStrength(password: String): PasswordStrength {
var currentScore = 0
var sawUpper = false
var sawLower = false
var sawDigit = false
var sawSpecial = false
for (i in 0 until password.length) {
val c = password[i]
if (!sawSpecial && !Character.isLetterOrDigit(c)) {
currentScore += 1
sawSpecial = true
} else {
if (!sawDigit && Character.isDigit(c)) {
currentScore += 1
sawDigit = true
} else {
if (!sawUpper || !sawLower) {
if (Character.isUpperCase(c))
sawUpper = true
else
sawLower = true
if (sawUpper && sawLower)
currentScore += 1
}
}
}
}
if (password.length > REQUIRED_LENGTH) {
if (REQUIRE_SPECIAL_CHARACTERS && !sawSpecial
|| REQUIRE_UPPER_CASE && !sawUpper
|| REQUIRE_LOWER_CASE && !sawLower
|| REQUIRE_DIGITS && !sawDigit) {
currentScore = 1
} else {
currentScore = 2
if (password.length > MAXIMUM_LENGTH) {
currentScore = 3
}
}
} else {
currentScore = 0
}
when (currentScore) {
0 -> return WEAK
1 -> return MEDIUM
2 -> return STRONG
3 -> return VERY_STRONG
}
return VERY_STRONG
}
}
}
I’ll begin by explaining the four constants we have to indicate the different strengths of a password and they include the following
- WEAK
- MEDIUM
- STRONG
- VERY STRONG
Each of these fields are associated with a corresponding string stored in our string values resource file, and also a color to go with.
Furthermore, in our companion object, we have the conditions we want our password to meet as variable of int and boolean types. They include the following.
- Required Length – Int
- Maximum Legth – Int
- Required Special Characters – Boolean
- Required Digits – Boolean
- Required Lowercase – Boolean
- Required Uppercase – Boolean
2. This is what our layout file looks like for our password strength calculator application.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/linearLayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="16dp">
<EditText
android:id="@+id/login_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="152dp"
android:background="@null"
android:clickable="true"
android:freezesText="true"
android:hint="Enter Password"
android:inputType="textPassword"
android:padding="10dp"
android:singleLine="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:indeterminate="false"
android:maxHeight="20dip"
android:minHeight="20dip"
android:progress="0"
app:layout_constraintEnd_toStartOf="@+id/password_strength"
app:layout_constraintStart_toStartOf="@+id/login_password"
app:layout_constraintTop_toBottomOf="@+id/login_password" />
<TextView
android:id="@+id/password_strength"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="Weak"
app:layout_constraintBottom_toBottomOf="@+id/progressBar"
app:layout_constraintEnd_toEndOf="@+id/login_password"
app:layout_constraintTop_toBottomOf="@+id/login_password" />
<TextView
android:id="@+id/login_instructions"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Your password must be at least 8 characters. With at least 1 number and 1 special character"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/progressBar" />
</androidx.constraintlayout.widget.ConstraintLayout>
From the foregoing we using a Constraint Layout as our Parent View, which will house all the widgets we are going to be using. We have a textview to show instructions and an EditText widget which will receive the input from the user.
3. Finally, Let’s take a good look at our MainActivity class, which is the entry point of our application and where we’ll be employing our newly created enum class.
class MainActivity : AppCompatActivity(), TextWatcher {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val password = findViewById<EditText>(R.id.login_password) as EditText
password.addTextChangedListener(this)
}
override fun afterTextChanged(s: Editable) {}
override fun beforeTextChanged(
s: CharSequence, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
updatePasswordStrengthView(s.toString())
}
private fun updatePasswordStrengthView(password: String) {
val progressBar = findViewById<ProgressBar>(R.id.progressBar) as ProgressBar
val strengthView = findViewById<ProgressBar>(R.id.password_strength) as TextView
if (TextView.VISIBLE != strengthView.visibility)
return
if (TextUtils.isEmpty(password)) {
strengthView.text = ""
progressBar.progress = 0
return
}
val str = PasswordStrength.calculateStrength(password)
strengthView.text = str.getText(this)
strengthView.setTextColor(str.color)
progressBar.progressDrawable.setColorFilter(str.color, android.graphics.PorterDuff.Mode.SRC_IN)
if (str.getText(this) == "Weak") {
progressBar.progress = 25
} else if (str.getText(this) == "Medium") {
progressBar.progress = 50
} else if (str.getText(this) == "Strong") {
progressBar.progress = 75
} else {
progressBar.progress = 100
}
}
}
In our mainactivity class we set up our edittext and associate it with a textwatcher. You can read more about the TextWatcher class HERE.
The text watcher enables us observe changes in the text and helps us trigger an action whenever we observe changes. Furthermore, we use an object of our PasswordStrength enum class to observe changes in the password and check what the return value is each time, so we can update our progress bar simultaneously.
With this, you can compile your application and run it for your desired result.
That’s it. Now you have a Password Strength Calculator Application. You can find the source code for this project below.
The source code can be found by clicking HERE
If you found this post informative, or have a question do well to drop a comment below and don’t forget to share with your friends.