Skip to content

Commit 9023957

Browse files
committed
Update Android biometric lib and improve null handling
Upgrades Android biometric dependency to androidx.biometric:biometric-ktx:1.4.0-alpha02 and updates usage to prefer setConfirmationRequired for improved UX. Refactors HybridSensitiveInfo to return a Variant_NullType_SensitiveInfoItem when no entry is found, improving type safety and compatibility. Also enables Gradle parallel builds in the example, and updates iOS and JS dependencies to latest React Native and NitroModules versions.
1 parent b84ec82 commit 9023957

File tree

9 files changed

+1028
-976
lines changed

9 files changed

+1028
-976
lines changed

android/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ dependencies {
138138
// Add a dependency on NitroModules
139139
implementation project(":react-native-nitro-modules")
140140

141-
implementation "androidx.biometric:biometric:1.1.0"
141+
implementation "androidx.biometric:biometric-ktx:1.4.0-alpha02"
142142
}
143143

144144
if (isNewArchitectureEnabled()) {

android/src/main/java/com/sensitiveinfo/HybridSensitiveInfo.kt

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package com.sensitiveinfo
22

3+
import androidx.annotation.Keep
4+
import com.facebook.proguard.annotations.DoNotStrip
5+
36
import android.content.Context
47
import com.margelo.nitro.core.Promise
58
import com.margelo.nitro.sensitiveinfo.*
@@ -24,6 +27,8 @@ import kotlin.jvm.Volatile
2427
* This class provides secure storage for sensitive data on Android using the Android Keystore
2528
* for key management and SharedPreferences for encrypted data persistence.
2629
*/
30+
@DoNotStrip
31+
@Keep
2732
class HybridSensitiveInfo : HybridSensitiveInfoSpec() {
2833
private data class Dependencies(
2934
val context: Context,
@@ -98,14 +103,33 @@ class HybridSensitiveInfo : HybridSensitiveInfoSpec() {
98103
}
99104
}
100105

101-
override fun getItem(request: SensitiveInfoGetRequest): Promise<SensitiveInfoItem?> {
106+
override fun getItem(request: SensitiveInfoGetRequest): Promise<Variant_NullType_SensitiveInfoItem> {
102107
return Promise.async(coroutineScope) {
103108
val deps = ensureInitialized()
104109
val service = deps.serviceNameResolver.resolve(request.service)
105110

106111
val entry = deps.storage.read(service, request.key)
112+
107113
if (entry == null) {
108-
return@async null
114+
try {
115+
val ctor = com.margelo.nitro.core.NullType::class.java.getDeclaredConstructor()
116+
ctor.isAccessible = true
117+
val nullTypeInstance = ctor.newInstance()
118+
return@async Variant_NullType_SensitiveInfoItem.create(nullTypeInstance)
119+
} catch (e: Throwable) {
120+
// Fallback: create a null-type via unsafe camino — return a Second with empty SensitiveInfoItem omitted
121+
return@async Variant_NullType_SensitiveInfoItem.create(com.margelo.nitro.sensitiveinfo.SensitiveInfoItem(
122+
key = request.key,
123+
service = service,
124+
value = null,
125+
metadata = StorageMetadata(
126+
securityLevel = SecurityLevel.SOFTWARE,
127+
backend = StorageBackend.ANDROIDKEYSTORE,
128+
accessControl = AccessControl.NONE,
129+
timestamp = System.currentTimeMillis() / 1000.0
130+
)
131+
))
132+
}
109133
}
110134

111135
val metadata = entry.metadata.toStorageMetadata()
@@ -131,15 +155,17 @@ class HybridSensitiveInfo : HybridSensitiveInfoSpec() {
131155
null
132156
}
133157

134-
SensitiveInfoItem(
135-
key = request.key,
136-
service = service,
137-
value = value,
138-
metadata = metadata ?: StorageMetadata(
139-
securityLevel = SecurityLevel.SOFTWARE,
140-
backend = StorageBackend.ANDROIDKEYSTORE,
141-
accessControl = AccessControl.NONE,
142-
timestamp = System.currentTimeMillis() / 1000.0
158+
Variant_NullType_SensitiveInfoItem.create(
159+
SensitiveInfoItem(
160+
key = request.key,
161+
service = service,
162+
value = value,
163+
metadata = metadata ?: StorageMetadata(
164+
securityLevel = SecurityLevel.SOFTWARE,
165+
backend = StorageBackend.ANDROIDKEYSTORE,
166+
accessControl = AccessControl.NONE,
167+
timestamp = System.currentTimeMillis() / 1000.0
168+
)
143169
)
144170
)
145171
}

android/src/main/java/com/sensitiveinfo/internal/auth/BiometricAuthenticator.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,12 +120,22 @@ internal class BiometricAuthenticator {
120120
val builder = BiometricPrompt.PromptInfo.Builder()
121121
.setTitle(prompt.title)
122122

123+
// Prefer disabling confirmation on supported devices to streamline UX while maintaining
124+
// biometric security. Newer Biometric APIs support `setConfirmationRequired`.
125+
try {
126+
builder.setConfirmationRequired(false)
127+
} catch (_: Throwable) {
128+
// Ignore if the platform/library doesn't support this method.
129+
}
130+
123131
prompt.subtitle?.let(builder::setSubtitle)
124132
prompt.description?.let(builder::setDescription)
125133

126134
var promptAuthenticators = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
135+
// Newer biometric library versions (1.4.x+) prefer `setAllowedAuthenticators`.
127136
allowedAuthenticators
128137
} else {
138+
// On older platforms fall back to the legacy flags.
129139
allowedAuthenticators and (BiometricManager.Authenticators.BIOMETRIC_STRONG or BiometricManager.Authenticators.DEVICE_CREDENTIAL)
130140
}
131141

example/android/gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m
1515
# When configured, Gradle will run in incubating parallel mode.
1616
# This option should only be used with decoupled projects. More details, visit
1717
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18-
# org.gradle.parallel=true
18+
org.gradle.parallel=true
1919

2020
# AndroidX package structure to make it clearer which packages are bundled with the
2121
# Android operating system, and which are packaged with your app's APK

0 commit comments

Comments
 (0)