diff --git a/build.gradle b/build.gradle index af0c578..b6733a5 100644 --- a/build.gradle +++ b/build.gradle @@ -74,6 +74,7 @@ android { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib:2.0.10" + implementation 'androidx.activity:activity-ktx:1.9.1' testImplementation "junit:junit:4.13.2" testImplementation "androidx.test.ext:junit:1.2.1" diff --git a/src/main/java/com/simprints/libsimprints/Constants.kt b/src/main/java/com/simprints/libsimprints/Constants.kt index f2ae264..db99153 100644 --- a/src/main/java/com/simprints/libsimprints/Constants.kt +++ b/src/main/java/com/simprints/libsimprints/Constants.kt @@ -1,105 +1,115 @@ -package com.simprints.libsimprints; +package com.simprints.libsimprints -import android.app.Activity; +import android.app.Activity @SuppressWarnings("unused", "WeakerAccess") object Constants { // Intents - const val SIMPRINTS_REGISTER_INTENT = "com.simprints.id.REGISTER"; - const val SIMPRINTS_IDENTIFY_INTENT = "com.simprints.id.IDENTIFY"; - const val SIMPRINTS_VERIFY_INTENT = "com.simprints.id.VERIFY"; - const val SIMPRINTS_SELECT_GUID_INTENT = "com.simprints.id.CONFIRM_IDENTITY"; - const val SIMPRINTS_REGISTER_LAST_BIOMETRICS_INTENT = "com.simprints.id.REGISTER_LAST_BIOMETRICS"; + const val SIMPRINTS_ENROL_INTENT = "com.simprints.id.REGISTER" + const val SIMPRINTS_IDENTIFY_INTENT = "com.simprints.id.IDENTIFY" + const val SIMPRINTS_VERIFY_INTENT = "com.simprints.id.VERIFY" + const val SIMPRINTS_CONFIRM_IDENTITY_INTENT = "com.simprints.id.CONFIRM_IDENTITY" + const val SIMPRINTS_ENROL_LAST_BIOMETRICS_INTENT = "com.simprints.id.REGISTER_LAST_BIOMETRICS" // Mandatory extras - const val SIMPRINTS_PROJECT_ID = "projectId"; - const val SIMPRINTS_USER_ID = "userId"; - const val SIMPRINTS_MODULE_ID = "moduleId"; + const val SIMPRINTS_PROJECT_ID = "projectId" + const val SIMPRINTS_USER_ID = "userId" + const val SIMPRINTS_MODULE_ID = "moduleId" // Mandatory for SIMPRINTS_VERIFY_INTENT - const val SIMPRINTS_VERIFY_GUID = "verifyGuid"; + const val SIMPRINTS_VERIFY_GUID = "verifyGuid" - // Mandatory for SIMPRINTS_SELECT_GUID_INTENT - const val SIMPRINTS_SELECTED_GUID = "selectedGuid"; - const val SIMPRINTS_SESSION_ID = "sessionId"; + // Mandatory for SIMPRINTS_CONFIRM_IDENTITY_INTENT + const val SIMPRINTS_SELECTED_GUID = "selectedGuid" + const val SIMPRINTS_SESSION_ID = "sessionId" + + // Special case value for SIMPRINTS_CONFIRM_IDENTITY_INTENT when none of the guids are selected + const val SIMPRINTS_SELECTED_GUID_NONE = "none_selected" // Optional extras - const val SIMPRINTS_CALLING_PACKAGE = "packageName"; - const val SIMPRINTS_BIOMETRIC_DATA_SOURCE = "biometricDataSource"; - const val SIMPRINTS_METADATA = "metadata"; + const val SIMPRINTS_CALLING_PACKAGE = "packageName" + const val SIMPRINTS_BIOMETRIC_DATA_SOURCE = "biometricDataSource" + const val SIMPRINTS_METADATA = "metadata" // Optional keys in SIMPRINTS_METADATA - const val SIMPRINTS_SUBJECT_AGE = "subjectAge"; + const val SIMPRINTS_SUBJECT_AGE = "subjectAge" // Custom callout parameters for particular integrations: Don't include if not needed - const val SIMPRINTS_RESULT_FORMAT = "resultFormat"; - const val SIMPRINTS_ODK_RESULT_FORMAT_V01 = "ODKv01"; - const val SIMPRINTS_ODK_RESULT_FORMAT_V01_SEPARATOR = " "; + const val SIMPRINTS_RESULT_FORMAT = "resultFormat" + const val SIMPRINTS_ODK_RESULT_FORMAT_V01 = "ODKv01" + const val SIMPRINTS_ODK_RESULT_FORMAT_V01_SEPARATOR = " " // Result codes - const val SIMPRINTS_OK = Activity.RESULT_OK; - const val SIMPRINTS_CANCELLED = Activity.RESULT_CANCELED; - const val SIMPRINTS_MISSING_USER_ID = Activity.RESULT_FIRST_USER + 2; - const val SIMPRINTS_MISSING_MODULE_ID = Activity.RESULT_FIRST_USER + 4; - const val SIMPRINTS_INVALID_INTENT_ACTION = Activity.RESULT_FIRST_USER + 6; - const val SIMPRINTS_INVALID_UPDATE_GUID = Activity.RESULT_FIRST_USER + 7; - const val SIMPRINTS_MISSING_UPDATE_GUID = Activity.RESULT_FIRST_USER + 8; - const val SIMPRINTS_MISSING_VERIFY_GUID = Activity.RESULT_FIRST_USER + 9; - const val SIMPRINTS_INVALID_METADATA = Activity.RESULT_FIRST_USER + 10; - const val SIMPRINTS_VERIFY_GUID_NOT_FOUND_ONLINE = Activity.RESULT_FIRST_USER + 11; - const val SIMPRINTS_VERIFY_GUID_NOT_FOUND_OFFLINE = Activity.RESULT_FIRST_USER + 12; - const val SIMPRINTS_INVALID_VERIFY_GUID = Activity.RESULT_FIRST_USER + 13; - const val SIMPRINTS_INVALID_RESULT_FORMAT = Activity.RESULT_FIRST_USER + 14; - const val SIMPRINTS_INVALID_MODULE_ID = Activity.RESULT_FIRST_USER + 15; - const val SIMPRINTS_INVALID_USER_ID = Activity.RESULT_FIRST_USER + 16; - const val SIMPRINTS_INVALID_CALLING_PACKAGE = Activity.RESULT_FIRST_USER + 17; - const val SIMPRINTS_MISSING_PROJECT_ID = Activity.RESULT_FIRST_USER + 18; - const val SIMPRINTS_INVALID_PROJECT_ID = Activity.RESULT_FIRST_USER + 19; - const val SIMPRINTS_DIFFERENT_PROJECT_ID = Activity.RESULT_FIRST_USER + 20; - const val SIMPRINTS_DIFFERENT_USER_ID = Activity.RESULT_FIRST_USER + 21; - const val SIMPRINTS_ROOTED_DEVICE = Activity.RESULT_FIRST_USER + 22; - const val SIMPRINTS_UNEXPECTED_ERROR = Activity.RESULT_FIRST_USER + 23; - const val SIMPRINTS_BLUETOOTH_NOT_SUPPORTED = Activity.RESULT_FIRST_USER + 24; - const val SIMPRINTS_INVALID_SELECTED_ID = Activity.RESULT_FIRST_USER + 25; - const val SIMPRINTS_INVALID_SESSION_ID = Activity.RESULT_FIRST_USER + 26; - const val SIMPRINTS_LOGIN_NOT_COMPLETE = Activity.RESULT_FIRST_USER + 27; - const val SIMPRINTS_INVALID_STATE_FOR_INTENT_ACTION = Activity.RESULT_FIRST_USER + 28; - const val SIMPRINTS_ENROLMENT_LAST_BIOMETRICS_FAILED = Activity.RESULT_FIRST_USER + 29; - const val SIMPRINTS_LICENSE_MISSING = Activity.RESULT_FIRST_USER + 30; - const val SIMPRINTS_LICENSE_INVALID = Activity.RESULT_FIRST_USER + 31; - const val SIMPRINTS_SETUP_OFFLINE_DURING_MODALITY_DOWNLOAD = Activity.RESULT_FIRST_USER + 32; - const val SIMPRINTS_SETUP_MODALITY_DOWNLOAD_CANCELLED = Activity.RESULT_FIRST_USER + 33; - const val SIMPRINTS_FINGERPRINT_CONFIGURATION_ERROR = Activity.RESULT_FIRST_USER + 34; - const val SIMPRINTS_FACE_CONFIGURATION_ERROR = Activity.RESULT_FIRST_USER + 35; - const val SIMPRINTS_BACKEND_MAINTENANCE_ERROR = Activity.RESULT_FIRST_USER + 36; - const val SIMPRINTS_PROJECT_PAUSED = Activity.RESULT_FIRST_USER + 37; - const val SIMPRINTS_PROJECT_ENDING = Activity.RESULT_FIRST_USER + 38; - const val SIMPRINTS_BLUETOOTH_NO_PERMISSION = Activity.RESULT_FIRST_USER + 39; - const val SIMPRINTS_AGE_GROUP_NOT_SUPPORTED = Activity.RESULT_FIRST_USER + 40; + const val SIMPRINTS_OK = Activity.RESULT_OK + const val SIMPRINTS_CANCELLED = Activity.RESULT_CANCELED + const val SIMPRINTS_MISSING_USER_ID = Activity.RESULT_FIRST_USER + 2 + const val SIMPRINTS_MISSING_MODULE_ID = Activity.RESULT_FIRST_USER + 4 + const val SIMPRINTS_INVALID_INTENT_ACTION = Activity.RESULT_FIRST_USER + 6 + const val SIMPRINTS_INVALID_UPDATE_GUID = Activity.RESULT_FIRST_USER + 7 + const val SIMPRINTS_MISSING_UPDATE_GUID = Activity.RESULT_FIRST_USER + 8 + const val SIMPRINTS_MISSING_VERIFY_GUID = Activity.RESULT_FIRST_USER + 9 + const val SIMPRINTS_INVALID_METADATA = Activity.RESULT_FIRST_USER + 10 + const val SIMPRINTS_VERIFY_GUID_NOT_FOUND_ONLINE = Activity.RESULT_FIRST_USER + 11 + const val SIMPRINTS_VERIFY_GUID_NOT_FOUND_OFFLINE = Activity.RESULT_FIRST_USER + 12 + const val SIMPRINTS_INVALID_VERIFY_GUID = Activity.RESULT_FIRST_USER + 13 + const val SIMPRINTS_INVALID_RESULT_FORMAT = Activity.RESULT_FIRST_USER + 14 + const val SIMPRINTS_INVALID_MODULE_ID = Activity.RESULT_FIRST_USER + 15 + const val SIMPRINTS_INVALID_USER_ID = Activity.RESULT_FIRST_USER + 16 + const val SIMPRINTS_INVALID_CALLING_PACKAGE = Activity.RESULT_FIRST_USER + 17 + const val SIMPRINTS_MISSING_PROJECT_ID = Activity.RESULT_FIRST_USER + 18 + const val SIMPRINTS_INVALID_PROJECT_ID = Activity.RESULT_FIRST_USER + 19 + const val SIMPRINTS_DIFFERENT_PROJECT_ID = Activity.RESULT_FIRST_USER + 20 + const val SIMPRINTS_DIFFERENT_USER_ID = Activity.RESULT_FIRST_USER + 21 + const val SIMPRINTS_ROOTED_DEVICE = Activity.RESULT_FIRST_USER + 22 + const val SIMPRINTS_UNEXPECTED_ERROR = Activity.RESULT_FIRST_USER + 23 + const val SIMPRINTS_BLUETOOTH_NOT_SUPPORTED = Activity.RESULT_FIRST_USER + 24 + const val SIMPRINTS_INVALID_SELECTED_ID = Activity.RESULT_FIRST_USER + 25 + const val SIMPRINTS_INVALID_SESSION_ID = Activity.RESULT_FIRST_USER + 26 + const val SIMPRINTS_LOGIN_NOT_COMPLETE = Activity.RESULT_FIRST_USER + 27 + const val SIMPRINTS_INVALID_STATE_FOR_INTENT_ACTION = Activity.RESULT_FIRST_USER + 28 + const val SIMPRINTS_ENROLMENT_LAST_BIOMETRICS_FAILED = Activity.RESULT_FIRST_USER + 29 + const val SIMPRINTS_LICENSE_MISSING = Activity.RESULT_FIRST_USER + 30 + const val SIMPRINTS_LICENSE_INVALID = Activity.RESULT_FIRST_USER + 31 + const val SIMPRINTS_SETUP_OFFLINE_DURING_MODALITY_DOWNLOAD = Activity.RESULT_FIRST_USER + 32 + const val SIMPRINTS_SETUP_MODALITY_DOWNLOAD_CANCELLED = Activity.RESULT_FIRST_USER + 33 + const val SIMPRINTS_FINGERPRINT_CONFIGURATION_ERROR = Activity.RESULT_FIRST_USER + 34 + const val SIMPRINTS_FACE_CONFIGURATION_ERROR = Activity.RESULT_FIRST_USER + 35 + const val SIMPRINTS_BACKEND_MAINTENANCE_ERROR = Activity.RESULT_FIRST_USER + 36 + const val SIMPRINTS_PROJECT_PAUSED = Activity.RESULT_FIRST_USER + 37 + const val SIMPRINTS_PROJECT_ENDING = Activity.RESULT_FIRST_USER + 38 + const val SIMPRINTS_BLUETOOTH_NO_PERMISSION = Activity.RESULT_FIRST_USER + 39 + const val SIMPRINTS_AGE_GROUP_NOT_SUPPORTED = Activity.RESULT_FIRST_USER + 40 // Result extras - const val SIMPRINTS_REGISTRATION = "registration"; - const val SIMPRINTS_IDENTIFICATIONS = "identification"; - const val SIMPRINTS_VERIFICATION = "verification"; - const val SIMPRINTS_VERIFICATION_SUCCESS = "verificationSuccess"; - const val SIMPRINTS_REFUSAL_FORM = "refusalForm"; + const val SIMPRINTS_REGISTRATION = "registration" + const val SIMPRINTS_IDENTIFICATIONS = "identification" + const val SIMPRINTS_VERIFICATION = "verification" + const val SIMPRINTS_VERIFICATION_SUCCESS = "verificationSuccess" + const val SIMPRINTS_REFUSAL_FORM = "refusalForm" // When SIMPRINTS_BIOMETRICS_COMPLETE_CHECK is true, the user has completed the Simprints flow - const val SIMPRINTS_BIOMETRICS_COMPLETE_CHECK = "biometricsComplete"; + const val SIMPRINTS_BIOMETRICS_COMPLETE_CHECK = "biometricsComplete" // These two values represent data that could be null. They only apply to projects using cosync - const val SIMPRINTS_COSYNC_EVENT = "events"; - const val SIMPRINTS_COSYNC_SUBJECT_ACTIONS = "subjectActions"; - - // Deprecated extras - @Deprecated("Use {@link #SIMPRINTS_PROJECT_ID} instead.") - const val SIMPRINTS_API_KEY = "apiKey"; - - // Deprecated result codes - @Deprecated("Use {@link #SIMPRINTS_MISSING_PROJECT_ID} instead.") - const val SIMPRINTS_MISSING_API_KEY = Activity.RESULT_FIRST_USER; - - @Deprecated("Use {@link #SIMPRINTS_INVALID_PROJECT_ID} instead.") - const val SIMPRINTS_INVALID_API_KEY = Activity.RESULT_FIRST_USER + 1; + const val SIMPRINTS_COSYNC_EVENT = "events" + const val SIMPRINTS_COSYNC_SUBJECT_ACTIONS = "subjectActions" + + @Deprecated( + "Use SIMPRINTS_ENROL_INTENT instead", + replaceWith = ReplaceWith("SIMPRINTS_ENROL_INTENT") + ) + const val SIMPRINTS_REGISTER_INTENT = SIMPRINTS_ENROL_INTENT + + @Deprecated( + "Use SIMPRINTS_CONFIRM_IDENTITY_INTENT instead", + replaceWith = ReplaceWith("SIMPRINTS_CONFIRM_IDENTITY_INTENT") + ) + const val SIMPRINTS_SELECT_GUID_INTENT = SIMPRINTS_CONFIRM_IDENTITY_INTENT + + @Deprecated( + "Use SIMPRINTS_ENROL_LAST_BIOMETRICS_INTENT instead", + replaceWith = ReplaceWith("SIMPRINTS_ENROL_LAST_BIOMETRICS_INTENT") + ) + const val SIMPRINTS_REGISTER_LAST_BIOMETRICS_INTENT = SIMPRINTS_ENROL_LAST_BIOMETRICS_INTENT } diff --git a/src/main/java/com/simprints/libsimprints/FingerIdentifier.kt b/src/main/java/com/simprints/libsimprints/FingerIdentifier.kt index d717dfa..2957a38 100644 --- a/src/main/java/com/simprints/libsimprints/FingerIdentifier.kt +++ b/src/main/java/com/simprints/libsimprints/FingerIdentifier.kt @@ -1,6 +1,5 @@ -package com.simprints.libsimprints; +package com.simprints.libsimprints -@SuppressWarnings("unused") enum class FingerIdentifier { RIGHT_5TH_FINGER, RIGHT_4TH_FINGER, diff --git a/src/main/java/com/simprints/libsimprints/Identification.kt b/src/main/java/com/simprints/libsimprints/Identification.kt index 730b627..065a629 100644 --- a/src/main/java/com/simprints/libsimprints/Identification.kt +++ b/src/main/java/com/simprints/libsimprints/Identification.kt @@ -1,4 +1,4 @@ -package com.simprints.libsimprints; +package com.simprints.libsimprints import android.os.Parcelable import kotlinx.parcelize.Parcelize @@ -10,7 +10,6 @@ import kotlinx.parcelize.Parcelize * @param confidence An int containing the (matching) confidence * @param tier The tier score derived from the confidence */ -@SuppressWarnings("unused") @Parcelize data class Identification( val guid: String, diff --git a/src/main/java/com/simprints/libsimprints/Metadata.kt b/src/main/java/com/simprints/libsimprints/Metadata.kt index c01ceb8..3f4c20e 100644 --- a/src/main/java/com/simprints/libsimprints/Metadata.kt +++ b/src/main/java/com/simprints/libsimprints/Metadata.kt @@ -28,6 +28,8 @@ data class Metadata( * or it contains nested arrays or key/value mappings. */ constructor(jsonString: String) : this() { + if (jsonString.isBlank()) return + // Parse the JSON-encoded string try { json = JSONObject(jsonString) @@ -35,11 +37,11 @@ data class Metadata( throw InvalidMetadataException("The metadata string is not a valid JSON object string.") } // Make sure the metadata string does not contain nested arrays or key-value mappings - val keys = json.keys(); + val keys = json.keys() while (keys.hasNext()) { - val key = keys.next(); + val key = keys.next() if (json.optJSONArray(key) != null || json.optJSONObject(key) != null) - throw InvalidMetadataException("Only boolean, string, integer and floating point values are allowed."); + throw InvalidMetadataException("Only boolean, string, integer and floating point values are allowed.") } } @@ -81,9 +83,9 @@ data class Metadata( private fun putObject(key: String, value: Any): Metadata { try { - json.put(key, value); + json.put(key, value) } catch (e: JSONException) { - throw RuntimeException(e); + throw RuntimeException(e) } return this } diff --git a/src/main/java/com/simprints/libsimprints/RefusalForm.kt b/src/main/java/com/simprints/libsimprints/RefusalForm.kt index 20771e6..8951b8b 100644 --- a/src/main/java/com/simprints/libsimprints/RefusalForm.kt +++ b/src/main/java/com/simprints/libsimprints/RefusalForm.kt @@ -1,9 +1,8 @@ -package com.simprints.libsimprints; +package com.simprints.libsimprints import android.os.Parcelable import kotlinx.parcelize.Parcelize -@SuppressWarnings("WeakerAccess", "unused") @Parcelize data class RefusalForm( val reason: String, diff --git a/src/main/java/com/simprints/libsimprints/Registration.kt b/src/main/java/com/simprints/libsimprints/Registration.kt index 7c4bacd..ef7194c 100644 --- a/src/main/java/com/simprints/libsimprints/Registration.kt +++ b/src/main/java/com/simprints/libsimprints/Registration.kt @@ -1,35 +1,9 @@ -package com.simprints.libsimprints; +package com.simprints.libsimprints import android.os.Parcelable import kotlinx.parcelize.Parcelize -@SuppressWarnings("unused", "WeakerAccess") @Parcelize -data class Registration @JvmOverloads constructor( +data class Registration( val guid: String, - private val templates: MutableMap = mutableMapOf() -) : Parcelable { - - fun setTemplate(fingerId: FingerIdentifier, fingerTemplate: ByteArray) { - templates[fingerId] = fingerTemplate - } - - fun getTemplate(fingerId: FingerIdentifier): ByteArray = templates[fingerId] ?: byteArrayOf() - - override fun hashCode(): Int { - var result = super.hashCode() - result = 31 * result + guid.hashCode() - result = 31 * result + templates.hashCode() - return result - } - - override fun equals(other: Any?): Boolean { - if (other === this) return true - if (other !is Registration) return false - if (guid != other.guid) return false - for (fingerId in FingerIdentifier.entries) { - templates[fingerId] == (other.templates[fingerId] ?: return false) - } - return true; - } -} +) : Parcelable diff --git a/src/main/java/com/simprints/libsimprints/SimHelper.kt b/src/main/java/com/simprints/libsimprints/SimHelper.kt index a51a740..f1dff22 100644 --- a/src/main/java/com/simprints/libsimprints/SimHelper.kt +++ b/src/main/java/com/simprints/libsimprints/SimHelper.kt @@ -1,4 +1,4 @@ -package com.simprints.libsimprints; +package com.simprints.libsimprints import android.content.Intent @@ -18,6 +18,7 @@ import android.content.Intent * @param userId identifies which user is making a request to Simprints ID. Can be any arbitrary String. */ @SuppressWarnings("unused", "WeakerAccess") +@Deprecated("Use SimprintsContract instead") data class SimHelper( private val projectId: String, private val userId: String @@ -31,6 +32,7 @@ data class SimHelper( * @param metadata optional metadata to attach to the registration if provided. * @return a new registration {@link Intent}. */ + @Deprecated("Use SimprintsContract and SimprintsRequest.Enrol instead") @JvmOverloads fun register( moduleId: String, @@ -47,6 +49,7 @@ data class SimHelper( * @param metadata optional metadata to attach to the identification if provided. * @return a new identification {@link Intent}. */ + @Deprecated("Use SimprintsContract and SimprintsRequest.Identify instead") @JvmOverloads fun identify( moduleId: String, @@ -64,6 +67,7 @@ data class SimHelper( * @param metadata optional metadata to attach to the verification if provided. * @return a new verification {@link Intent}. */ + @Deprecated("Use SimprintsContract and SimprintsRequest.Verify instead") @JvmOverloads fun verify( moduleId: String, @@ -81,6 +85,7 @@ data class SimHelper( * @param selectedGuid the GUID that was confirmed in the host app. * @return a new confirm indentity {@link Intent}. */ + @Deprecated("Use SimprintsContract and SimprintsRequest.ConfirmIdentity instead") fun confirmIdentity( sessionId: String, selectedGuid: String, @@ -99,6 +104,7 @@ data class SimHelper( * @param metadata metadata to attach to the registration if provided. * @return a new registration for last biometrics {@link Intent}. */ + @Deprecated("Use SimprintsContract and SimprintsRequest.EnrolLastBiometric instead") @JvmOverloads fun registerLastBiometrics( moduleId: String, diff --git a/src/main/java/com/simprints/libsimprints/Tier.kt b/src/main/java/com/simprints/libsimprints/Tier.kt index ba6f0e2..6d19173 100644 --- a/src/main/java/com/simprints/libsimprints/Tier.kt +++ b/src/main/java/com/simprints/libsimprints/Tier.kt @@ -1,4 +1,4 @@ -package com.simprints.libsimprints; +package com.simprints.libsimprints enum class Tier { TIER_1, diff --git a/src/main/java/com/simprints/libsimprints/Verification.kt b/src/main/java/com/simprints/libsimprints/Verification.kt index ab9f1ce..187ec58 100644 --- a/src/main/java/com/simprints/libsimprints/Verification.kt +++ b/src/main/java/com/simprints/libsimprints/Verification.kt @@ -10,12 +10,13 @@ import kotlinx.parcelize.Parcelize * @param tier The tier score derived from the confidence * @param guid Global unique id of the verified person */ -@SuppressWarnings("unused", "WeakerAccess") @Parcelize -data class Verification( +data class Verification @JvmOverloads constructor( private val confidence: Int, val tier: Tier, val guid: String, + // TODO change to val once it is correctly returned from SID + var isSuccess: Boolean = false, ) : Parcelable { fun getConfidence(): Float = confidence.toFloat() diff --git a/src/main/java/com/simprints/libsimprints/contracts/SimprintsContract.kt b/src/main/java/com/simprints/libsimprints/contracts/SimprintsContract.kt new file mode 100644 index 0000000..c74694e --- /dev/null +++ b/src/main/java/com/simprints/libsimprints/contracts/SimprintsContract.kt @@ -0,0 +1,35 @@ +package com.simprints.libsimprints.contracts + +import android.content.Context +import android.content.Intent +import androidx.activity.result.contract.ActivityResultContract + +/** + * An [ActivityResultContract] that encapsulates the interaction with the Simprints ID. + * + * This contract handles the creation of an [Intent] from a [SimprintsRequest] to launch a Simprints operation, + * and the parsing of the result from the launched activity into a [SimprintsResponse]. + * + * + * Create an instance of [SimprintsContract] and register it with an Activity or Fragment + * ``` + * val simprintsLauncher = registerForActivityResult(SimprintsContract()) { result -> + * // Handle the SimprintsResponse here + * } + * ``` + * + * Call [launch] with a corresponding [SimprintsRequest] subclass to launch the corresponding Simprints ID flow. + * ``` + * // To launch the registration/enrollment flow in Simprints ID + * simprintsLauncher.launch(SimprintsRequest.Registration(projectId, userId, moduleId)) + * ``` + * + * @see [registerForActivityResult] + */ +class SimprintsContract() : ActivityResultContract() { + + override fun createIntent(context: Context, input: SimprintsRequest): Intent = input.toIntent() + + override fun parseResult(resultCode: Int, intent: Intent?): SimprintsResponse = + SimprintsResponse.fromIntent(intent, resultCode) +} diff --git a/src/main/java/com/simprints/libsimprints/contracts/SimprintsRequest.kt b/src/main/java/com/simprints/libsimprints/contracts/SimprintsRequest.kt new file mode 100644 index 0000000..f5624d2 --- /dev/null +++ b/src/main/java/com/simprints/libsimprints/contracts/SimprintsRequest.kt @@ -0,0 +1,161 @@ +package com.simprints.libsimprints.contracts + +import android.content.Intent +import com.simprints.libsimprints.Constants +import com.simprints.libsimprints.Metadata + +/** + * Each of the [SimprintsRequest] subclasses represents one of the possible flows that can be started in Simprints ID. + * + * Three main biometric flows are: + * * A [Enrol] call-out will collect fingerprints and link them to a new GUID. + * * An [Identify] call-out will collect fingerprints and search through a group of people. + * * A [Verify] call-out will collect fingerprints and verify a specific user. + * + * Additionally there are two possible follow-up flows: + * * A [ConfirmIdentity] call-out will notify SID that provided GUID matches the identified person. + * * An [EnrolLastBiometrics] call-out will perform a new registration/enrolment using the last collected biometric data. + * + * [More info](https://simprints.gitbook.io/docs/development/simprints-for-developers/integrating-with-simprints) + */ +sealed class SimprintsRequest { + + abstract val userId: String + abstract val projectId: String + + abstract fun toIntent(): Intent + + /** + * Data required to start the registration/enrolment request flow in Simprints ID. + * + * Response data will either contain a [Registration] object with the GUID and the templates, or additional data such as errors and refusal data. + * If Enrolment+ is enabled, list of [Identify] results could be returned if there are any close matches. + * + * [More info](https://simprints.gitbook.io/docs/development/simprints-for-developers/integrating-with-simprints/enrollment) + * + * @param projectId identifies the project that is making the call-out. Will be checked if it matches the scanned project id upon signing-in. + * @param userId identifies which user is making a request to Simprints ID. Can be any arbitrary String. + * @param moduleId identifies which module to register into. + * @param metadata optional metadata to attach to the registration if provided. + */ + data class Enrol( + override val projectId: String, + override val userId: String, + val moduleId: String, + val metadata: Metadata? = null, + ) : SimprintsRequest() { + + override fun toIntent() = Intent(Constants.SIMPRINTS_ENROL_INTENT) + .appendAuthFields(projectId, userId) + .putExtra(Constants.SIMPRINTS_MODULE_ID, moduleId) + .appendOptionalMetadata(metadata) + } + + /** + * Data required to start the identification request flow in Simprints ID. + * + * Response data will either contain an array of [Identify] objects, or additional data such as errors and refusal data. + * + * [More info](https://simprints.gitbook.io/docs/development/simprints-for-developers/integrating-with-simprints/identification) + * + * @param projectId identifies the project that is making the call-out. Will be checked if it matches the scanned project id upon signing-in. + * @param userId identifies which user is making a request to Simprints ID. Can be any arbitrary String. + * @param moduleId identifies which module to register into. + * @param metadata optional metadata to attach to the registration if provided. + */ + data class Identify( + override val projectId: String, + override val userId: String, + val moduleId: String, + val metadata: Metadata? = null, + ) : SimprintsRequest() { + override fun toIntent() = Intent(Constants.SIMPRINTS_IDENTIFY_INTENT) + .appendAuthFields(projectId, userId) + .putExtra(Constants.SIMPRINTS_MODULE_ID, moduleId) + .appendOptionalMetadata(metadata) + } + + /** + * Data required to start the verification request flow in Simprints ID. + * + * Response data will either contain a [Verify] object, or additional data such as errors and refusal data. + * + * [More info](https://simprints.gitbook.io/docs/development/simprints-for-developers/integrating-with-simprints/verification) + * + * @param projectId identifies the project that is making the call-out. Will be checked if it matches the scanned project id upon signing-in. + * @param userId identifies which user is making a request to Simprints ID. Can be any arbitrary String. + * @param moduleId identifies which module to register into. + * @param verifyId identifies which registered beneficiary to verify. + * @param metadata optional metadata to attach to the registration if provided. + */ + data class Verify( + override val projectId: String, + override val userId: String, + val moduleId: String, + val verifyId: String, + val metadata: Metadata? = null, + ) : SimprintsRequest() { + override fun toIntent() = Intent(Constants.SIMPRINTS_VERIFY_INTENT) + .appendAuthFields(projectId, userId) + .putExtra(Constants.SIMPRINTS_MODULE_ID, moduleId) + .putExtra(Constants.SIMPRINTS_VERIFY_GUID, verifyId) + .appendOptionalMetadata(metadata) + } + + /** + * Data required to start the identity confirmation follow-up flow in Simprints ID. + * + * [More info](https://simprints.gitbook.io/docs/development/simprints-for-developers/integrating-with-simprints/enrolment-and-identification-+) + * + * @param projectId identifies the project that is making the call-out. Will be checked if it matches the scanned project id upon signing-in. + * @param userId identifies which user is making a request to Simprints ID. Can be any arbitrary String. + * @param sessionId identifies the identification session. + * @param selectedGuid the GUID that was confirmed in the host app. + */ + data class ConfirmIdentity( + override val projectId: String, + override val userId: String, + val sessionId: String, + val selectedGuid: String, + ) : SimprintsRequest() { + override fun toIntent() = Intent(Constants.SIMPRINTS_CONFIRM_IDENTITY_INTENT) + .appendAuthFields(projectId, userId) + .putExtra(Constants.SIMPRINTS_SESSION_ID, sessionId) + .putExtra(Constants.SIMPRINTS_SELECTED_GUID, selectedGuid) + } + + /** + * Data required to start the last biometric enrolment follow-up flow in Simprints ID. + * + * Result data will either contain a [Registration] object with the GUID and the templates, or an error. + * + * [More info](https://simprints.gitbook.io/docs/development/simprints-for-developers/integrating-with-simprints/enrolment-and-identification-+) + * + * @param projectId identifies the project that is making the call-out. Will be checked if it matches the scanned project id upon signing-in. + * @param userId identifies which user is making a request to Simprints ID. Can be any arbitrary String. + * @param moduleId identifies which module to register into. + * @param sessionId identifies the identification session. + * @param metadata optional metadata to attach to the registration if provided. + */ + data class EnrolLastBiometrics( + override val projectId: String, + override val userId: String, + val moduleId: String, + val sessionId: String, + val metadata: Metadata? = null, + ) : SimprintsRequest() { + override fun toIntent() = Intent(Constants.SIMPRINTS_ENROL_LAST_BIOMETRICS_INTENT) + .appendAuthFields(projectId, userId) + .putExtra(Constants.SIMPRINTS_MODULE_ID, moduleId) + .putExtra(Constants.SIMPRINTS_SESSION_ID, sessionId) + .appendOptionalMetadata(metadata) + } + + protected fun Intent.appendAuthFields(projectId: String, userId: String) = this + .putExtra(Constants.SIMPRINTS_PROJECT_ID, projectId) + .putExtra(Constants.SIMPRINTS_USER_ID, userId) + + protected fun Intent.appendOptionalMetadata(metadata: Metadata?) = + if (metadata == null) this + else putExtra(Constants.SIMPRINTS_METADATA, metadata.toString()) +} diff --git a/src/main/java/com/simprints/libsimprints/contracts/SimprintsResponse.kt b/src/main/java/com/simprints/libsimprints/contracts/SimprintsResponse.kt new file mode 100644 index 0000000..b2421d7 --- /dev/null +++ b/src/main/java/com/simprints/libsimprints/contracts/SimprintsResponse.kt @@ -0,0 +1,97 @@ +package com.simprints.libsimprints.contracts + +import android.content.Intent +import com.simprints.libsimprints.Constants +import com.simprints.libsimprints.Identification +import com.simprints.libsimprints.RefusalForm +import com.simprints.libsimprints.Registration +import com.simprints.libsimprints.Verification + +/** + * Container class for all possible response data that Simprints ID can return. + * + * In all cases at most one of + * * registration: [Registration] - in case of enrolment + * * verification: [Verification] - in case of verification + * * identifications: List<[Identification]> - in case of identification + * * refusal: [RefusalForm] - in case of patient refusal + * will be non-null if the result code is [Constants.SIMPRINTS_OK]. + * + */ +data class SimprintsResponse( + // Data common to all requests + val resultCode: Int, + val biometricsComplete: Boolean = false, + val sessionId: String? = null, + + // Request-specific data - only one field will be non-null + val registration: Registration? = null, + val verification: Verification? = null, + val identifications: List? = null, + val refusal: RefusalForm? = null, + + // Co-sync data + val subjectActions: String? = null, +) { + + companion object { + + @Suppress("UNCHECKED_CAST") + @JvmStatic + fun fromIntent(intent: Intent?, resultCode: Int): SimprintsResponse = when { + resultCode != Constants.SIMPRINTS_OK -> SimprintsResponse(resultCode = resultCode) + intent == null -> SimprintsResponse(resultCode = Constants.SIMPRINTS_CANCELLED) + + intent.hasExtra(Constants.SIMPRINTS_REFUSAL_FORM) -> SimprintsResponse( + resultCode = resultCode, + biometricsComplete = intent.getBooleanExtra( + Constants.SIMPRINTS_BIOMETRICS_COMPLETE_CHECK, + false + ), + sessionId = intent.getStringExtra(Constants.SIMPRINTS_SESSION_ID), + refusal = intent.getParcelableExtra(Constants.SIMPRINTS_REFUSAL_FORM), + ) + + intent.hasExtra(Constants.SIMPRINTS_REGISTRATION) -> SimprintsResponse( + resultCode = resultCode, + biometricsComplete = intent.getBooleanExtra( + Constants.SIMPRINTS_BIOMETRICS_COMPLETE_CHECK, + false + ), + sessionId = intent.getStringExtra(Constants.SIMPRINTS_SESSION_ID), + registration = intent.getParcelableExtra(Constants.SIMPRINTS_REGISTRATION), + subjectActions = intent.getStringExtra(Constants.SIMPRINTS_COSYNC_SUBJECT_ACTIONS), + ) + + intent.hasExtra(Constants.SIMPRINTS_IDENTIFICATIONS) -> SimprintsResponse( + resultCode = resultCode, + biometricsComplete = intent.getBooleanExtra( + Constants.SIMPRINTS_BIOMETRICS_COMPLETE_CHECK, + false + ), + sessionId = intent.getStringExtra(Constants.SIMPRINTS_SESSION_ID), + identifications = intent.getParcelableArrayListExtra(Constants.SIMPRINTS_IDENTIFICATIONS) as List?, + ) + + intent.hasExtra(Constants.SIMPRINTS_VERIFICATION) -> { + val verification = intent.getParcelableExtra(Constants.SIMPRINTS_VERIFICATION) as Verification? + + SimprintsResponse( + resultCode = resultCode, + biometricsComplete = intent.getBooleanExtra( + Constants.SIMPRINTS_BIOMETRICS_COMPLETE_CHECK, + false + ), + sessionId = intent.getStringExtra(Constants.SIMPRINTS_SESSION_ID), + verification = verification?.also { + // In SID 2024.2.0 this value is returned next to the verification object, + // so it needs to be updated on during response parsing + it.isSuccess = intent.getBooleanExtra(Constants.SIMPRINTS_VERIFICATION_SUCCESS, false) + }, + ) + } + + else -> SimprintsResponse(resultCode = Constants.SIMPRINTS_CANCELLED) + } + } +} diff --git a/src/test/java/com/simprints/libsimprints/IdentificationTest.java b/src/test/java/com/simprints/libsimprints/IdentificationTest.java deleted file mode 100644 index 70b47b3..0000000 --- a/src/test/java/com/simprints/libsimprints/IdentificationTest.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.simprints.libsimprints; - -import android.os.Parcel; - -import androidx.test.ext.junit.runners.AndroidJUnit4; - -import junit.framework.Assert; - -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; - - -@RunWith(AndroidJUnit4.class) -public class IdentificationTest { - @Test - public void testIdentificationParcelling() { - Identification exampleId = new Identification("case-id", 99, Tier.TIER_1); - - Parcel parcel = Parcel.obtain(); - exampleId.writeToParcel(parcel, 0); - - parcel.setDataPosition(0); - - Identification createdFromParcel = Identification.CREATOR.createFromParcel(parcel); - Assert.assertEquals(exampleId, createdFromParcel); - } - - @Test - public void testSorting() { - ArrayList idList; - Identification topId = new Identification("top-id", 99, Tier.TIER_1); - Identification midId1 = new Identification("first-mid-id", 51, Tier.TIER_3); - Identification midId2 = new Identification("second-mid-id", 51, Tier.TIER_3); - Identification lowId = new Identification("low-id", 2, Tier.TIER_5); - Identification[] descendingOrder = new Identification[]{topId, midId1, midId2, lowId}; - - Identification[] f = new Identification[]{midId1, lowId, topId, midId2}; - idList = new ArrayList<>(Arrays.asList(f)); - - Collections.sort(idList); - for (int i = 0; i < descendingOrder.length; i++) { - Assert.assertEquals(descendingOrder[i], idList.get(i)); - } - } -} \ No newline at end of file diff --git a/src/test/java/com/simprints/libsimprints/IdentificationTest.kt b/src/test/java/com/simprints/libsimprints/IdentificationTest.kt new file mode 100644 index 0000000..7f977c1 --- /dev/null +++ b/src/test/java/com/simprints/libsimprints/IdentificationTest.kt @@ -0,0 +1,43 @@ +package com.simprints.libsimprints + +import androidx.core.os.bundleOf +import androidx.test.ext.junit.runners.AndroidJUnit4 +import org.junit.Assert.assertEquals +import org.junit.Test +import org.junit.runner.RunWith + + +@RunWith(AndroidJUnit4::class) +class IdentificationTest { + + @Test + fun `test identification parcelling`() { + val expected = Identification("case-id", 99, Tier.TIER_1) + val actual = bundleOf("test" to expected).getParcelable("test") + + assertEquals(expected, actual) + } + + + @Test + fun `test verification confidence`() { + val identification = Identification("case-id", 42, Tier.TIER_2) + + assertEquals(42.0f, identification.getConfidence()) + } + + @Test + fun `test sorting`() { + val topId = Identification("top-id", 99, Tier.TIER_1) + val midId1 = Identification("first-mid-id", 51, Tier.TIER_3) + val midId2 = Identification("second-mid-id", 51, Tier.TIER_3) + val lowId = Identification("low-id", 2, Tier.TIER_5) + + val descendingOrder = listOf(topId, midId1, midId2, lowId) + val sortedList = listOf(midId1, lowId, topId, midId2).sorted() + + for (i in descendingOrder.indices) { + assertEquals(descendingOrder[i], sortedList[i]) + } + } +} diff --git a/src/test/java/com/simprints/libsimprints/MetadataTest.kt b/src/test/java/com/simprints/libsimprints/MetadataTest.kt new file mode 100644 index 0000000..4f5cb22 --- /dev/null +++ b/src/test/java/com/simprints/libsimprints/MetadataTest.kt @@ -0,0 +1,79 @@ +package com.simprints.libsimprints + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.simprints.libsimprints.Metadata.InvalidMetadataException +import junit.framework.TestCase.assertEquals +import org.junit.Assert.fail +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class MetadataTest { + + @Test + fun `constructs from blank string`() { + val result = Metadata(" ") + + assertEquals("""{}""", result.toString()) + } + + @Test + fun `constructs from valid fields`() { + val result = Metadata( + """ + { + "key1": 1, + "key2":true, + "key3": "value", + "key4": 0.5 + } + """.trimIndent() + ) + + assertEquals("""{"key1":1,"key2":true,"key3":"value","key4":0.5}""", result.toString()) + } + + @Test + fun `fails to construct from array fields`() { + try { + Metadata("""{"key1": 1,"key":[]}""") + + fail("Should have thrown") + } catch (e: Exception) { + assertEquals(InvalidMetadataException::class.java, e::class.java) + } + } + + @Test + fun `fails to construct from object fields`() { + try { + Metadata("""{"key1": 1,"key":{}}""") + + fail("Should have thrown") + } catch (e: Exception) { + assertEquals(InvalidMetadataException::class.java, e::class.java) + } + } + + @Test + fun `fails to construct from invalid string`() { + try { + Metadata("test") + + fail("Should have thrown") + } catch (e: Exception) { + assertEquals(InvalidMetadataException::class.java, e::class.java) + } + } + + @Test + fun `puts objects correctly`() { + val result = Metadata() + result.put("key1", 1) + result.put("key2", true) + result.put("key3", "value") + result.put("key4", 0.5) + + assertEquals("""{"key1":1,"key2":true,"key3":"value","key4":0.5}""", result.toString()) + } +} diff --git a/src/test/java/com/simprints/libsimprints/RefusalFormTest.java b/src/test/java/com/simprints/libsimprints/RefusalFormTest.java deleted file mode 100644 index 451c532..0000000 --- a/src/test/java/com/simprints/libsimprints/RefusalFormTest.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.simprints.libsimprints; - -import android.os.Parcel; - -import androidx.test.ext.junit.runners.AndroidJUnit4; - -import junit.framework.Assert; - -import org.junit.Test; -import org.junit.runner.RunWith; - -@RunWith(AndroidJUnit4.class) -public class RefusalFormTest { - - @Test - public void testRefusalFormParcelling() { - RefusalForm example = new RefusalForm("No Scanner", "Forgot Scanner"); - - Parcel parcel = Parcel.obtain(); - example.writeToParcel(parcel, 0); - - parcel.setDataPosition(0); - - RefusalForm createdFromParcel = RefusalForm.CREATOR.createFromParcel(parcel); - Assert.assertEquals(example, createdFromParcel); - } -} diff --git a/src/test/java/com/simprints/libsimprints/RefusalFormTest.kt b/src/test/java/com/simprints/libsimprints/RefusalFormTest.kt new file mode 100644 index 0000000..f0b4942 --- /dev/null +++ b/src/test/java/com/simprints/libsimprints/RefusalFormTest.kt @@ -0,0 +1,19 @@ +package com.simprints.libsimprints; + +import androidx.core.os.bundleOf +import androidx.test.ext.junit.runners.AndroidJUnit4 +import org.junit.Assert.assertEquals +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class RefusalFormTest { + + @Test + fun `test refusal form parcelling`() { + val expected = RefusalForm("No Scanner", "Forgot Scanner") + val actual = bundleOf("test" to expected).getParcelable("test") + + assertEquals(expected, actual) + } +} diff --git a/src/test/java/com/simprints/libsimprints/RegistrationTest.java b/src/test/java/com/simprints/libsimprints/RegistrationTest.java deleted file mode 100644 index 91b35ab..0000000 --- a/src/test/java/com/simprints/libsimprints/RegistrationTest.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.simprints.libsimprints; - -import android.os.Parcel; - -import androidx.test.ext.junit.runners.AndroidJUnit4; - -import junit.framework.Assert; - -import org.junit.Test; -import org.junit.runner.RunWith; - -@RunWith(AndroidJUnit4.class) -public class RegistrationTest { - @Test - public void testRegistrationParcelling() { - - final byte[] leftThumb = {1, 2, 3, 4}; - final byte[] leftIndex = {3, 2, 1}; - final byte[] left3rd = {7, 8, 1, 9}; - final byte[] left4th = {7, 7, 7, 7, 7, 8, 1, 9}; - final byte[] left5th = {1, 2}; - final byte[] right5th = {8, 3, 5, 3, 3, 7, 7, 3}; - final byte[] right4th = {7, 1, 3, 7, 0, 5}; - final byte[] right3rd = {7}; - final byte[] rightThumb = {1, 0}; - final byte[] rightIndex = {0}; - - - Registration exampleRegistration = new Registration("case-id"); - exampleRegistration.setTemplate(FingerIdentifier.LEFT_THUMB, leftThumb); - exampleRegistration.setTemplate(FingerIdentifier.LEFT_INDEX_FINGER, leftIndex); - exampleRegistration.setTemplate(FingerIdentifier.LEFT_3RD_FINGER, left3rd); - exampleRegistration.setTemplate(FingerIdentifier.LEFT_4TH_FINGER, left4th); - exampleRegistration.setTemplate(FingerIdentifier.LEFT_5TH_FINGER, left5th); - exampleRegistration.setTemplate(FingerIdentifier.RIGHT_5TH_FINGER, right5th); - exampleRegistration.setTemplate(FingerIdentifier.RIGHT_4TH_FINGER, right4th); - exampleRegistration.setTemplate(FingerIdentifier.RIGHT_3RD_FINGER, right3rd); - exampleRegistration.setTemplate(FingerIdentifier.RIGHT_INDEX_FINGER, rightIndex); - exampleRegistration.setTemplate(FingerIdentifier.RIGHT_THUMB, rightThumb); - - Parcel parcel = Parcel.obtain(); - exampleRegistration.writeToParcel(parcel, 0); - - parcel.setDataPosition(0); - - Registration createdFromParcel = Registration.CREATOR.createFromParcel(parcel); - Assert.assertEquals(exampleRegistration, createdFromParcel); - } -} \ No newline at end of file diff --git a/src/test/java/com/simprints/libsimprints/RegistrationTest.kt b/src/test/java/com/simprints/libsimprints/RegistrationTest.kt new file mode 100644 index 0000000..fe35310 --- /dev/null +++ b/src/test/java/com/simprints/libsimprints/RegistrationTest.kt @@ -0,0 +1,19 @@ +package com.simprints.libsimprints + +import androidx.core.os.bundleOf +import androidx.test.ext.junit.runners.AndroidJUnit4 +import org.junit.Assert.assertEquals +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class RegistrationTest { + + @Test + fun `test registration parcelling`() { + val expected = Registration("case-id") + val actual = bundleOf("test" to expected).getParcelable("test") + + assertEquals(expected, actual) + } +} diff --git a/src/test/java/com/simprints/libsimprints/VerificationTest.kt b/src/test/java/com/simprints/libsimprints/VerificationTest.kt new file mode 100644 index 0000000..c6b9dfe --- /dev/null +++ b/src/test/java/com/simprints/libsimprints/VerificationTest.kt @@ -0,0 +1,28 @@ +package com.simprints.libsimprints + +import androidx.core.os.bundleOf +import androidx.test.ext.junit.runners.AndroidJUnit4 +import org.junit.Assert.assertEquals +import org.junit.Assert.assertFalse +import org.junit.Assert.assertTrue +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class VerificationTest { + + @Test + fun `test verification parcelling`() { + val expected = Verification(42, Tier.TIER_2, "case-id", true) + val actual = bundleOf("test" to expected).getParcelable("test") + + assertEquals(expected, actual) + } + + @Test + fun `test verification confidence`() { + val verification = Verification(42, Tier.TIER_2, "case-id", true) + + assertEquals(42.0f, verification.getConfidence()) + } +} diff --git a/src/test/java/com/simprints/libsimprints/contracts/SimprintsRequestTest.kt b/src/test/java/com/simprints/libsimprints/contracts/SimprintsRequestTest.kt new file mode 100644 index 0000000..ac30bc0 --- /dev/null +++ b/src/test/java/com/simprints/libsimprints/contracts/SimprintsRequestTest.kt @@ -0,0 +1,116 @@ +package com.simprints.libsimprints.contracts + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.simprints.libsimprints.Constants +import com.simprints.libsimprints.Metadata +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNull +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class SimprintsRequestTest { + + @Test + fun `creates correct enrol intent`() { + val intent = SimprintsRequest.Enrol( + projectId = "project-id", + userId = "user-id", + moduleId = "module-id", + metadata = Metadata().put("key", "value"), + ).toIntent() + + assertEquals(Constants.SIMPRINTS_ENROL_INTENT, intent.action) + assertEquals("project-id", intent.getStringExtra(Constants.SIMPRINTS_PROJECT_ID)) + assertEquals("user-id", intent.getStringExtra(Constants.SIMPRINTS_USER_ID)) + assertEquals("module-id", intent.getStringExtra(Constants.SIMPRINTS_MODULE_ID)) + assertEquals(METADATA_JSON, intent.getStringExtra(Constants.SIMPRINTS_METADATA)) + } + + @Test + fun `creates correct identify intent`() { + val intent = SimprintsRequest.Identify( + projectId = "project-id", + userId = "user-id", + moduleId = "module-id", + metadata = Metadata().put("key", "value"), + ).toIntent() + + assertEquals(Constants.SIMPRINTS_IDENTIFY_INTENT, intent.action) + assertEquals("project-id", intent.getStringExtra(Constants.SIMPRINTS_PROJECT_ID)) + assertEquals("user-id", intent.getStringExtra(Constants.SIMPRINTS_USER_ID)) + assertEquals("module-id", intent.getStringExtra(Constants.SIMPRINTS_MODULE_ID)) + assertEquals(METADATA_JSON, intent.getStringExtra(Constants.SIMPRINTS_METADATA)) + } + + @Test + fun `creates correct verify intent`() { + val intent = SimprintsRequest.Verify( + projectId = "project-id", + userId = "user-id", + moduleId = "module-id", + verifyId = "guid", + metadata = Metadata().put("key", "value"), + ).toIntent() + + assertEquals(Constants.SIMPRINTS_VERIFY_INTENT, intent.action) + assertEquals("project-id", intent.getStringExtra(Constants.SIMPRINTS_PROJECT_ID)) + assertEquals("user-id", intent.getStringExtra(Constants.SIMPRINTS_USER_ID)) + assertEquals("module-id", intent.getStringExtra(Constants.SIMPRINTS_MODULE_ID)) + assertEquals("guid", intent.getStringExtra(Constants.SIMPRINTS_VERIFY_GUID)) + assertEquals(METADATA_JSON, intent.getStringExtra(Constants.SIMPRINTS_METADATA)) + } + + @Test + fun `creates correct confirm intent`() { + val intent = SimprintsRequest.ConfirmIdentity( + projectId = "project-id", + userId = "user-id", + sessionId = "session-id", + selectedGuid = "guid", + ).toIntent() + + assertEquals(Constants.SIMPRINTS_CONFIRM_IDENTITY_INTENT, intent.action) + assertEquals("project-id", intent.getStringExtra(Constants.SIMPRINTS_PROJECT_ID)) + assertEquals("user-id", intent.getStringExtra(Constants.SIMPRINTS_USER_ID)) + assertEquals("session-id", intent.getStringExtra(Constants.SIMPRINTS_SESSION_ID)) + assertEquals("guid", intent.getStringExtra(Constants.SIMPRINTS_SELECTED_GUID)) + } + + @Test + fun `creates correct enrol last intent`() { + val intent = SimprintsRequest.EnrolLastBiometrics( + projectId = "project-id", + userId = "user-id", + moduleId = "module-id", + sessionId = "session-id", + metadata = Metadata().put("key", "value"), + ).toIntent() + + assertEquals(Constants.SIMPRINTS_ENROL_LAST_BIOMETRICS_INTENT, intent.action) + assertEquals("project-id", intent.getStringExtra(Constants.SIMPRINTS_PROJECT_ID)) + assertEquals("user-id", intent.getStringExtra(Constants.SIMPRINTS_USER_ID)) + assertEquals("module-id", intent.getStringExtra(Constants.SIMPRINTS_MODULE_ID)) + assertEquals("session-id", intent.getStringExtra(Constants.SIMPRINTS_SESSION_ID)) + assertEquals(METADATA_JSON, intent.getStringExtra(Constants.SIMPRINTS_METADATA)) + } + + @Test + fun `creates correct intent without meta data`() { + val intent = SimprintsRequest.Enrol( + projectId = "project-id", + userId = "user-id", + moduleId = "module-id", + ).toIntent() + + assertEquals(Constants.SIMPRINTS_ENROL_INTENT, intent.action) + assertEquals("project-id", intent.getStringExtra(Constants.SIMPRINTS_PROJECT_ID)) + assertEquals("user-id", intent.getStringExtra(Constants.SIMPRINTS_USER_ID)) + assertEquals("module-id", intent.getStringExtra(Constants.SIMPRINTS_MODULE_ID)) + assertNull(intent.getStringExtra(Constants.SIMPRINTS_METADATA)) + } + + companion object { + private const val METADATA_JSON = """{"key":"value"}""" + } +} diff --git a/src/test/java/com/simprints/libsimprints/contracts/SimprintsResponseTest.kt b/src/test/java/com/simprints/libsimprints/contracts/SimprintsResponseTest.kt new file mode 100644 index 0000000..717b393 --- /dev/null +++ b/src/test/java/com/simprints/libsimprints/contracts/SimprintsResponseTest.kt @@ -0,0 +1,104 @@ +package com.simprints.libsimprints.contracts + +import android.content.Intent +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.simprints.libsimprints.Constants +import com.simprints.libsimprints.Identification +import com.simprints.libsimprints.RefusalForm +import com.simprints.libsimprints.Registration +import com.simprints.libsimprints.Tier +import com.simprints.libsimprints.Verification +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNotNull +import org.junit.Assert.assertNull +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class SimprintsResponseTest { + + @Test + fun `correctly parses null intent`() { + val intent: Intent? = null + val result = SimprintsResponse.fromIntent(intent, Constants.SIMPRINTS_OK) + + assertEquals(Constants.SIMPRINTS_CANCELLED, result.resultCode) + } + + @Test + fun `correctly parses empty intent`() { + val intent: Intent? = null + val result = SimprintsResponse.fromIntent(intent, Constants.SIMPRINTS_OK) + + assertEquals(Constants.SIMPRINTS_CANCELLED, result.resultCode) + } + + @Test + fun `correctly parses error result intent`() { + val intent = Intent() + // This should be ignored in final data + .putExtra(Constants.SIMPRINTS_REFUSAL_FORM, RefusalForm("reason", "action")) + val result = SimprintsResponse.fromIntent(intent, Constants.SIMPRINTS_UNEXPECTED_ERROR) + + assertEquals(Constants.SIMPRINTS_UNEXPECTED_ERROR, result.resultCode) + assertNull(result.refusal) + assertNull(result.registration) + assertNull(result.identifications) + assertNull(result.verification) + } + + @Test + fun `correctly parses refusal intent`() { + val intent = Intent() + .putExtra(Constants.SIMPRINTS_REFUSAL_FORM, RefusalForm("reason", "action")) + val result = SimprintsResponse.fromIntent(intent, Constants.SIMPRINTS_OK) + + assertEquals(Constants.SIMPRINTS_OK, result.resultCode) + assertNotNull(result.refusal) + assertNull(result.registration) + assertNull(result.identifications) + assertNull(result.verification) + } + + @Test + fun `correctly parses enrolment intent`() { + val intent = Intent() + .putExtra(Constants.SIMPRINTS_REGISTRATION, Registration("guid")) + val result = SimprintsResponse.fromIntent(intent, Constants.SIMPRINTS_OK) + + assertEquals(Constants.SIMPRINTS_OK, result.resultCode) + assertNull(result.refusal) + assertNotNull(result.registration) + assertNull(result.identifications) + assertNull(result.verification) + } + + @Test + fun `correctly parses identification intent`() { + val intent = Intent() + .putExtra( + Constants.SIMPRINTS_IDENTIFICATIONS, + arrayListOf(Identification("guid", 42, Tier.TIER_1)) + ) + val result = SimprintsResponse.fromIntent(intent, Constants.SIMPRINTS_OK) + + assertEquals(Constants.SIMPRINTS_OK, result.resultCode) + assertNull(result.refusal) + assertNull(result.registration) + assertNotNull(result.identifications) + assertNull(result.verification) + } + + @Test + fun `correctly parses verification intent`() { + val intent = Intent() + .putExtra(Constants.SIMPRINTS_VERIFICATION, Verification(42, Tier.TIER_1, "guid")) + val result = SimprintsResponse.fromIntent(intent, Constants.SIMPRINTS_OK) + + assertEquals(Constants.SIMPRINTS_OK, result.resultCode) + assertNull(result.refusal) + assertNull(result.registration) + assertNull(result.identifications) + assertNotNull(result.verification) + } +} diff --git a/src/test/java/com/simprints/libsimprints/regression/JavaRegressionTests.java b/src/test/java/com/simprints/libsimprints/regression/JavaRegressionTests.java index e3a0ea5..359b9ea 100644 --- a/src/test/java/com/simprints/libsimprints/regression/JavaRegressionTests.java +++ b/src/test/java/com/simprints/libsimprints/regression/JavaRegressionTests.java @@ -8,7 +8,6 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import com.simprints.libsimprints.Constants; -import com.simprints.libsimprints.FingerIdentifier; import com.simprints.libsimprints.Identification; import com.simprints.libsimprints.Metadata; import com.simprints.libsimprints.RefusalForm; @@ -202,8 +201,6 @@ public void enrolLastWithMetaDataSetUp() { @Test public void enrolmentResultHandling() { Registration registration = new Registration("guid-id"); - registration.setTemplate(FingerIdentifier.LEFT_3RD_FINGER, new byte[]{3, 4, 5}); - registration.setTemplate(FingerIdentifier.RIGHT_3RD_FINGER, new byte[]{1, 2, 3}); Intent intent = createIntentWithExtra(Constants.SIMPRINTS_REGISTRATION, registration); diff --git a/src/test/java/com/simprints/libsimprints/regression/KotlinRegressionTests.kt b/src/test/java/com/simprints/libsimprints/regression/KotlinRegressionTests.kt index f15acbb..064a135 100644 --- a/src/test/java/com/simprints/libsimprints/regression/KotlinRegressionTests.kt +++ b/src/test/java/com/simprints/libsimprints/regression/KotlinRegressionTests.kt @@ -178,10 +178,7 @@ class KotlinRegressionTests { @Test fun enrolmentResultHandling() { - val registration = Registration("case-id").apply { - setTemplate(FingerIdentifier.LEFT_3RD_FINGER, byteArrayOf(1, 2, 3)) - setTemplate(FingerIdentifier.RIGHT_3RD_FINGER, byteArrayOf(4, 5, 6)) - } + val registration = Registration("case-id") val intent = Intent().putExtras(Bundle().apply { putParcelable(Constants.SIMPRINTS_REGISTRATION, registration) })