Android FIDO PIN Authenticator
HYPR SDK for Android: Android Authenticators
This document provides a description of and integration guidelines for HYPR Android PIN Authenticator interface.
Description | Value |
---|---|
Standard PIN AAID (Authenticator ID) | 0045#0001 |
Library Name | HyprPin-<version>.aar |
PIN DROP
The PIN Authenticator's PIN is not the same as the PIN on your lock screen.
PIN Attributes
Description | Value |
---|---|
PIN Length | 6 |
Number of Attempts for Authentication | 3 |
Integration
Do This First
Before any HYPR authenticator is added to a project, be sure to follow the HYPR SDK for Android Quick Start setup and integration.
The HYPR PIN Authenticator specifically requires the following app/commonlibraries/build.gradle
file additions:
dependencies {
...
// HYPR Common Dependency
api(name: 'HyprCommon', version: "${hyprVersion}", ext: 'aar')
// HYPR Crypto
api(name: "crypto", version: "${cryptoVersion}", ext: 'aar') { transitive = true }
// HYPR PIN Authenticator Dependency
api(name: 'HyprPin', version: "${hyprVersion}", ext: 'aar')
...
}
User Interface
Identical PINs
You will be unable to enroll if there is a mismatch between the PIN and confirmation PIN as seen in the picture below.
The following default authentication confirmation screen displays when a user authenticates.

To enable/disable the confirmation screen for authentication and/or transactions, locate overrides.xml
in app/<module_name>/src/main/res/values
and append it with the following content:
<string name="hypr_pin_show_auth_conf_override">true</string>
<string name="hypr_pin_show_trans_conf_override">true</string>
UI Customization
We can customize the PIN Authenticator screens via XML overrides. Each screen has a corresponding XML layout file. By creating a layout file with the same name as the one you want to override, the SDK will present that layout file instead.
ID Check
If you are overriding the layout files, please make sure to keep all the
android:ids
with their respective view from the layout that you want to override as the SDK uses those IDs.
Overriding the PIN Enrollment Screen
Create a file called hypr_fragment_pin_double_enroll.xml
in app/<module_name>/src/main/res/layout
and you can now alter/add views and change the properties of those views.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:background="@drawable/hypr_common_auth_primary_background"
tools:context=".ui.activities.HyprPinActivity"
tools:ignore="Overdraw">
<include layout="@layout/hypr_view_pin_overlay_title" />
<RelativeLayout
android:id="@+id/hypr_pin_layout_movable_parent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true">
<LinearLayout
android:id="@+id/hypr_pin_layout_pin_one"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/hypr_pin_layout_pin_entry_text_one"
android:layout_gravity="center_horizontal"
android:gravity="center_horizontal"
android:orientation="horizontal">
<com.hypr.hyprandroidcommon.uiadapter.ui.views.HyprStatefullEditText
android:id="@+id/hypr_pin_editview_pin_one_first"
style="@style/PinEditTextStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/hyprColorPinFocusedLine" />
<com.hypr.hyprandroidcommon.uiadapter.ui.views.HyprStatefullEditText
android:id="@+id/hypr_pin_editview_pin_one_second"
style="@style/PinEditTextStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/hyprColorPinFocusedLine" />
<com.hypr.hyprandroidcommon.uiadapter.ui.views.HyprStatefullEditText
android:id="@+id/hypr_pin_editview_pin_one_third"
style="@style/PinEditTextStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/hyprColorPinFocusedLine" />
<com.hypr.hyprandroidcommon.uiadapter.ui.views.HyprStatefullEditText
android:id="@+id/hypr_pin_editview_pin_one_fourth"
style="@style/PinEditTextStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/hyprColorPinFocusedLine" />
<com.hypr.hyprandroidcommon.uiadapter.ui.views.HyprStatefullEditText
android:id="@+id/hypr_pin_editview_pin_one_fifth"
style="@style/PinEditTextStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/hyprColorPinFocusedLine" />
<com.hypr.hyprandroidcommon.uiadapter.ui.views.HyprStatefullEditText
android:id="@+id/hypr_pin_editview_pin_one_sixth"
style="@style/PinEditTextStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/hyprColorPinFocusedLine" />
</LinearLayout>
<LinearLayout
android:id="@+id/hypr_pin_layout_pin_entry_text_one"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/hypr_pin_layout_pin_two"
android:layout_marginBottom="@dimen/hypr_pin_double_bottom_margin"
android:layout_marginTop="@dimen/hypr_pin_double_top_margin"
android:gravity="center_horizontal"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/sharetech_regular"
android:gravity="center_horizontal"
android:text="@string/hypr_pin_entry_text"
android:textColor="@color/hyprColorTextPrimary"
android:textSize="@dimen/hypr_pin_entry_hint_size" />
</LinearLayout>
<LinearLayout
android:id="@+id/hypr_pin_layout_pin_two"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/hypr_pin_layout_wrong_pin"
android:layout_gravity="center_horizontal"
android:gravity="center_horizontal"
android:orientation="horizontal">
<com.hypr.hyprandroidcommon.uiadapter.ui.views.HyprStatefullEditText
android:id="@+id/hypr_pin_editview_pin_two_first"
style="@style/PinEditTextStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/hyprColorPinFocusedLine" />
<com.hypr.hyprandroidcommon.uiadapter.ui.views.HyprStatefullEditText
android:id="@+id/hypr_pin_editview_pin_two_second"
style="@style/PinEditTextStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/hyprColorPinFocusedLine" />
<com.hypr.hyprandroidcommon.uiadapter.ui.views.HyprStatefullEditText
android:id="@+id/hypr_pin_editview_pin_two_third"
style="@style/PinEditTextStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/hyprColorPinFocusedLine" />
<com.hypr.hyprandroidcommon.uiadapter.ui.views.HyprStatefullEditText
android:id="@+id/hypr_pin_editview_pin_two_fourth"
style="@style/PinEditTextStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/hyprColorPinFocusedLine" />
<com.hypr.hyprandroidcommon.uiadapter.ui.views.HyprStatefullEditText
android:id="@+id/hypr_pin_editview_pin_two_fifth"
style="@style/PinEditTextStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/hyprColorPinFocusedLine" />
<com.hypr.hyprandroidcommon.uiadapter.ui.views.HyprStatefullEditText
android:id="@+id/hypr_pin_editview_pin_two_sixth"
style="@style/PinEditTextStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/hyprColorPinFocusedLine" />
</LinearLayout>
<LinearLayout
android:id="@+id/hypr_pin_layout_wrong_pin"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/hypr_pin_layout_pin_entry_text_two"
android:layout_gravity="center_horizontal"
android:layout_marginTop="@dimen/hypr_pin_double_top_margin"
android:gravity="center_horizontal"
android:orientation="horizontal"
android:visibility="gone"
tools:ignore="UseCompoundDrawables">
<ImageView
android:layout_width="@dimen/hypr_pin_wrong_icon_size"
android:layout_height="@dimen/hypr_pin_wrong_icon_size"
android:layout_gravity="center_vertical"
android:layout_marginEnd="@dimen/hypr_pin_wrong_icon_margin_end"
android:contentDescription="@string/hypr_todo_content_description"
android:src="@drawable/hypr_pin_warning_icon" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:fontFamily="@font/sharetech_regular"
android:text="@string/hypr_error_display_pin_mismatch"
android:textColor="@color/hyprColorRedFail"
android:textSize="@dimen/hypr_pin_entry_hint_size" />
</LinearLayout>
<LinearLayout
android:id="@+id/hypr_pin_layout_pin_entry_text_two"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/hypr_pin_view_pin_entry_text_buffer"
android:layout_marginBottom="@dimen/hypr_pin_double_bottom_margin"
android:gravity="center_horizontal"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="@string/hypr_pin_confirm_text"
android:textColor="@color/hyprColorTextPrimary"
android:textSize="@dimen/hypr_pin_entry_hint_size" />
</LinearLayout>
<View
android:id="@+id/hypr_pin_view_pin_entry_text_buffer"
android:layout_width="match_parent"
android:layout_height="@dimen/hypr_pin_buffer_view_height"
android:layout_above="@+id/hypr_pin_view_button_layout"
android:visibility="visible" />
<RelativeLayout
android:id="@+id/hypr_pin_view_button_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/hypr_pin_view_bottom_anchor_2">
<include
layout="@layout/hypr_common_view_ok_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/hypr_common_selection_button_margin_bottom" />
<include
android:id="@+id/hypr_pin_layout_button_cancel"
layout="@layout/hypr_common_view_cancel_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/hypr_common_selection_button_margin_bottom" />
</RelativeLayout>
<View
android:id="@+id/hypr_pin_view_bottom_anchor_2"
android:layout_width="match_parent"
android:layout_height="@dimen/hypr_common_keyboard_divider_bar_height"
android:layout_alignParentBottom="true"
android:background="@color/hyprColorKeyboardAnchorView"
android:visibility="invisible" />
</RelativeLayout>
<include layout="@layout/hypr_common_view_keyboard_layout" />
</RelativeLayout>

PIN Enrollment UI Override
Overriding the Authentication Screen
In the same location, create a file called hypr_fragment_pin_single_verify.xml
to alter/add views and change the properties of those views.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:background="@drawable/hypr_common_auth_primary_background"
tools:context=".ui.activities.HyprPinActivity"
tools:ignore="Overdraw">
<include layout="@layout/hypr_view_pin_overlay_title" />
<RelativeLayout
android:id="@+id/hypr_layout_transaction"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone">
<TextView
android:id="@+id/hypr_text_transaction_amount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:gravity="center_horizontal"
android:textColor="@color/hyprColorGeneralInfoDesc"
android:textSize="@dimen/hypr_common_general_rectangle_desc_text_size"
android:visibility="gone" />
<TextView
android:id="@+id/hypr_text_transaction_type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/hypr_text_transaction_amount"
android:layout_centerHorizontal="true"
android:gravity="center_horizontal"
android:textColor="@color/hyprColorGeneralInfoDesc"
android:textSize="@dimen/hypr_common_general_rectangle_desc_text_size"
android:visibility="gone" />
<TextView
android:id="@+id/hypr_text_transaction_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/hypr_text_transaction_type"
android:layout_centerHorizontal="true"
android:gravity="center_horizontal"
android:textColor="@color/hyprColorGeneralInfoDesc"
android:textSize="@dimen/hypr_common_general_rectangle_desc_text_size"
android:visibility="gone" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/hypr_pin_layout_movable_parent"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/hypr_pin_layout_pin_one"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/hypr_pin_layout_pin_entry_layout"
android:layout_gravity="center_horizontal"
android:gravity="center_horizontal"
android:orientation="horizontal">
<com.hypr.hyprandroidcommon.uiadapter.ui.views.HyprStatefullEditText
android:id="@+id/hypr_pin_editview_pin_one_first"
style="@style/PinEditTextStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/hyprColorPinFocusedLine" />
<com.hypr.hyprandroidcommon.uiadapter.ui.views.HyprStatefullEditText
android:id="@+id/hypr_pin_editview_pin_one_second"
style="@style/PinEditTextStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/hyprColorPinFocusedLine" />
<com.hypr.hyprandroidcommon.uiadapter.ui.views.HyprStatefullEditText
android:id="@+id/hypr_pin_editview_pin_one_third"
style="@style/PinEditTextStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/hyprColorPinFocusedLine" />
<com.hypr.hyprandroidcommon.uiadapter.ui.views.HyprStatefullEditText
android:id="@+id/hypr_pin_editview_pin_one_fourth"
style="@style/PinEditTextStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/hyprColorPinFocusedLine" />
<com.hypr.hyprandroidcommon.uiadapter.ui.views.HyprStatefullEditText
android:id="@+id/hypr_pin_editview_pin_one_fifth"
style="@style/PinEditTextStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/hyprColorPinFocusedLine" />
<com.hypr.hyprandroidcommon.uiadapter.ui.views.HyprStatefullEditText
android:id="@+id/hypr_pin_editview_pin_one_sixth"
style="@style/PinEditTextStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/hyprColorPinFocusedLine" />
</LinearLayout>
<LinearLayout
android:id="@+id/hypr_pin_layout_pin_entry_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/hypr_pin_layout_button_cancel"
android:layout_marginBottom="@dimen/hypr_pin_text_margin_bottom"
android:layout_marginTop="@dimen/hypr_pin_text_margin_top"
android:gravity="center_horizontal"
android:orientation="vertical">
<TextView
android:id="@+id/hypr_pin_layout_pin_entry_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:text="@string/hypr_pin_entry_text"
android:textColor="@color/hyprColorTextPrimary"
android:textSize="@dimen/hypr_pin_entry_hint_size" />
</LinearLayout>
<include
android:id="@+id/hypr_pin_layout_button_cancel"
layout="@layout/hypr_common_view_cancel_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/hypr_pin_view_pin_entry_text_buffer"
android:layout_marginBottom="@dimen/hypr_pin_cancel_margin_bottom" />
<View
android:id="@+id/hypr_pin_view_pin_entry_text_buffer"
android:layout_width="match_parent"
android:layout_height="@dimen/hypr_pin_buffer_view_height"
android:layout_above="@+id/hypr_pin_view_bottom_anchor"
android:visibility="visible" />
<View
android:id="@+id/hypr_pin_view_bottom_anchor"
android:layout_width="match_parent"
android:layout_height="@dimen/hypr_common_keyboard_divider_bar_height"
android:layout_alignParentBottom="true"
android:background="@color/hyprColorKeyboardAnchorView"
android:visibility="invisible" />
</RelativeLayout>
<include layout="@layout/hypr_common_view_keyboard_layout" />
</RelativeLayout>
PIN Authentication UI override:

PIN Authenticator Configuration
Configurable values in the PIN Authenticator include the following:
- The number of attempts the user has to enter the correct PIN
- The time in milliseconds before the keyboard is automatically opened
To configure these values, create integers.xml
in the app/<module_name>/src/main/res/values
directory with the desired values:
<?xml version="1.0" encoding="utf-8"?>
<resources>
// Amount of authentication attempts allowed before authentication fails
// Default value is 3, minimum value is 1.
<integer name="hypr_pin_authentication_retry_limit">3</integer>
// Amount of time in milliseconds before keyboard is automatically opened
// If set to -1, keyboard is not automatically opened
<integer name="hypr_pin_keyboard_auto_open_delay_ms">250</integer>
</resources>
Integrating Additional Functionality
Additional functionality may also be added to the PIN enrollment and authentication fragments outside of UI customization.
Customizing the PIN Enrollment Fragment
Here is an example of the HyprPinDoubleEnrollFragment
subclass:
package your.package.path;
public class CustomPinEnrollFragment extends HyprPinDoubleEnrollFragment {
@Override
public void onViewCreated(@NonNull View view,
@Nullable Bundle bundle) {
super.onViewCreated(view, bundle);
// If you want, find the views and attach listeners to them
}
@Override
public int getPinSize() {
// Modify the PIN length
}
@Override
public int getFragmentLayout() {
// Return the layout file you want to use
// By default, the layout file here would be: R.layout.hypr_fragment_pin_double_enroll
}
}
ID Check
If you are overriding
getFrameLayout()
to display a different layout file, please make sure to keep all theandroid:ids
from the layout that you are replacing as the SDK uses those IDs.
To use your own HyprPinDoubleEnrollFragment
subclass, make sure it it is included in overrides.xml
within the app/<module_name>/src/main/res/values
directory. Provide the package path to your HyprPinDoubleEnrollFragment
subclass along with the subclass name as the string value in overrides.xml
.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hypr_pin_double_enroll_fragment_class_override">your.package.path.CustomPinEnrollFragment</string>
</resources>
Customizing the PIN Authentication Screen
Following is an example of the HyprPinSingleVerifyFragment
subclass:
package your.package.path;
public class CustomPinVerificationFragment extends HyprPinSingleVerifyFragment {
@Override
public void onViewCreated(@NonNull View view,
@Nullable Bundle bundle) {
super.onViewCreated(view, bundle);
// If you want, find the views and attach listeners to them
}
@Override
public int getPinSize() {
// Modify the PIN length
}
@Override
public int getFragmentLayout() {
// Return the layout file you want to use
// By default, the layout file here would be: R.layout.hypr_fragment_pin_single_verify
}
}
ID Check
If you are overriding
getFrameLayout()
to display a different layout file, please make sure to keep all theandroid:ids
from the layout that you are replacing as the SDK uses those IDs.
To use your own HyprPinSingleVerifyFragment
subclass, make sure it it is included in overrides.xml
within the app/<module_name>/src/main/res/values/
directory. Provide the package path to your HyprPinSingleVerifyFragment
subclass along with the subclass name as the string value in overrides.xml
.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="hypr_pin_single_verify_fragment_class_override">your.package.path.CustomPinVerificationFragment</string>
</resources>
Updated 8 months ago