Hi all today we are going to work on one more app security topic apart from FingerPrint Authentication. In many of apps you have seen the app is opening a screen where it ask you to enter the PIN or draw a Pattern which is by default security you have set to your device. Some the apps are Tez, Paytm, etc.
NOTE : The Security Lock authentication only works for API Level 21+ (Lollipop+).
So today we are going to do the same and we will see how we can also implement the same kind of authentication which other apps are doing. The steps to implement the Security Level Authentication are following:
1. You will be needing a KeyguardManager to implement this authentication:
1 |
KeyguardManager keyguardManager = (KeyguardManager) getSystemService(KEYGUARD_SERVICE); |
2. Create an Intent like below:
1 |
Intent i = keyguardManager.createConfirmDeviceCredentialIntent(title, description); |
After creating Intent start the intent with startActivityForResult() to check if the authentication is successful or not.
1 2 3 4 5 6 7 |
try { //Start activity for result startActivityForResult(i, LOCK_REQUEST_CODE); } catch (Exception e) { //If some exception occurs means Screen lock is not set up please set screen lock } |
It will open the screen requesting user to enter the PIN or draw a Pattern which he has set for particular device.
3. Some of the devices have not enabled Security Lock for their device. So for those devices you will get exception and in that case you need to open the Security Settings of the device with an intent:
1 2 3 4 5 6 7 8 9 10 11 |
//Open Security screen directly to enable patter lock Intent intent = new Intent(Settings.ACTION_SECURITY_SETTINGS); try { //Start activity for result startActivityForResult(intent, SECURITY_SETTING_REQUEST_CODE); } catch (Exception ex) { //If app is unable to find any Security settings then user has to set screen lock manually textView.setText(getResources().getString(R.string.setting_label)); } |
4. Alternate way to check if the device is Security Lock enabled or not is given below :
1 2 3 4 5 6 7 8 9 |
private boolean isDeviceSecure() { KeyguardManager keyguardManager = (KeyguardManager) getSystemService(KEYGUARD_SERVICE); //this method only work whose api level is greater than or equal to Jelly_Bean (16) return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && keyguardManager.isKeyguardSecure(); //You can also use keyguardManager.isDeviceSecure(); but it requires API Level 23 } |
The above method only works for API Level 16+ (Jelly Bean+).
1. Create a new project in Android Studio by navigating to File ⇒ New Android ⇒ Application Project and fill required details. By default my activity is MainActivity.java.
2. Open res ⇒ values ⇒ strings.xml and add below string values. These are some strings that we are going to use in our project.
1 2 3 4 5 6 7 8 9 10 11 |
<resources> <string name="app_name">Security Lock Demo</string> <string name="unlock">Unlock</string> <string name="confirm_pattern">Confirm your screen lock PIN,Pattern or Password</string> <string name="setting_label"><![CDATA[Please set the screen lock Manually by navigating to : Settings>Security.]]></string> <string name="unlock_success">App is Unlocked successfully.</string> <string name="unlock_failed">Failed to Unlock the app.</string> <string name="device_is_secure">Device is now secure.</string> <string name="security_device_cancelled">Device is not secure or user cancel the request.</string> <string name="authenticate_again">Authenticate Again</string> </resources> |
3. Now go to activity_main.xml and add the below code to it.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" android:orientation="vertical" android:padding="10dp" tools:context="com.security_lock_demo.MainActivity"> <TextView android:id="@+id/texview" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:padding="10dp" android:textColor="@android:color/black" android:textSize="18sp" /> <Button android:layout_width="match_parent" android:layout_marginTop="15dp" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:background="@color/colorPrimary" android:onClick="authenticateAgain" android:text="@string/authenticate_again" android:textColor="@android:color/white" android:textSize="15sp" /> </LinearLayout> |
4. After adding the activity_main.xml layout come to MainActivity.java and put the below code to it. This code contains all step by step information which we discussed above.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
package com.security_lock_demo; import android.app.KeyguardManager; import android.content.Intent; import android.os.Build; import android.provider.Settings; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends AppCompatActivity { private static final int LOCK_REQUEST_CODE = 221; private static final int SECURITY_SETTING_REQUEST_CODE = 233; private TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView = (TextView) findViewById(R.id.texview); authenticateApp(); } //method to authenticate app private void authenticateApp() { //Get the instance of KeyGuardManager KeyguardManager keyguardManager = (KeyguardManager) getSystemService(KEYGUARD_SERVICE); //Check if the device version is greater than or equal to Lollipop(21) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { //Create an intent to open device screen lock screen to authenticate //Pass the Screen Lock screen Title and Description Intent i = keyguardManager.createConfirmDeviceCredentialIntent(getResources().getString(R.string.unlock), getResources().getString(R.string.confirm_pattern)); try { //Start activity for result startActivityForResult(i, LOCK_REQUEST_CODE); } catch (Exception e) { //If some exception occurs means Screen lock is not set up please set screen lock //Open Security screen directly to enable patter lock Intent intent = new Intent(Settings.ACTION_SECURITY_SETTINGS); try { //Start activity for result startActivityForResult(intent, SECURITY_SETTING_REQUEST_CODE); } catch (Exception ex) { //If app is unable to find any Security settings then user has to set screen lock manually textView.setText(getResources().getString(R.string.setting_label)); } } } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); switch (requestCode) { case LOCK_REQUEST_CODE: if (resultCode == RESULT_OK) { //If screen lock authentication is success update text textView.setText(getResources().getString(R.string.unlock_success)); } else { //If screen lock authentication is failed update text textView.setText(getResources().getString(R.string.unlock_failed)); } break; case SECURITY_SETTING_REQUEST_CODE: //When user is enabled Security settings then we don't get any kind of RESULT_OK //So we need to check whether device has enabled screen lock or not if (isDeviceSecure()) { //If screen lock enabled show toast and start intent to authenticate user Toast.makeText(this, getResources().getString(R.string.device_is_secure), Toast.LENGTH_SHORT).show(); authenticateApp(); } else { //If screen lock is not enabled just update text textView.setText(getResources().getString(R.string.security_device_cancelled)); } break; } } /** * method to return whether device has screen lock enabled or not **/ private boolean isDeviceSecure() { KeyguardManager keyguardManager = (KeyguardManager) getSystemService(KEYGUARD_SERVICE); //this method only work whose api level is greater than or equal to Jelly_Bean (16) return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && keyguardManager.isKeyguardSecure(); //You can also use keyguardManager.isDeviceSecure(); but it requires API Level 23 } //On Click of button do authentication again public void authenticateAgain(View view) { authenticateApp(); } } |
5. Finally all done, now you can also make your app secure with the help of Confirm Credential/Security Lock.
You can use the above code to authenticate the users while making Payment in your app or while accessing some critical information from app.
Thanks.
Subscribe to us and get the latest news.
4 Comments
Valentin Gonzalez
Saturday, March 17th, 2018Hi
I followed your article closely. Could you extend its value by providing a MainActivity.java that will work with API 16 and above? The article states that some code will only work above API but the MainActivity.java will clearly only work for API 21. I look forward to hearing from you.
Dr. Droid
Saturday, March 17th, 2018Hi Valentin,
If you read the article I have already written that this API only work for 21+ . For lower devices this code won’t work. For that you have to create and enable your own lock.
Thanks
vishwajeet
Thursday, March 22nd, 2018As you replied to valentin that you have to create your own lock screen activity in that case will you please create post or example as above for the same. Looking forward to help from you.
Valentin Gonzalez
Monday, May 21st, 2018Thank you for the reply.
Separate question on my example:
Every time I called the Screenlock challenge my resultCode is always -1 on valid PIN number.
Is there a reason for createConfirmDeviceCredentialIntent to always return that value? If I intentionally enter an invalid PIN the return value is zero (0).
Do you have an idea why?