How to Sign a PDF on Android with PSPDFKit's Signature Library
In this post, you’ll learn how to add electronic and digital signatures to a PDF in your Android application using PSPDFKit’s Android signature library.
This post will also cover the various types of signatures PSPDFKit facilitates. Additionally, it’ll include code examples of adding a signature programmatically and through PSPDFKit’s built-in user interface (UI).
PSPDFKit supports the following signature types:
-
Drawn eSignatures
-
Image eSignatures
-
Typed eSignatures
-
Digital Signatures
PSPDFKit also supports eSigning with a certificate.
Requirements to Get Started
To get started, you’ll need:
Getting Started and Integrating the PSPDFKit Library
The next few sections will walk you through the getting started process.
Creating a New Project
-
To create a new project for your application, open Android Studio and select New Project. Or, if another project is open, choose File > New > New Project…
-
Choose the correct template for your project. For this example, you’ll use Empty Activity.
-
When prompted, choose your app name (PSPDFKit Demo) and set the Save location and Language to your choice. Set the Minimum SDK to API 21.
-
Click Finish to let Android Studio create your project at your preferred save location.
Adding PSPDFKit to Your Project
-
Add the PSPDFKit Maven repository in
settings.gradle
, which is located at the root of your project:
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
maven {
url 'https://my.nutrient.io/maven/'
}
}
}
dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { google() mavenCentral() maven { url = uri("https://my.nutrient.io/maven") } } }
-
Add the PSPDFKit dependency in
app/build.gradle
:
dependencies {
implementation 'com.pspdfkit:pspdfkit:8.4.0'
}
dependencies {
implementation("com.pspdfkit:pspdfkit:8.4.0")
}
Configuring Your Build
PSPDFKit is supported on Android devices running API level 21 and newer and targeting the latest stable Android version 12 (API 31). Furthermore, PSPDFKit requires apps to enable Java 8 language features to build:
android { compileSdk 31 buildToolsVersion '30.0.3' defaultConfig { applicationId 'com.example.app' minSdk 21 targetSdk 31 } compileOptions { sourceCompatibility JavaVersion.VERSION_17 targetCompatibility JavaVersion.VERSION_17 } }
android { compileSdk = 31 buildToolsVersion = "30.0.3" defaultConfig { applicationId = "com.example.app" minSdk = 21 targetSdk = 31 } compileOptions { sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 } }
Adding an Android Signature Pad to Accept Signatures
To enable users to sign a document digitally, the document needs to have at least one signature pad. This is a reserved area within a document for digital and electronic signatures.
If your test document doesn’t contain a signature form field, you can create one using PSPDFKit. This is done by defining the index page and the annotation bounding box that will contain the signature form element using the code below:
private fun createSignatureFormField( pageIndex: Int, left: Float, top: Float, right: Float, bottom: Float, formFieldId: String ) { val formConfigurationRect = RectF( left, top, right, bottom ) val signatureFormConfiguration = SignatureFormConfiguration.Builder(pageIndex, formConfigurationRect) .build() val signatureFormField = document.formProvider.addFormElementToPage(formFieldId, signatureFormConfiguration) }
Adding Electronic Signatures Programmatically in Android
Electronic signatures in PSPDFKit are sometimes referred to as signature annotations because they’re modeled using annotations.
To enable eSignature functionality, your license must include either the Annotations component or the Electronic Signatures component.
Signatures can be ink or image annotations with the isSignature
property set to true
. To programmatically create signatures, you can create instances of InkAnnotation
or StampAnnotation
, call setIsSignature(true)
on them, and add them to a document via PdfFragment#addAnnotationToPage()
.
-
To create an ink signature:
val pdfFragment: PdfFragment = ... // Create the ink annotation. val annotation = InkAnnotation(pageIndex) // Set the line color and width. annotation.color = Color.RED annotation.lineWidth = 3f // Set the stroke data. For example, this would be loaded from user input on another device. // This example code is just hardcoding a stroke with three points. val line = listOf( PointF(100f, 100f), PointF(150f, 150f), PointF(200f, 100f) ) annotation.lines = listOf(line) // Mark this ink annotation as a signature. annotation.setIsSignature(true) // Add it to the page. pdfFragment.addAnnotationToPage(annotation, false)
-
To create an image signature:
val pdfFragment: PdfFragment = ... val bitmap = BitmapFactory.decodeFile("my-signature.png") // Create the image annotation. val annotation = StampAnnotation(pageIndex, RectF(50f, 440.0f, 500f, 0.0f), bitmap) // Mark this image annotation as a signature. annotation.setIsSignature(true) // Add it to the page. pdfFragment.addAnnotationToPage(annotation, false)
Adding Electronic Signatures through the UI
There are two ways to add electronic signatures via the UI.
-
With a signature form field
You can bring up the signature creation modal view by tapping a signature form field in the document if you’re using PSPDFKit with forms.
-
Without a signature form field
If your license includes Annotations, the signature tool can be found with the other annotation tools, as shown in image below.
If this isn’t the case, you’ll only be able to create, move, resize, and delete signature annotations, but not modify them.
The signature tool can also be added using forceSignatureButtonPositionInMainToolbar
in the PdfActivityConfiguration.Builder
, like so:
The signature creation modal view offers the options for signatures outlined below.
-
Draw
Drawn eSignatures are similar to paper-based signatures, and they’re especially suited to using a touchscreen and stylus.
Drawn eSignatures let the user choose between the following inks:
-
Black — #000000
-
Palatinate Blue — #4636e3
-
Blue (Crayola) — #2972ff
-
Image
The image option lets the user snap a picture or scan a signature on paper. It also allows users to select an existing image from their gallery.
-
Typed
The type option allows users to enter their name and select a signature style. It’s compatible with screen readers such as VoiceOver, TalkBack, NVDA, and JAWS, as well as other accessibility technologies like Switch Control on macOS and iOS.
Like drawn eSignatures, typed eSignatures also let the user choose between three inks:
-
Black — #000000
-
Palatinate Blue — #4636e3
-
Blue (Crayola) — #2972ff
Adding Digital Signatures to PDFs in Android
Digital signatures are signed with a certificate, which we cover in depth in our generating a digital certificate guide. For demonstration purposes, this next section uses a self-signed certificate.
Download the test certificate and place it in the
android_assets
folder.
Since you’re using a self-signed certificate, you need to add it to a trusted certificate store for it to validate. Since PSPDFKit and other readers (like Acrobat) will warn when using self-signed certificates, your app should use a CA-issued certificate instead.
To add a digital signature, do the following:
private fun addJohnAppleseedCertificateToTrustedCertificates(context: Context) { try { val keystoreFile = context.assets.open("JohnAppleseed.p12") // Inside a p12, we have both the certificate and private key used for signing. We just // need the certificate here. Proper signatures should have a root CA-approved // certificate, making this step unnecessary. val key = SignatureManager.loadPrivateKeyPairFromStream(keystoreFile, "test", null, null) if (key.certificate.type == "X.509") { SignatureManager.addTrustedCertificate((key.certificate as X509Certificate)) } } catch (e: Exception) { // Handle exception here. } }
After adding the self-signed certificate to the trusted certificate store, you can sign the document like so:
private fun signDocument(context: Context, assetName: String): Uri { val outputFile = File(context.filesDir, "signedDocument.pdf") // 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") ) // Provide a password to the signer, which will be used to unlock its private key. signer.unlockPrivateKeyWithPassword("test") val unsignedDocument = PdfDocumentLoader.openDocument(context, DocumentSource(AssetDataProvider(assetName))) val signatureFormFields = unsignedDocument.documentSignatureInfo.signatureFormFields check(signatureFormFields.isNotEmpty()) { "No signature form element found in document '$assetName'" } val signerOptions = SignerOptions.Builder(signatureFormFields[0], FileOutputStream(outputFile)).build() signer.signFormFieldAsync(signerOptions).blockingAwait() return Uri.fromFile(outputFile) }
The above function signs and returns a URI to the document. You can load and show the document with the following:
val intent = PdfActivityIntentBuilder.fromUri(context, signedDocument)
.configuration(configuration.build())
.build()
context.startActivity(intent)
Expanding the Capabilities of Your Android App with PSPDFKit
PSPDFKit also supports the following:
They’re beyond the scope of this post, but you can read more if you’re interested.
Conclusion
In this post, you learned how to add electronic and digital signatures to a document using the PSPDFKit library on Android. You also had an overview of the various types of electronic signatures supported by PSPDFKit. If you hit any snags, don’t hesitate to reach out to our support team for help.
At PSPDFKit, we offer a commercial, feature-rich, and completely customizable Android PDF library that’s easy to integrate and comes with well-documented APIs to handle advanced use cases. Try it for free, or visit our demo to see it in action.