Skip to content

smart‐id‐lib

Boriss Melikjan edited this page Sep 9, 2025 · 1 revision

Android service for signing with Smart-ID.

Example usage of the SmartSignService

suspend fun performSmartIdWorkRequest(
    activity: Activity,
    context: Context,
    displayMessage: String,
    container: SignedContainer?,
    personalCode: String,
    country: Int,
    roleData: RoleData?,
) {
    activity.requestedOrientation = activity.resources.configuration.orientation
    resetValues()
    val configurationProvider = configurationRepository.getConfiguration()
    val uuid = dataStore.getSettingsUUID()
    val proxySetting: ProxySetting = dataStore.getProxySetting()
    val manualProxySettings: ManualProxy = dataStore.getManualProxySettings()

    val request: SmartCreateSignatureRequest =
        SmartCreateSignatureRequestHelper
            .create(
                container,
                uuid,
                configurationProvider?.sidV2RestUrl,
                configurationProvider?.sidV2SkRestUrl,
                countries[country],
                personalCode,
                displayMessage,
            )
    val certBundle = ArrayList(configurationProvider?.certBundle ?: emptyList())
    withContext(Main) {
        smartSignService.errorState.observeForever {
            if (it != null) {
                _errorState.postValue(it)
            }
        }
        smartSignService.challenge.observeForever { challenge ->
            if (challenge != null) {
                _challenge.postValue(challenge)

                if (!PowerUtil.isPowerSavingMode(context)) {
                    debugLog(logTag, "Creating notification channel")

                    NotificationUtil.createNotificationChannel(
                        context,
                        NOTIFICATION_CHANNEL,
                        context.getString(R.string.signature_update_signature_add_method_smart_id),
                    )
                }
                val challengeTitle: String = context.getString(R.string.smart_id_challenge)
                val notification: Notification? =
                    NotificationUtil.createNotification(
                        context,
                        NOTIFICATION_CHANNEL,
                        R.mipmap.ic_launcher,
                        challengeTitle,
                        challenge,
                        NotificationCompat.PRIORITY_HIGH,
                        false,
                    )
                try {
                    if (notification != null) {
                        sendNotification(context, challenge, notification)
                    }
                } catch (nfe: NumberFormatException) {
                    errorLog(logTag, "Unable to send notification", nfe)
                }
            }
        }
        smartSignService.selectDevice.observeForever {
            if (it != null) {
                _selectDevice.postValue(it)
            }
        }
        smartSignService.status.observeForever { status ->
            if (status != null) {
                _status.postValue(status)
                if (status != SessionStatusResponseProcessStatus.OK) {
                    if (status != SessionStatusResponseProcessStatus.USER_CANCELLED) {
                        setErrorState(context, status)
                    } else {
                        CoroutineScope(Main).launch {
                            val containerSignatures = container?.getSignatures(Main)
                            val signatureInterface =
                                if (containerSignatures?.isEmpty() == true) {
                                    null
                                } else {
                                    containerSignatures
                                        ?.lastOrNull {
                                            it.validator.status == ValidatorInterface.Status.Invalid ||
                                                it.validator.status == ValidatorInterface.Status.Unknown
                                        }
                                }
                            signatureInterface?.let {
                                try {
                                    container?.removeSignature(it)
                                } catch (e: Exception) {
                                    debugLog(
                                        logTag,
                                        "Unable to remove Smart-ID signature after " +
                                            "cancelling from device: ${e.localizedMessage}",
                                        e,
                                    )
                                }
                            }
                            _signedContainer.postValue(container)
                        }
                    }
                }
            }
        }
        smartSignService.response.observeForever {
            when (it?.status) {
                SessionStatusResponseProcessStatus.OK -> {
                    CoroutineScope(Main).launch {
                        _status.postValue(it.status)
                        _signedContainer.postValue(container)
                    }
                }

                else -> {
                    if (it != null) {
                        _status.postValue(it.status)
                        setErrorState(context, it.status)
                    }
                }
            }
        }
    }
    smartSignService.resetValues()
    if (container != null) {
        smartSignService.processSmartIdRequest(
            context = context,
            signedContainer = container,
            request = request,
            roleDataRequest = roleData,
            proxySetting = proxySetting,
            manualProxySettings = manualProxySettings,
            certificateBundle = certBundle,
            accessTokenPath = Objects.requireNonNull(Conf.instance()).PKCS12Cert(),
            accessTokenPass = Objects.requireNonNull(Conf.instance()).PKCS12Pass(),
        )
    } else {
        CoroutineScope(Main).launch {
            _status.postValue(SessionStatusResponseProcessStatus.GENERAL_ERROR)
            _errorState.postValue(context.getString(R.string.error_general_client))
            errorLog(logTag, "Unable to get container value. Container is 'null'")
        }
    }

    withContext(Main) {
        smartSignService.errorState.removeObserver {}
        smartSignService.challenge.removeObserver {}
        smartSignService.status.removeObserver {}
        smartSignService.response.removeObserver {}
        activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
    }
}
Details
// Get configurationProvider
val configurationProvider = configurationRepository.getConfiguration()
// Set display message
val displayMessage = "Sign with app"
// Prepare the request object
// Container to be signed, RP UUID, Smart-ID REST url, SID-SK-REST url, user's country, user's personal code and message to display are needed
val request: SmartCreateSignatureRequest =
SmartCreateSignatureRequestHelper
    .create(
        container,
        uuid,
        configurationProvider?.sidV2RestUrl,
        configurationProvider?.sidV2SkRestUrl,
        countries[country],
        personalCode,
        displayMessage,
    )
// Process the Smart-ID service
smartSignService.processSmartIdRequest(
    context = context,
    signedContainer = container,
    request = request,
    roleDataRequest = roleData,
    proxySetting = proxySetting,
    manualProxySettings = manualProxySettings,
    certificateBundle = certBundle,
    accessTokenPath = Objects.requireNonNull(Conf.instance()).PKCS12Cert(),
    accessTokenPass = Objects.requireNonNull(Conf.instance()).PKCS12Pass(),
)

Clone this wiki locally