<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Joseph Olugbohunmi</title>
    <description>The latest articles on DEV Community by Joseph Olugbohunmi (@mayorjay).</description>
    <link>https://dev.to/mayorjay</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F487435%2Fe902ffc6-018c-4107-8c35-d2a32cae344f.jpeg</url>
      <title>DEV Community: Joseph Olugbohunmi</title>
      <link>https://dev.to/mayorjay</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mayorjay"/>
    <language>en</language>
    <item>
      <title>My first attempt at Deploying a Backend Service on AWS: A Journey of Learning and Problem-Solving</title>
      <dc:creator>Joseph Olugbohunmi</dc:creator>
      <pubDate>Sat, 30 Nov 2024 23:47:51 +0000</pubDate>
      <link>https://dev.to/mayorjay/my-first-attempt-at-deploying-a-backend-service-on-aws-a-journey-of-learning-and-problem-solving-2n93</link>
      <guid>https://dev.to/mayorjay/my-first-attempt-at-deploying-a-backend-service-on-aws-a-journey-of-learning-and-problem-solving-2n93</guid>
      <description>&lt;p&gt;I have been developing backend services for about 3 years and have always deployed them on in-house servers. Deploying a backend service on AWS for the first time can be both exciting and intimidating. For me, the experience was filled with moments of triumph, a few roadblocks, and a lot of learning. In this article, I’ll walk you through my journey of deploying a backend service on AWS, including the challenges I faced and how I solved them.&lt;/p&gt;

&lt;p&gt;NB: This article is also available on &lt;a href="https://olugbohunmijoseph.medium.com/my-first-attempt-at-deploying-a-backend-service-on-aws-22b5c1f65c3c" rel="noopener noreferrer"&gt;Medium&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why Amazon Web Services (AWS)?&lt;/strong&gt;&lt;br&gt;
I am currently building both the frontend (Android) and the backend service (SpringBoot) of a product (unfortunately, I can’t give too many details about this). After researching various cloud platforms, I chose AWS for its robust ecosystem and flexibility. For my project, I decided to use the free tier of two key AWS products: &lt;a href="https://aws.amazon.com/rds" rel="noopener noreferrer"&gt;Amazon RDS&lt;/a&gt; for my PostgreSQL database and &lt;a href="https://aws.amazon.com/ec2" rel="noopener noreferrer"&gt;Amazon EC2&lt;/a&gt; for deploying the backend service.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Setting Up the Database&lt;/strong&gt;&lt;br&gt;
The first step was setting up the database using Amazon RDS. I configured the instance with PostgreSQL and ensured it was running properly. To test the database, I used &lt;a href="https://dbeaver.io/" rel="noopener noreferrer"&gt;DBeaver&lt;/a&gt;, a reliable database management tool, to connect to the RDS instance. After verifying the connection and running some test queries, I was confident that the database setup was solid. I proceeded to provide the database URL and credentials in the application properties file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Launching the EC2 Instance&lt;/strong&gt;&lt;br&gt;
Next, I focused on the service deployment. I launched an Amazon EC2 instance running on a Linux machine and configured a security group to allow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The service port for external requests.&lt;/li&gt;
&lt;li&gt;The database port for internal communication.&lt;/li&gt;
&lt;li&gt;SSH access for managing the server.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using CLI commands, I connected to the EC2 instance via SSH from my local terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;chmod 400 /path/to/key.pem
ssh -i /path/to/key.pem ec2-user@&amp;lt;EC2-public-DNS&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once inside the EC2 instance, I installed the necessary dependencies (Java in particular), copied the jar file and deployed the service:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo yum install java-17-amazon-corretto
scp -i /path/to/key.pem my-service.jar ec2-user@&amp;lt;EC2-public-DNS&amp;gt;
java -jar my-service.jar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Testing the Service&lt;/strong&gt;&lt;br&gt;
Once the service was up, I tested it using the public URL provided by AWS. Tools like &lt;a href="https://www.postman.com/" rel="noopener noreferrer"&gt;Postman&lt;/a&gt; and the Android app I developed were invaluable. I integrated the URL and verified the service’s functionality by sending and receiving data. I was thrilled to see all endpoints working perfectly, with data being stored correctly in the database.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Unexpected Roadblock and the Fix&lt;/strong&gt;&lt;br&gt;
Just when I thought I had everything figured out, an issue cropped up: the service became unreachable whenever my PC was turned off. This was puzzling because I assumed the EC2 instance would remain accessible independent of my local machine. After some troubleshooting and research, I realized that there was a problem with how I had configured the instance’s networking and persistence. By applying the correct adjustments, I ensured that the service was fully reachable regardless of my PC’s status. Here’s how I resolved it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensured the EC2 instance was running:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws ec2 describe-instances --instance-ids &amp;lt;instance-id&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Made the service persistent by creating a systemd service file:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo nano /etc/systemd/system/my-service.service #This opens a text editor to create the file
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Added the following content to the file:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[Unit]
Description=My Java Application
After=network.target

[Service]
ExecStart=/usr/bin/java -jar /path/to/my-service.jar
WorkingDirectory=/path/to/my-service-directory
StandardOutput=inherit
StandardError=inherit
Restart=always
User=ec2-user  # Change this to the user running the app if different

[Install]
WantedBy=multi-user.target
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Saved the file and exited the editor (&lt;code&gt;Ctrl+O&lt;/code&gt;, &lt;code&gt;Enter&lt;/code&gt;, then &lt;code&gt;Ctrl+X&lt;/code&gt; in Nano).&lt;/li&gt;
&lt;li&gt;Reloaded the systemd daemon to recognize the new service, start the Java application service and enable it to start automatically when the EC2 instance boots:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo systemctl daemon-reload
sudo systemctl start my-service.service
sudo systemctl enable my-service.service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Checked the service status:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo systemctl status my-service.service # An "active (running)" status indicates that the application is running successfully
sudo journalctl -u my-service.service # Checking the logs for troubleshooting
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;After those changes, I confirmed the service’s availability by using the Android App when my PC was turned off, and it worked as expected!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Lesson learned&lt;/strong&gt;&lt;br&gt;
Deploying a backend service on AWS for the first time taught me a lot, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The importance of testing every component individually before integrating them.&lt;/li&gt;
&lt;li&gt;Understanding AWS’s networking configurations and security group settings to allow only necessary traffic.&lt;/li&gt;
&lt;li&gt;Ensure critical services restart automatically and don’t rely on a local machine for accessibility.&lt;/li&gt;
&lt;li&gt;Staying calm and persistent when troubleshooting issues.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;br&gt;
AWS is a powerful platform for deploying backend services, but like any tool, it has a learning curve. My journey from setting up RDS and EC2 to solving accessibility issues was challenging but was a fulfilling experience that combined technical skills with problem-solving. It also enhanced my understanding of cloud architecture. If you’re just starting with AWS, don’t be afraid to make mistakes — they’re part of the learning process. &lt;a href="https://calculator.aws/#/" rel="noopener noreferrer"&gt;Here&lt;/a&gt; is an additional resource that you’d find helpful in estimating the cost of deploying your solution on AWS.&lt;/p&gt;

&lt;p&gt;Feel free to share your thoughts or experiences in the comments. I’d love to hear how others have tackled similar challenges!&lt;/p&gt;

</description>
      <category>backenddevelopment</category>
      <category>aws</category>
      <category>springboot</category>
      <category>kotlin</category>
    </item>
    <item>
      <title>In-App Authentication Made Easy With Biometric API</title>
      <dc:creator>Joseph Olugbohunmi</dc:creator>
      <pubDate>Mon, 03 Jul 2023 09:14:30 +0000</pubDate>
      <link>https://dev.to/mayorjay/in-app-authentication-made-easy-with-biometric-api-23ad</link>
      <guid>https://dev.to/mayorjay/in-app-authentication-made-easy-with-biometric-api-23ad</guid>
      <description>&lt;p&gt;In Android Apps nowadays, there are various forms of user authentication we get to implement such as login, verification, transaction approval and so on. Traditionally, we would authenticate users with emails, passwords, OTP and the like but what if we can authenticate a user with the security token they already use on their device such as fingerprints, face, iris, password, PIN, or pattern?&lt;/p&gt;

&lt;p&gt;With the release of Android 10 (API level 29), a new Biometric API was introduced to help Android developers seamlessly authenticate their users with Biometrics or device credentials (password, PIN, or pattern) already registered on the device. This feature is also backwards compatible, down to Android 6 (API level 23). Integrating this library is pretty straightforward and can be done in 4 simple steps.&lt;/p&gt;

&lt;p&gt;NB: This article is also available on &lt;a href="https://olugbohunmijoseph.medium.com/in-app-authentication-made-easy-with-biometric-api-b603b8e26324" rel="noopener noreferrer"&gt;Medium&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Now the four simple steps…&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Add the dependency&lt;/strong&gt;&lt;br&gt;
In the App's &lt;code&gt;build.gradle&lt;/code&gt; file, add the dependency to download the library's artifacts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dependencies {
    ...
    implementation "androidx.biometric:biometric:${current_version}"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At the time of writing this article, the version was &lt;code&gt;1.1.0&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Check if the device can perform Biometric Authentication&lt;/strong&gt;&lt;br&gt;
Do this check in &lt;code&gt;onCreate()&lt;/code&gt; of your Activity or &lt;code&gt;onViewCreated()&lt;/code&gt; of your Fragment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;private fun canAuthenticate(): Boolean {
    val biometricManager = BiometricManager.from(requireContext())
    return biometricManager.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_WEAK) == BiometricManager.BIOMETRIC_SUCCESS
}

if (canAuthenticate()) {
  // initializeBiometricAuth()
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before now, we could just use &lt;code&gt;biometricManager.canAuthenticate()&lt;/code&gt; but that has been deprecated for the one mentioned above where we have to pass in a type of Authenticator.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Instantiate BiometricPrompt and build PromptInfo&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;private fun initializeBiometricAuth() {
        val executor: Executor = ContextCompat.getMainExecutor(context)

        val authCallback = object : BiometricPrompt.AuthenticationCallback() {

            override fun onAuthenticationSucceeded(result: BiometricPrompt.AuthenticationResult) {
                super.onAuthenticationSucceeded(result)
                showToast("Success!")
                // proceed
            }

            override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
                super.onAuthenticationError(errorCode, errString)
                showToast("Error occurred: $errString")
            }

            override fun onAuthenticationFailed() {
                super.onAuthenticationFailed()
                showToast("Authentication failure")
            }
        }

        val biometricPrompt = BiometricPrompt(this, executor, authCallback)

        val promptInfo: BiometricPrompt.PromptInfo = BiometricPrompt.PromptInfo.Builder()
            .setTitle("Authentication")
            .setSubtitle("Subtitle")
            .setDescription("Short description")
            .setNegativeButtonText("Cancel")
            .setConfirmationRequired(true)
            .setAllowedAuthenticators(BiometricManager.Authenticators.DEVICE_CREDENTIAL)
            .build()
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;BiometricPrompt can be  constructed using 3 parameters; the context, an Executor and the AuthenticationCallback. &lt;code&gt;AuthenticationCallback&lt;/code&gt; is an abstract class that has 3 methods; &lt;code&gt;onAuthenticationError()&lt;/code&gt; - called when an error occurs, &lt;code&gt;onAuthenticationSucceeded()&lt;/code&gt; - called when authentication is successful and &lt;code&gt;onAuthenticationFailed()&lt;/code&gt; - called when authentication failed. Any of these methods can be implemented based on your requirements, but of course, &lt;code&gt;onAuthenticationSucceeded()&lt;/code&gt; is very important.&lt;/p&gt;

&lt;p&gt;While building BiometricPrompt.PromptInfo, you can provide any relevant information such as title, subtitle, description, and so on. Before now, we could just call &lt;code&gt;setDeviceCredentialAllowed(true)&lt;/code&gt; but that has been deprecated for &lt;code&gt;setAllowedAuthenticators()&lt;/code&gt; mentioned above. This method makes it possible to authenticate using a password, PIN, or pattern. &lt;strong&gt;Please note that when &lt;code&gt;setAllowedAuthenticators(DEVICE_CREDENTIAL)&lt;/code&gt; is called, you cannot also call &lt;code&gt;setNegativeButtonText()&lt;/code&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4: Authenticate the User&lt;/strong&gt;&lt;br&gt;
Finally, you can call the authenticate method, passing in the PromptInfo object to authenticate the user.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;biometricPrompt.authenticate(promptInfo)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will display a Dialog with the provided information, now you can seamlessly authenticate a user in your App.&lt;/p&gt;

&lt;p&gt;The Biometric API can also be used to perform other cryptographic operations. For advanced topics relating to the Biometric API, you can have a look at the &lt;a href="https://developer.android.com/jetpack/androidx/releases/biometric" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Thanks for reading! If you have any observations, kindly share your thoughts in the comment section. You can also reach out to me via &lt;a href="https://twitter.com/mayorjay1" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; or &lt;a href="https://www.linkedin.com/in/joseph-olugbohunmi/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>android</category>
      <category>authentication</category>
      <category>security</category>
      <category>mobile</category>
    </item>
    <item>
      <title>Implementing Splash Screens the Recommended Way</title>
      <dc:creator>Joseph Olugbohunmi</dc:creator>
      <pubDate>Sat, 19 Nov 2022 12:04:04 +0000</pubDate>
      <link>https://dev.to/mayorjay/implementing-splash-screens-the-recommended-way-3873</link>
      <guid>https://dev.to/mayorjay/implementing-splash-screens-the-recommended-way-3873</guid>
      <description>&lt;h2&gt;
  
  
  &lt;em&gt;Do this in four steps only&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;With the release of Android 12 (API 31), a new SplashScreen API was introduced to ensure there is a standard in how Android Apps are launched. This means that using the traditional Splash screen approach will result in unexpected behaviours if your App is installed on Android 12 devices (or higher). But not to worry, implementing a Splash screen using this new API can be done in 4 simple steps. Worthy of note, is the fact that this API is backwards compatible which means it can as well be implemented on Android 11 and lower. You can easily migrate your existing Splash screen implementation to conform to the new recommended way (we will dive into that much later).&lt;/p&gt;

&lt;p&gt;NB: This article is also available on &lt;a href="https://olugbohunmijoseph.medium.com/implementing-splash-screens-the-recommended-way-5a866ae4d114" rel="noopener noreferrer"&gt;Medium&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Now the four simple steps…&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Add the dependency&lt;/strong&gt;&lt;br&gt;
In the App's &lt;code&gt;build.gradle&lt;/code&gt; file, add the dependency to download the library's artefacts&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dependencies {
    ...
    implementation "androidx.core:core-splashscreen:${current_version}"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At the time of writing this article, the version was &lt;code&gt;1.0.0&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Create the theme&lt;/strong&gt;&lt;br&gt;
In the &lt;code&gt;styles.xml&lt;/code&gt; file, create a new theme (any name is fine) and set its parent to &lt;code&gt;Theme.SplashScreen&lt;/code&gt; or &lt;code&gt;Theme.SplashScreen.IconBackground&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;style name="SplashScreenTheme" parent="Theme.SplashScreen"&amp;gt;
    &amp;lt;item name="windowSplashScreenBackground"&amp;gt;@color/colorWhite&amp;lt;/item&amp;gt;
    &amp;lt;item name="windowSplashScreenAnimatedIcon"&amp;gt;@drawable/ic_launcher&amp;lt;/item&amp;gt;
    &amp;lt;item name="postSplashScreenTheme"&amp;gt;@style/AppTheme&amp;lt;/item&amp;gt;
&amp;lt;/style&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;windowSplashScreenBackground&lt;/code&gt; specifies the window background&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;windowSplashScreenAnimatedIcon&lt;/code&gt; specifies the image you want to see on the screen. In Android 11 and below, the image specified here is not animated but in Android 12 and above it comes with a nice animation and so you could use an optional attribute &lt;code&gt;windowSplashScreenAnimationDuration&lt;/code&gt; with a recommended value of 1000 to specify the duration of the animation.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;postSplashScreenTheme&lt;/code&gt; specifies the theme the App is expected to use after the expiration of the Splash action (usually the AppTheme)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Add the theme to the Manifest&lt;/strong&gt;&lt;br&gt;
In the &lt;code&gt;AndroidManifest.xml&lt;/code&gt; file, set the theme to the Application as a whole or just the MainActivity (or your starting activity).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;application
    android:name=".MyApplication"
    android:theme="@style/SplashScreenTheme"&amp;gt; 

                OR

&amp;lt;activity 
    android:name=".MainActivity"
    android:theme="@style/SplashScreenTheme"&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 4: Install the Splash screen&lt;/strong&gt;&lt;br&gt;
In the MainActivity.kt file, call the extension function to install the Splash Screen, just before the call to &lt;code&gt;super.onCreate(savedInstanceState)&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;override fun onCreate(savedInstanceState: Bundle?) {
    installSplashScreen()
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's it, launch the App and you should have a cool splash screen after which you should have a smooth transition into your App. The good part as I said earlier is that you can follow these same steps for any Android API level at all&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;What if your App already has a Splash Screen?&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;&lt;strong&gt;Well, there is a solution…&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frvbrlh1w5t2fby9wkg24.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frvbrlh1w5t2fby9wkg24.png" alt="Splash Screen Lint Warning" width="800" height="99"&gt;&lt;/a&gt;&lt;br&gt;
I am sure you must have seen this already in your existing Splash Screen Implementation. You may decide to suppress it &lt;code&gt;@SuppressLint("CustomSplashScreen")&lt;/code&gt; and move on, but if your App is installed on Android 12 devices, the behaviour would be awful. But not to worry, it is very easy to migrate to the new API, it is as easy as the four steps we discussed earlier. Just follow those steps and there you go!&lt;br&gt;
In addition to that, if you have a delay mechanism in your Splash Screen - maybe you are pulling some data from remote or local storage, you have to call the &lt;code&gt;setKeepOnScreenCondition&lt;/code&gt; function on the SplashScreen object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;override fun onCreate(savedInstanceState: Bundle?) {
    val splashScreen = installSplashScreen()
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_splash)
    splashScreen.setKeepOnScreenCondition { true }
    startJob()
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This helps keep the Splash Screen open until the App is ready to launch the next screen and it also ensures you have a smooth transition into your App.&lt;/p&gt;

&lt;p&gt;For advanced topics relating to the SplashScreen API, you can have a look at the &lt;a href="https://developer.android.com/develop/ui/views/launch/splash-screen" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Thanks for reading! If you have any observations, kindly share your thoughts in the comment section. You can also reach out to me via &lt;a href="https://twitter.com/mayorjay1" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; or &lt;a href="https://www.linkedin.com/in/joseph-olugbohunmi" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>android</category>
      <category>splashscreen</category>
      <category>kotlin</category>
      <category>programming</category>
    </item>
    <item>
      <title>Not a Regular Password Regex</title>
      <dc:creator>Joseph Olugbohunmi</dc:creator>
      <pubDate>Sun, 30 Jan 2022 02:06:24 +0000</pubDate>
      <link>https://dev.to/mayorjay/not-a-regular-password-regex-4gjj</link>
      <guid>https://dev.to/mayorjay/not-a-regular-password-regex-4gjj</guid>
      <description>&lt;p&gt;&lt;em&gt;The password must contain at least 3 of these: a lower-case letter, an upper-case letter, a number, a special character (such as @$!%*#?&amp;amp;) and cannot be less than 8 characters in length.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That is the goal…&lt;/p&gt;

&lt;p&gt;There are several regular expression patterns used for password validation based on different requirements but what if you have a password policy that is a little bit lenient and at the same time does not compromise on the security and strength of the password. There is a particular regex pattern that can achieve this &lt;em&gt;(NB: I am not in any way saying this is the best password policy).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Let us have a look at the regex;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;String regex = "^(((?=.*[a-z])(?=.*[A-Z])(?=.*\\d))|((?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*#?&amp;amp;]))|((?=.*[a-z])(?=.*[A-Z])(?=.*[@$!%*#?&amp;amp;]))|((?=.*[a-z])(?=.*\\d)(?=.*[@$!%*#?&amp;amp;])))(?=\\S+$).{8,}$";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now let us see this regex in use;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class PasswordValidationTest {

    private Pattern pattern;

    @Before
    public void setUp() {
        String regex = "^(((?=.*[a-z])(?=.*[A-Z])(?=.*\\d))|((?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*#?&amp;amp;]))|((?=.*[a-z])(?=.*[A-Z])(?=.*[@$!%*#?&amp;amp;]))|((?=.*[a-z])(?=.*\\d)(?=.*[@$!%*#?&amp;amp;])))(?=\\S+$).{8,}$";
        pattern = Pattern.compile(regex);
    }

    @Test
    public void test_first_valid_password_example() {
        //Number, upper case, lower case in no particular order
        String password = "13Edlpouhgfdcfvgbqb";
        Assert.assertTrue(matchPassword(password));
    }

    @Test
    public void test_second_valid_password_example() {
        //Lower case, number, special character in no particular order
        String password = "dfgjrwerdvfbghjhgfdxc90@";
        Assert.assertTrue(matchPassword(password));
    }

    @Test
    public void test_third_valid_password_example() {
        //Upper case, number, lower case in no particular order
        String password = "POIIUHGFBGNHUYF2df";
        Assert.assertTrue(matchPassword(password));
    }

    @Test
    public void test_fourth_valid_password_example() {
        //Upper case, lower case, number, special character in no particular order
        String password = "KJSrtyhgh!58E543561#";
        Assert.assertTrue(matchPassword(password));
    }

    @Test
    public void test_invalid_password_example() {
        String password = "TGsayhtgfdcsxrbfdvc";
        Assert.assertFalse(matchPassword(password));
    }

    //Utility function
    private boolean matchPassword(String password) {
        Matcher matcher = pattern.matcher(password);
        return matcher.matches();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As seen in the code snippet above, this regex does not make any of the conditions mandatory but the user cannot submit a password that does not satisfy at least three of these conditions, and of course, the password cannot be less than 8 characters long. The fourth test case shows that the regex can allow a password that has all four combinations, while the last test case is that of an invalid password.&lt;/p&gt;

&lt;p&gt;Now let us see the result of the tests above;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmf5m3o0ev7bqbicn6qhu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmf5m3o0ev7bqbicn6qhu.png" alt="Image description" width="800" height="308"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All tests passed, now some explanation;&lt;br&gt;
&lt;code&gt;^&lt;/code&gt; Assert position at the start of the line&lt;br&gt;
&lt;code&gt;(?=.*[a-z])&lt;/code&gt; Ensure a lower case letter must occur at least once&lt;br&gt;
&lt;code&gt;(?=.*[A-Z])&lt;/code&gt; Ensure an upper case letter must occur at least once&lt;br&gt;
&lt;code&gt;(?=.*\\d)&lt;/code&gt; Ensure a digit must occur at least once&lt;br&gt;
&lt;code&gt;(?=.*[@$!%*#?&amp;amp;])&lt;/code&gt; Ensure a special character must occur at least once&lt;br&gt;
&lt;code&gt;(?=\S+$)&lt;/code&gt; Ensure no white space is allowed in the entire string&lt;br&gt;
&lt;code&gt;.{8,}&lt;/code&gt; Ensure at least eight characters&lt;br&gt;
&lt;code&gt;$&lt;/code&gt; Assert position at the end of the line&lt;br&gt;
Also, notice that there are 4 groups of combination in the regex separated by the &lt;strong&gt;Alternative sign&lt;/strong&gt; (|), equivalent to OR condition. That does the conditional enforcement. I hope this is helpful to someone out there.&lt;/p&gt;

&lt;p&gt;Thanks for reading! If you have any observation, kindly share your thoughts in the comment section. You can also reach out to me via &lt;a href="https://twitter.com/mayorjay1" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; or &lt;a href="https://www.linkedin.com/in/joseph-olugbohunmi/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>regex</category>
      <category>java</category>
      <category>security</category>
    </item>
  </channel>
</rss>
