eSign PDFs with a Certificate on Android

This guide shows how Electronic Signatures and Digital Signatures can be used together.

To combine using the Electronic Signatures signing UI with digitally signing a document using a certificate, your activity needs to implement two interfaces: an OnSignaturePickedListener, and a DocumentSigningListener. The OnSignaturePickedListener will allow you to override onSignaturePicked, which can then be used to apply the created signature annotation to a digital signature. The DocumentSigningListener will enable you to access the signed document once it has been saved, in case you need to display it.

It could look something like this:

class MyActivity :
    PdfActivity(),
    OnSignaturePickedListener,
    DocumentSigningListener {

    private var signatureFormFieldName: String? = null

    override fun onSignaturePicked(signature: Signature) {
        val document = document ?: return
        // Signature form name can be obtained from an `addOnFormElementClickedListener`.
        val signatureFormFieldName = this.signatureFormFieldName ?: return

        val formField = document.formProvider.getFormFieldWithFullyQualifiedName(signatureFormFieldName)

        // The signature object provides convenient conversion to ink or stamp annotation.
        val signatureAnnotation: Annotation = when (signature.annotationType) {
            AnnotationType.INK -> signature.toInkAnnotation(
                document,
                formField.formElement.pageIndex,
                formField.formElement.boundingBox)
            AnnotationType.STAMP -> signature.toStampAnnotation(
                document,
                formField.formElement.pageIndex,
                formField.formElement.boundingBox)
            else -> throw IllegalStateException("Unhandled Signature type. Neither Ink, nor Stamp.")
        }

        // Add the annotation to the document. This step is required so we can render the signature
        // to pass the render to the `SignatureAppearance`.
        document.annotationProvider.addAnnotationToPage(signatureAnnotation)

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

        // Now that we've made the bitmap, we can remove the annotation from the document.
        document.annotationProvider.removeAnnotationFromPage(signatureAnnotation)

        // Now sign the document with a certificate asset in the next function.
        signDocumentWithSignatureBitmap(formField.formElement as SignatureFormElement, signatureBitmap)
    }

    private fun signDocumentWithSignatureBitmap(formElement: SignatureFormElement, signatureBitmap: Bitmap) {
        // The signer is a named entity holding a certificate (usually a person) and has a display
        // name shown in the app.
        val signer = Pkcs12Signer(
            "John Appleseed",
            Uri.parse("file:///android_asset/JohnAppleseed.p12")
        )
        // We need to register the signer with the signature manager for signing to work.
        SignatureManager.addSigner("john_appleseed", signer)
        // Provide a password to the signer, which will be used to unlock its private key.
        if (signer is InteractiveSigner) {
            (signer as InteractiveSigner).unlockPrivateKeyWithPassword("password")
        }
        // Add the created signature to the appearance.
        val signatureAppearance = SignatureAppearance.Builder()
            .setShowWatermark(false)
            .setSignatureGraphic(SignatureAppearance.SignatureGraphic.fromBitmap(getImageUri(signatureBitmap)))
            .build()

        // Show the signer dialog that handles the signing process.
        SignatureSignerDialog.show(
            supportFragmentManager,
            SignatureSignerDialog.Options.Builder(document!!, formElement.formField, signer)
                .signatureAppearance(signatureAppearance)
                .build(),
            this
        )
    }

    override fun onDocumentSigned(signedDocumentUri: Uri) {
        // Replace the loaded document with the signed document.
        setDocumentFromUri(signedDocumentUri, null)
    }
}

You can see a working Catalog example of this code here.