diff --git a/android/src/main/java/expo/modules/localauthentication/LocalAuthenticationModule.kt b/android/src/main/java/expo/modules/localauthentication/LocalAuthenticationModule.kt
index 996ee2ec5b77386b360fed3118fd6d6d4244d3c4..4aa70a89a7fb5d01b5b700d55c9817c213322e4d 100644
--- a/android/src/main/java/expo/modules/localauthentication/LocalAuthenticationModule.kt
+++ b/android/src/main/java/expo/modules/localauthentication/LocalAuthenticationModule.kt
@@ -4,6 +4,8 @@ package expo.modules.localauthentication
 import android.app.Activity
 import android.app.KeyguardManager
 import android.content.Context
+import android.content.Intent
+import android.provider.Settings
 import android.os.Build
 import android.os.Bundle
 import androidx.annotation.UiThread
@@ -51,7 +53,7 @@ class LocalAuthenticationModule : Module() {
 
     AsyncFunction("supportedAuthenticationTypesAsync") {
       val results = mutableSetOf<Int>()
-      if (canAuthenticateUsingWeakBiometrics() == BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE) {
+      if (canAuthenticateUsingStrongBiometrics() == BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE) {
         return@AsyncFunction results
       }
 
@@ -67,12 +69,29 @@ class LocalAuthenticationModule : Module() {
       return@AsyncFunction results
     }
 
+    AsyncFunction("enrollForAuthentication") {
+      if (Build.VERSION.SDK_INT >= 30) {
+        val intent = Intent(Settings.ACTION_BIOMETRIC_ENROLL)
+        intent.putExtra(
+          Settings.EXTRA_BIOMETRIC_AUTHENTICATORS_ALLOWED,
+          BiometricManager.Authenticators.BIOMETRIC_STRONG
+        )
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+        currentActivity?.startActivity(intent)
+        return@AsyncFunction true
+      } else {
+        val intent = Intent(Settings.ACTION_FINGERPRINT_ENROLL)
+        currentActivity?.startActivity(intent)
+        return@AsyncFunction true
+      }
+    }
+
     AsyncFunction("hasHardwareAsync") {
-      canAuthenticateUsingWeakBiometrics() != BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE
+      canAuthenticateUsingStrongBiometrics() != BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE
     }
 
     AsyncFunction("isEnrolledAsync") {
-      canAuthenticateUsingWeakBiometrics() == BiometricManager.BIOMETRIC_SUCCESS
+      canAuthenticateUsingStrongBiometrics() == BiometricManager.BIOMETRIC_SUCCESS
     }
 
     AsyncFunction("getEnrolledLevelAsync") {
@@ -80,7 +99,7 @@ class LocalAuthenticationModule : Module() {
       if (isDeviceSecure) {
         level = SECURITY_LEVEL_SECRET
       }
-      if (canAuthenticateUsingWeakBiometrics() == BiometricManager.BIOMETRIC_SUCCESS) {
+      if (canAuthenticateUsingStrongBiometrics() == BiometricManager.BIOMETRIC_SUCCESS) {
         level = SECURITY_LEVEL_BIOMETRIC
       }
       return@AsyncFunction level
@@ -235,10 +254,19 @@ class LocalAuthenticationModule : Module() {
       if (disableDeviceFallback) {
         setNegativeButtonText(cancelLabel)
       } else {
-        setAllowedAuthenticators(
-          BiometricManager.Authenticators.BIOMETRIC_WEAK
-            or BiometricManager.Authenticators.DEVICE_CREDENTIAL
-        )
+        if (Build.VERSION.SDK_INT >= 30) {
+          setAllowedAuthenticators(
+            BiometricManager.Authenticators.BIOMETRIC_STRONG
+              or BiometricManager.Authenticators.DEVICE_CREDENTIAL
+          )
+        } else {
+          setAllowedAuthenticators(
+            BiometricManager.Authenticators.BIOMETRIC_STRONG
+          )
+          cancelLabel?.let {
+            setNegativeButtonText(it)
+          }
+        }
       }
       setConfirmationRequired(requireConfirmation)
     }
@@ -336,6 +364,9 @@ class LocalAuthenticationModule : Module() {
   private fun canAuthenticateUsingWeakBiometrics(): Int =
     biometricManager.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_WEAK)
 
+  private fun canAuthenticateUsingStrongBiometrics(): Int =
+    biometricManager.canAuthenticate(BiometricManager.Authenticators.BIOMETRIC_STRONG)
+
   private fun createResponse(
     error: String? = null,
     warning: String? = null
diff --git a/src/LocalAuthentication.ts b/src/LocalAuthentication.ts
index b9f3f0732b61138f790e7c3a33a92d8d726a71f1..b847e90d87e91e4a5be83d1b9c90dbc6fe6188bb 100644
--- a/src/LocalAuthentication.ts
+++ b/src/LocalAuthentication.ts
@@ -78,12 +78,17 @@ export async function getEnrolledLevelAsync(): Promise<SecurityLevel> {
  * @return Returns a promise which fulfils with [`LocalAuthenticationResult`](#localauthenticationresult).
  */
 export async function authenticateAsync(
-  options: LocalAuthenticationOptions = {}
+  options: LocalAuthenticationOptions
 ): Promise<LocalAuthenticationResult> {
   if (!ExpoLocalAuthentication.authenticateAsync) {
     throw new UnavailabilityError('expo-local-authentication', 'authenticateAsync');
   }
 
+  invariant(
+    typeof options.cancelLabel === 'string' && options.cancelLabel.length,
+    'LocalAuthentication.authenticateAsync : `options.cancelLabel` must be a non-empty string.'
+  );
+
   if (options.hasOwnProperty('promptMessage')) {
     invariant(
       typeof options.promptMessage === 'string' && options.promptMessage.length,
diff --git a/src/LocalAuthentication.types.ts b/src/LocalAuthentication.types.ts
index a65b16d5bc5d18c03cee3ca8e4d223c9b736659b..d1ae18df61714b2bd44f3b9867718568707c1dc6 100644
--- a/src/LocalAuthentication.types.ts
+++ b/src/LocalAuthentication.types.ts
@@ -42,9 +42,9 @@ export type LocalAuthenticationOptions = {
    */
   promptMessage?: string;
   /**
-   * Allows to customize the default `Cancel` label shown.
+   * Allows to customize the default `Cancel` label shown. Required to be non-empty for Android or it might cause crashes.
    */
-  cancelLabel?: string;
+  cancelLabel: string;
   /**
    * After several failed attempts the system will fallback to the device passcode. This setting
    * allows you to disable this option and instead handle the fallback yourself. This can be
