---
title: "Electronic + Digital Signing"
canonical_url: "https://www.nutrient.io/guides/android/samples/electronic-digital-signing-kotlin/"
md_url: "https://www.nutrient.io/guides/android/samples/electronic-digital-signing-kotlin.md"
last_updated: "2026-05-15T19:10:04.916Z"
description: "Combine an electronic signature created with ElectronicSignatureDialog with a certificate-based digital signature."
---

# Electronic + Digital Signing

Combine an electronic signature created with ElectronicSignatureDialog with a certificate-based digital signature.

[Get Started](https://www.nutrient.io/sdk/android/getting-started.md)

[All Samples](https://www.nutrient.io/guides/android/samples.md)

[Download](https://www.nutrient.io/guides/android/downloads.md)

[Launch Demo](https://www.nutrient.io/demo/)

---

```kotlin

/*
 *   Copyright © 2018-2026 PSPDFKit GmbH. All rights reserved.
 *
 *   The PSPDFKit Sample applications are licensed with a modified BSD license.
 *   Please see License for details. This notice may not be removed from this file.
 */

package com.pspdfkit.catalog.examples.kotlin

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Bitmap
import android.net.Uri
import android.os.Bundle
import android.widget.Toast
import androidx.core.graphics.createBitmap
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentOnAttachListener
import com.pspdfkit.catalog.R
import com.pspdfkit.catalog.SdkExample
import com.pspdfkit.catalog.tasks.ExtractAssetTask.extract
import com.pspdfkit.configuration.activity.PdfActivityConfiguration
import com.pspdfkit.forms.FormType
import com.pspdfkit.forms.SignatureFormElement
import com.pspdfkit.signatures.DigitalSignatureMetadata
import com.pspdfkit.signatures.Signature
import com.pspdfkit.signatures.SignatureAppearance
import com.pspdfkit.signatures.SignatureGraphic
import com.pspdfkit.signatures.SignerOptions
import com.pspdfkit.signatures.SigningManager
import com.pspdfkit.signatures.getPrivateKeyEntryFromP12Stream
import com.pspdfkit.signatures.getX509Certificates
import com.pspdfkit.signatures.listeners.OnSignaturePickedListener
import com.pspdfkit.ui.PdfActivity
import com.pspdfkit.ui.PdfActivityIntentBuilder
import com.pspdfkit.ui.PdfFragment
import com.pspdfkit.ui.signatures.ElectronicSignatureFragment
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import kotlinx.coroutines.runBlocking
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.security.GeneralSecurityException
import java.security.KeyStore

/**
 * Showcases how to combine a created signature annotation using the [ElectronicSignatureFragment] with digitally signing
 * the document using a certificate.
 *
 * See guide: https://nutrient.io/guides/android/signatures/using-electronic-signatures-and-digital-signatures-together/
 */
class CombineElectronicSignaturesWithDigitalSigningExample(context: Context) :
    SdkExample(
        context,
        R.string.CombineElectronicSignaturesWithDigitalSigningExampleTitle,
        R.string.CombineElectronicSignaturesWithDigitalSigningExampleDescription,
    ) {
    override fun launchExample(context: Context, configuration: PdfActivityConfiguration.Builder) {
        // The form field for signing is on page with index 16.
        configuration.page(16)

        // Extract the document from the assets.
        extract(WELCOME_DOC, title, context) { documentFile ->
            val intent =
                PdfActivityIntentBuilder.fromUri(context, Uri.fromFile(documentFile)).configuration(configuration.build()).activityClass(CombineElectronicSignaturesWithDigitalSigningActivity::class).build()

            // Start the CombineElectronicSignaturesWithDigitalSigningActivity showing the demo document.
            context.startActivity(intent)
        }
    }
}

/**
 * Shows how to implement a signature picked listener and document signing listener in order to create a signature and sign with the
 * created signature render.
 */
class CombineElectronicSignaturesWithDigitalSigningActivity :
    PdfActivity(),
    OnSignaturePickedListener,
    FragmentOnAttachListener {
    /** Name of the previously clicked signature form field (if any). Used to access it after a configuration change.  */
    private var signatureFormFieldName: String? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        supportFragmentManager.addFragmentOnAttachListener(this)

        // In case this activity is being recreated (e.g. during a configuration change), reattach
        // the activity as listener to the existing dialog. Calling restore() is safe, and won't do
        // anything in case the dialog isn't currently shown.
        ElectronicSignatureFragment.restore(supportFragmentManager, this)

        // Also restore information about any previously clicked signature for element. We'll use
        // this when adding an ink annotation later.
        if (savedInstanceState!= null) {
            signatureFormFieldName = savedInstanceState.getString(STATE_FORM_FIELD_NAME, null)
        }
    }

    /**
     * Intercept clicks on form elements so we can customize showing the signature picker.
     *
     * @param fragmentManager FragmentManager the fragment is now attached to. This will
     * be the same FragmentManager that is returned by
     * [Fragment.getParentFragmentManager].
     * @param fragment Fragment that just received a callback to [Fragment.onAttach]
     */
    override fun onAttachFragment(fragmentManager: FragmentManager, fragment: Fragment) {
        if (fragment is PdfFragment) {
            fragment.addOnFormElementClickedListener { formElement ->
                when (formElement.type) {
                    FormType.SIGNATURE -> {
                        val signatureFormElement = formElement as SignatureFormElement
                        if (!signatureFormElement.isSigned) {
                            onSignatureFormElementClicked(formElement)
                            // By returning true, you intercept the event and prevent Nutrient from showing the signature picker itself.
                            true
                        } else {
                            false
                        }
                    }

                    // This click event is not interesting for us. Return false to let Nutrient handle this event.
                    else -> {
                        false
                    }
                }
            }
        }
    }

    override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)

        // Make sure to persist information of any clicked signature form element (so it outlives configuration changes).
        outState.putString(STATE_FORM_FIELD_NAME, signatureFormFieldName)
    }

    /**
     * This callback handles showing the signature picker whenever an unsigned signature form element is clicked by the user.
     * We need to keep track of the form field name so we can retrieve it when digitally signing after the signature has been created
     * in the Electronic Signature Dialog. The dialog is opened by Nutrient automatically when the signature form element is clicked.
     * This behaviour can also be overridden here if required.
     */
    private fun onSignatureFormElementClicked(formElement: SignatureFormElement) {
        // Keep reference of the stored signature form element so we can later on access it.
        signatureFormFieldName = formElement.formField.name
        // We need to control the showing of the signature dialog in order to attach this as a listener.
        ElectronicSignatureFragment.show(supportFragmentManager, this)
    }

    /**
     * We are the signature creation listener, so this method is called by the signature picker,
     * whenever the user selects/creates a signature.
     */
    override fun onSignaturePicked(signature: Signature) {
        // You can add you custom signature handling logic here.
        //...
        digitallySignWithSignatureAnnotation(signature)
    }

    /**
     * This method is called by the signature picker, if the user dismissed the picker without selecting a signature.
     */
    override fun onDismiss() {
        signatureFormFieldName = null
    }

    /**
     * This is an example that shows how to use the created signature annotation as the digital signature stamp appearance.
     * Note we're only ignoring the return of getFormFieldWithFullyQualifiedNameAsync for the sake of the example.
     */
    @SuppressLint("CheckResult")
    private fun digitallySignWithSignatureAnnotation(signature: Signature) {
        val document = document?: return
        val signatureFormFieldName = this.signatureFormFieldName?: return

        // Retrieve the previously clicked signature form element. We do this asynchronously to not block the UI thread.
        document.formProvider.getFormFieldWithFullyQualifiedNameAsync(signatureFormFieldName).observeOn(AndroidSchedulers.mainThread()).subscribe { formField ->
                val clickedSignatureFormElement = formField.formElement as SignatureFormElement

                // We want to place the ink annotation on top of the signature field. We retrieve the widget annotation to access its position.
                val formFieldAnnotation = clickedSignatureFormElement.annotation

                // The signature object provides convenient conversion to ink or stamp annotation.
                val signatureAnnotation = signature.toAnnotation(document, formFieldAnnotation.pageIndex, formFieldAnnotation.boundingBox)

                // Add the annotation to the document. This step is required so we can render the signature
                // in order to pass the render to the `SignatureAppearance` when digitally signing in the
                // next step. We remove it once we have the render.
                // Here, we use the synchronous `AnnotationProvider` method as the next steps need to wait for this to complete.
                runBlocking { document.annotationProvider.addAnnotationToPage(signatureAnnotation) }

                val w = kotlin.math.abs(signatureAnnotation.boundingBox.width().toInt())
                val h = kotlin.math.abs(signatureAnnotation.boundingBox.height().toInt())
                val signatureBitmap = createBitmap(w, h, Bitmap.Config.ARGB_8888)
                signatureAnnotation.renderToBitmap(signatureBitmap)

                // Now we've made the bitmap, we can remove the annotation from the document, as it will appear on the digital
                // signature when we digitally sign the document.
                runBlocking { document.annotationProvider.removeAnnotationFromPage(signatureAnnotation) }

                // Now sign the document using the certificate added in the example class in `addCertificateAndSigner`.
                signDocumentWithSignatureBitmap(clickedSignatureFormElement, signatureBitmap)
            }
    }

    /**
     * Takes the created signature bitmap and digitally signs the document using the bitmap and the signing certificate initialised in
     * [CombineElectronicSignaturesWithDigitalSigningExample].
     */
    private fun signDocumentWithSignatureBitmap(formElement: SignatureFormElement, signatureBitmap: Bitmap) {
        val outputFile = File(filesDir, "signedDocument.pdf")

        val signatureAppearance =
            SignatureAppearance(
                showWatermark = false,
                signatureGraphic = SignatureGraphic.fromBitmap(getImageUri(signatureBitmap)),
            )

        val key = getPrivateKeyEntry(this)
        val signedDocumentUri = Uri.fromFile(outputFile)
        val signerOptions =
            SignerOptions.Builder(formElement.formField, signedDocumentUri).setSignatureMetadata(
                    DigitalSignatureMetadata(signatureAppearance = signatureAppearance),
                ).setPrivateKey(key.privateKey).setCertificates(key.getX509Certificates()).build()

        // handles the signing process
        SigningManager.signDocument(
            context = this,
            signerOptions = signerOptions,
            onFailure = { t ->
                Toast.makeText(this, t.localizedMessage, Toast.LENGTH_LONG).show()
            },
        ) {
            setDocumentFromUri(signedDocumentUri, null)
            // Signature page.
            pageIndex = 16
        }
    }

    /**
     * Stores the signature image to the FS in order to obtain a URI to pass to the [SignatureAppearance].
     */
    private fun getImageUri(bitmap: Bitmap): Uri {
        val imageFile = File(cacheDir, "signature.png")
        val fileStream = FileOutputStream(imageFile)
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, fileStream)
        fileStream.close()
        return Uri.fromFile(imageFile)
    }

    @Throws(IOException::class, GeneralSecurityException::class)
    private fun getPrivateKeyEntry(context: Context): KeyStore.PrivateKeyEntry {
        // Inside a p12 we have both the certificate (or certificate chain to the root CA) and private key used for signing.
        val keystoreFile = context.assets.open("digital-signatures/ExampleSigner.p12")
        return getPrivateKeyEntryFromP12Stream(keystoreFile, "test")
    }
}

private const val STATE_FORM_FIELD_NAME = "Example.FORM_FIELD_NAME"

```

This code sample is an example that illustrates how to use our SDK. Please adapt it to your specific use case.

---

## Related pages

- [Application Policy](/guides/android/samples/application-policy-kotlin.md)
- [Custom Form Highlight Color](/guides/android/samples/custom-form-highlight-color-java.md)
- [Custom Page Templates](/guides/android/samples/custom-page-templates-java.md)
- [Digital Signature (Basic)](/guides/android/samples/digital-signature-basic-kotlin.md)
- [Disabled Annotation Property](/guides/android/samples/disabled-annotation-property-java.md)
- [Image Document](/guides/android/samples/image-document-kotlin.md)
- [Compose Image Document](/guides/android/samples/compose-image-document-kotlin.md)
- [Inline Multimedia](/guides/android/samples/inline-multimedia-kotlin.md)
- [JavaScript Form Filling](/guides/android/samples/javascript-form-filling-kotlin.md)
- [Overlay Visibility](/guides/android/samples/overlay-visibility-kotlin.md)
- [PdfFragment](/guides/android/samples/pdffragment-kotlin.md)
- [Reader View](/guides/android/samples/reader-view-kotlin.md)
- [Playground](/guides/android/samples/playground-kotlin.md)
- [JavaScript Calculator](/guides/android/samples/javascript-calculator-kotlin.md)
- [Text Field Suggestions](/guides/android/samples/text-field-suggestions-kotlin.md)
- [Thumbnail Bar Modes](/guides/android/samples/thumbnail-bar-modes-kotlin.md)
- [Signature Storage Database](/guides/android/samples/signature-storage-database-kotlin.md)
- [Selection Customization](/guides/android/samples/selection-customization-java.md)
- [Password Protected PDF](/guides/android/samples/password-protected-pdf-kotlin.md)
- [Scientific Paper](/guides/android/samples/scientific-paper-kotlin.md)
- [Try Instant](/guides/android/samples/try-instant-kotlin.md)
- [Merge Documents](/guides/android/samples/merge-documents-kotlin.md)
- [Annotation Rendering](/guides/android/samples/annotation-rendering-kotlin.md)
- [Custom Data Provider](/guides/android/samples/custom-data-provider-kotlin.md)
- [Annotations with Transparency](/guides/android/samples/annotations-with-transparency-kotlin.md)
- [Annotation Flags](/guides/android/samples/annotation-flags-kotlin.md)
- [AI Assistant (Multiple Documents, ViewPager)](/guides/android/samples/ai-assistant-multiple-documents-viewpager-kotlin.md)
- [Custom Sharing Menu](/guides/android/samples/custom-sharing-menu-java.md)
- [Add LTV to Existing Signature](/guides/android/samples/add-ltv-to-existing-signature-kotlin.md)
- [Custom Toolbar Grouping](/guides/android/samples/custom-toolbar-grouping-java.md)
- [Custom Layout](/guides/android/samples/custom-layout-kotlin.md)
- [Custom ActionBar Actions](/guides/android/samples/custom-actionbar-actions-kotlin.md)
- [Custom Activity Toolbars](/guides/android/samples/custom-activity-toolbars-java.md)
- [Custom Note Hinter](/guides/android/samples/custom-note-hinter-kotlin.md)
- [Custom Main Toolbar](/guides/android/samples/custom-main-toolbar-kotlin.md)
- [Annotation Configuration](/guides/android/samples/annotation-configuration-kotlin.md)
- [Annotation Selection Styling](/guides/android/samples/annotation-selection-styling-kotlin.md)
- [Custom Search UI (Compose)](/guides/android/samples/custom-search-ui-compose-kotlin.md)
- [Document Switcher](/guides/android/samples/document-switcher-java.md)
- [File Annotation Creation](/guides/android/samples/file-annotation-creation-kotlin.md)
- [Dynamic Pages on Scroll](/guides/android/samples/dynamic-pages-on-scroll-kotlin.md)
- [Custom Activity Form Editing](/guides/android/samples/custom-activity-form-editing-java.md)
- [Custom Stamp Annotations](/guides/android/samples/custom-stamp-annotations-java.md)
- [Custom Outline Provider](/guides/android/samples/custom-outline-provider-kotlin.md)
- [Compose Navigation](/guides/android/samples/compose-navigation-kotlin.md)
- [Fragment Runtime Configuration](/guides/android/samples/fragment-runtime-configuration-kotlin.md)
- [Annotation Overlay](/guides/android/samples/annotation-overlay-java.md)
- [Instant Document JSON](/guides/android/samples/instant-document-json-kotlin.md)
- [DocumentView Composable](/guides/android/samples/documentview-composable-kotlin.md)
- [Form Creation](/guides/android/samples/form-creation-kotlin.md)
- [Document Download](/guides/android/samples/document-download-kotlin.md)
- [JavaScript Actions](/guides/android/samples/javascript-actions-kotlin.md)
- [Instant JSON Attachment](/guides/android/samples/instant-json-attachment-kotlin.md)
- [Digital Signature (Manual)](/guides/android/samples/digital-signature-manual-kotlin.md)
- [Digital Signature (Third-Party)](/guides/android/samples/digital-signature-third-party-kotlin.md)
- [Inline Search](/guides/android/samples/inline-search-java.md)
- [Form Filling](/guides/android/samples/form-filling-kotlin.md)
- [Form Click Intercept (Compose)](/guides/android/samples/form-click-intercept-compose-kotlin.md)
- [Document Sharing](/guides/android/samples/document-sharing-java.md)
- [Custom Download Dialog](/guides/android/samples/custom-download-dialog-java.md)
- [Download Progress](/guides/android/samples/download-progress-kotlin.md)
- [Popup Toolbar Customization](/guides/android/samples/popup-toolbar-customization-kotlin.md)
- [Custom Sharing Dialog](/guides/android/samples/custom-sharing-dialog-java.md)
- [PDF from Image](/guides/android/samples/pdf-from-image-kotlin.md)
- [Digital Signature (Two-Step)](/guides/android/samples/digital-signature-two-step-kotlin.md)
- [Remote URL](/guides/android/samples/remote-url-kotlin.md)
- [PdfUiFragment](/guides/android/samples/pdfuifragment-kotlin.md)
- [Runtime Configuration](/guides/android/samples/runtime-configuration-kotlin.md)
- [Sound Extraction](/guides/android/samples/sound-extraction-kotlin.md)
- [Document from Canvas](/guides/android/samples/document-from-canvas-kotlin.md)
- [Tabbed Documents](/guides/android/samples/tabbed-documents-kotlin.md)
- [Watermarks](/guides/android/samples/watermarks-kotlin.md)
- [Programmatic Zoom](/guides/android/samples/programmatic-zoom-kotlin.md)
- [Signature Parcelize](/guides/android/samples/signature-parcelize-kotlin.md)
- [OCR](/guides/android/samples/ocr-kotlin.md)
- [Vertical Scrollbar](/guides/android/samples/vertical-scrollbar-java.md)
- [Split View](/guides/android/samples/split-view-java.md)
- [XFDF Import/Export](/guides/android/samples/xfdf-import-export-kotlin.md)
- [UI View Modes](/guides/android/samples/ui-view-modes-kotlin.md)
- [LTV Signature](/guides/android/samples/ltv-signature-kotlin.md)
- [Bookmark Highlighting](/guides/android/samples/bookmark-highlighting-kotlin.md)
- [Custom Annotation Inspector](/guides/android/samples/custom-annotation-inspector-java.md)
- [Annotation Sidebar](/guides/android/samples/annotation-sidebar-kotlin.md)
- [AI Assistant (Single Document)](/guides/android/samples/ai-assistant-single-document-kotlin.md)
- [AI Assistant (Multiple Documents, Compose)](/guides/android/samples/ai-assistant-multiple-documents-compose-kotlin.md)
- [Document Comparison](/guides/android/samples/document-comparison-kotlin.md)
- [Document Processing](/guides/android/samples/document-processing-kotlin.md)
- [Custom Annotation Creation Toolbar](/guides/android/samples/custom-annotation-creation-toolbar-java.md)
- [Custom Electronic Signature](/guides/android/samples/custom-electronic-signature-java.md)
- [E-Learning](/guides/android/samples/e-learning-kotlin.md)
- [Generate PDF Report](/guides/android/samples/generate-pdf-report-kotlin.md)
- [Multimedia Annotations](/guides/android/samples/multimedia-annotations-kotlin.md)
- [Forms with JavaScript](/guides/android/samples/forms-with-javascript-kotlin.md)
- [External Document](/guides/android/samples/external-document-kotlin.md)
- [Overlay Views](/guides/android/samples/overlay-views-kotlin.md)
- [Kiosk Grid](/guides/android/samples/kiosk-grid-kotlin.md)
- [Search Indexing](/guides/android/samples/search-indexing-kotlin.md)
- [Annotation Creation](/guides/android/samples/annotation-creation-kotlin.md)
- [Filterable Thumbnail Grid](/guides/android/samples/filterable-thumbnail-grid-kotlin.md)
- [Tabbed Documents (Persistent)](/guides/android/samples/tabbed-documents-persistent-kotlin.md)
- [Measurement Tools](/guides/android/samples/measurement-tools-kotlin.md)
- [HTML-to-PDF Conversion](/guides/android/samples/html-to-pdf-conversion-kotlin.md)
- [AES Encrypted File](/guides/android/samples/aes-encrypted-file-java.md)
- [Construction Floor Plan](/guides/android/samples/construction-floor-plan-kotlin.md)
- [Hide and Reveal Areas](/guides/android/samples/hide-and-reveal-areas-kotlin.md)
- [Multiple Documents (Compose Pager)](/guides/android/samples/multiple-documents-compose-pager-kotlin.md)
- [Screen Reader](/guides/android/samples/screen-reader-java.md)
- [Custom Search UI (Views)](/guides/android/samples/custom-search-ui-views-java.md)

