Overview
The IgniSign Android SDK allows you to integrate electronic signatures directly into your Android applications, providing a seamless experience for your users. The SDK handles the complexities of document presentation, identity verification, signature capture, and legal compliance.
Integration Flow
The general flow for integrating the signature interface into Android applications is as follows:
Installation
To get started with the IgniSign Android SDK, add it to your project by following these steps:
Add the IgniSign Maven repository to your project's build.gradle
file:
// In your project-level build.gradle file
allprojects {
repositories {
google()
mavenCentral()
// Add the IgniSign Maven repository
maven {
url "https://maven.ignisign.io/repository/maven-public/"
}
}
}
Or in your settings.gradle
file if you're using the new Android Studio project structure:
// In your settings.gradle file
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
// Add the IgniSign Maven repository
maven {
url "https://maven.ignisign.io/repository/maven-public/"
}
}
}
Add the IgniSign Android SDK dependency to your app's build.gradle
file:
// In your app-level build.gradle file
dependencies {
// Other dependencies
implementation 'io.ignisign:ignisign-android:1.0.0' // Replace with the latest version
}
The SDK requires Java 8 features. Add the following to your app's build.gradle
file:
// In your app-level build.gradle file
android {
// Other configurations
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
}
The SDK requires internet access. Add the following permission to your AndroidManifest.xml
file:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="your.package.name">
<uses-permission android:name="android.permission.INTERNET" />
<!-- Rest of your manifest -->
</manifest>
Implementation Steps
Basic Implementation
Here's a step-by-step guide to implementing IgniSign in your Android application:
Create a layout file for your signature activity:
<!-- activity_signature.xml -->
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".SignatureActivity">
<com.ignisign.IgnisignAndroid
android:id="@+id/ignisignView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Create an activity to handle the signature process:
package com.yourcompany.yourapp
import android.os.Bundle
import android.util.Log
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.ignisign.IgnisignAndroid
import com.ignisign.ISessionCallbacks
import com.ignisign.IgnisignSignatureSessionDimensions
import com.ignisign.IgnisignJSSignatureSessionsDisplayOptions
import com.ignisign.IgnisignInitParams
class SignatureActivity : AppCompatActivity(), ISessionCallbacks {
private lateinit var ignisignView: IgnisignAndroid
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_signature)
// Get the signature request and signer IDs from your backend
val signatureRequestId = intent.getStringExtra("signatureRequestId")
val signerId = intent.getStringExtra("signerId")
val signatureSessionToken = intent.getStringExtra("signatureSessionToken")
val signerAuthSecret = intent.getStringExtra("signerAuthSecret") // Required for embedded integration
// Initialize the IgniSign view
ignisignView = findViewById(R.id.ignisignView)
// Set up the signature session dimensions
val dimensions = IgnisignSignatureSessionDimensions(
width = "100%",
height = "100%"
)
// Set up display options
val displayOptions = IgnisignJSSignatureSessionsDisplayOptions(
showTitle = false,
showDescription = false,
darkMode = false,
forceShowDocumentInformations = false
)
// Set up initialization parameters
val initParams = IgnisignInitParams(
signatureRequestId = signatureRequestId!!,
signerId = signerId!!,
signatureSessionToken = signatureSessionToken!!, // Session token from your backend
signerAuthSecret = signerAuthSecret!!, // Required for embedded integration
sessionCallbacks = this,
closeOnFinish = true,
dimensions = dimensions,
displayOptions = displayOptions
)
// Initialize the signature session
ignisignView.setValues(initParams)
ignisignView.initSignatureSession()
}
// Implement ISessionCallbacks
override fun onSessionComplete(data: String) {
// Handle successful signature completion
Log.d(TAG, "Signature completed: $data")
Toast.makeText(this, "Signature completed successfully", Toast.LENGTH_SHORT).show()
finish()
}
override fun onSessionError(error: String) {
// Handle signature error
Log.e(TAG, "Signature error: $error")
Toast.makeText(this, "Error: $error", Toast.LENGTH_SHORT).show()
}
override fun onSessionCanceled(reason: String) {
// Handle signature cancellation
Log.d(TAG, "Signature canceled: $reason")
Toast.makeText(this, "Signature canceled: $reason", Toast.LENGTH_SHORT).show()
finish()
}
override fun onSessionProgress(progress: String) {
// Handle signature progress updates
Log.d(TAG, "Progress: $progress")
}
companion object {
private const val TAG = "SignatureActivity"
}
}
Start the signature process by launching the SignatureActivity from another part of your application:
// In your document list activity or fragment
import android.content.Intent
// ...
private fun startSignatureProcess(signatureRequestId: String, signerId: String) {
val intent = Intent(this, SignatureActivity::class.java).apply {
putExtra("signatureRequestId", signatureRequestId)
putExtra("signerId", signerId)
}
startActivity(intent)
}
Advanced Implementation
For more flexible integration, you can use a fragment instead of an activity:
package com.yourcompany.yourapp
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.fragment.app.Fragment
import com.ignisign.IgnisignAndroid
import com.ignisign.ISessionCallbacks
import com.ignisign.IgnisignSignatureSessionDimensions
import com.ignisign.IgnisignJSSignatureSessionsDisplayOptions
import com.ignisign.IgnisignInitParams
class SignatureFragment : Fragment(), ISessionCallbacks {
private lateinit var ignisignView: IgnisignAndroid
private var signatureRequestId: String? = null
private var signerId: String? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
signatureRequestId = it.getString(ARG_SIGNATURE_REQUEST_ID)
signerId = it.getString(ARG_SIGNER_ID)
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_signature, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// Check required parameters
if (signatureRequestId == null || signerId == null) {
throw IllegalArgumentException("signatureRequestId and signerId are required")
}
// Initialize the IgniSign view
ignisignView = view.findViewById(R.id.ignisignView)
// Configure session dimensions
val dimensions = IgnisignSignatureSessionDimensions(
width = "100%",
height = "100%"
)
// Configure display options
val displayOptions = IgnisignJSSignatureSessionsDisplayOptions(
hideTitle = true
)
// Set initialization parameters
val initParams = IgnisignInitParams(
signatureRequestId = signatureRequestId!!,
signerId = signerId!!,
dimensions = dimensions,
displayOptions = displayOptions
)
// Set values and initialize session
ignisignView.setValues(initParams)
ignisignView.initSignatureSession()
}
// Implement ISessionCallbacks
override fun onSessionComplete(data: String) {
// Handle successful signature completion
Log.d(TAG, "Signature completed: $data")
Toast.makeText(context, "Signature completed successfully", Toast.LENGTH_SHORT).show()
// Notify the parent activity/fragment
(activity as? SignatureListener)?.onSignatureComplete(data)
}
override fun onSessionError(error: String) {
// Handle signature error
Log.e(TAG, "Signature error: $error")
Toast.makeText(context, "Error: $error", Toast.LENGTH_SHORT).show()
// Notify the parent activity/fragment
(activity as? SignatureListener)?.onSignatureError(error)
}
override fun onSessionCanceled(reason: String) {
// Handle signature cancellation
Log.d(TAG, "Signature canceled: $reason")
Toast.makeText(context, "Signature canceled: $reason", Toast.LENGTH_SHORT).show()
// Notify the parent activity/fragment
(activity as? SignatureListener)?.onSignatureCanceled(reason)
}
override fun onSessionProgress(progress: String) {
// Handle signature progress updates
Log.d(TAG, "Progress: $progress")
// Notify the parent activity/fragment
(activity as? SignatureListener)?.onSignatureProgress(progress)
}
// Interface for communication with the parent activity/fragment
interface SignatureListener {
fun onSignatureComplete(data: String)
fun onSignatureError(error: String)
fun onSignatureCanceled(reason: String)
fun onSignatureProgress(progress: String)
}
companion object {
private const val TAG = "SignatureFragment"
private const val ARG_SIGNATURE_REQUEST_ID = "signatureRequestId"
private const val ARG_SIGNER_ID = "signerId"
@JvmStatic
fun newInstance(signatureRequestId: String, signerId: String) =
SignatureFragment().apply {
arguments = Bundle().apply {
putString(ARG_SIGNATURE_REQUEST_ID, signatureRequestId)
putString(ARG_SIGNER_ID, signerId)
}
}
}
}
You can customize the appearance and behavior of the signature interface:
// Create display options with advanced customizations
val displayOptions = IgnisignJSSignatureSessionsDisplayOptions(
hideTitle = true, // Hide the title bar
darkMode = true, // Enable dark mode
hideProgressBar = false, // Show progress bar
customCSS = "body { background-color: #f5f5f5; }", // Custom CSS
logo = "https://your-company.com/logo.png", // Custom logo
primaryColor = "#007bff" // Custom primary color
)
// Create initialization parameters with the custom display options
val initParams = IgnisignInitParams(
signatureRequestId = signatureRequestId,
signerId = signerId,
dimensions = dimensions,
displayOptions = displayOptions,
lang = "fr" // Set language to French
)
Implement comprehensive error handling to provide a better user experience:
override fun onSessionError(error: String) {
try {
// Parse the error JSON if applicable
val errorObj = JSONObject(error)
val errorCode = errorObj.optString("code", "UNKNOWN_ERROR")
val errorMessage = errorObj.optString("message", "An unknown error occurred")
// Handle specific error codes
when (errorCode) {
"NETWORK_ERROR" -> {
// Handle network connectivity issues
showNetworkErrorDialog()
}
"AUTH_ERROR" -> {
// Handle authentication errors
showAuthErrorDialog()
}
"SESSION_EXPIRED" -> {
// Handle session expiration
refreshSession()
}
else -> {
// Handle other errors
Log.e(TAG, "Signature error: $errorMessage")
Toast.makeText(this, "Error: $errorMessage", Toast.LENGTH_SHORT).show()
}
}
} catch (e: JSONException) {
// Handle case where error is not JSON
Log.e(TAG, "Error parsing error message: $error", e)
Toast.makeText(this, "Error: $error", Toast.LENGTH_SHORT).show()
}
}
Production Considerations
When implementing the IgniSign SDK in production, consider these security best practices:
- API Key Security: Store your API keys securely, preferably on your server side
- HTTPS: Ensure all communications use HTTPS
- Signature Token Handling: Generate signature tokens server-side to prevent tampering
- User Authentication: Properly authenticate users before initiating signature requests
- WebView Security: Configure WebView with secure settings
Optimize performance for a smooth user experience:
- Resource Loading: Initialize the SDK only when needed
- Memory Management: Release resources properly in onDestroy/onPause
- Network Handling: Implement proper network state detection and recovery
- Background Processing: Avoid heavy operations on the UI thread
Enhance the user experience with these tips:
- Loading States: Show proper loading indicators during initialization
- Error Messages: Provide clear and actionable error messages
- Orientation Changes: Handle device orientation changes properly
- Navigation: Implement intuitive navigation flows around the signature process
- Accessibility: Ensure the signature process is accessible to all users
Common Issues and Solutions
Issue | Solution |
---|---|
WebView JavaScript errors | Ensure JavaScript is enabled in the WebView. Add debugging to see JavaScript errors. |
Network connectivity issues | Implement network state detection and handle offline scenarios gracefully. |
SDK initialization failures | Ensure all required parameters are provided and network connectivity is available. |
Memory leaks | Properly release the IgnisignAndroid view and clean up resources in onDestroy. |
Next Steps
Now that you understand how to integrate the IgniSign signature interface into your Android applications, you might want to explore:
- GitHub Repository for the Android SDK
- Example Application for a complete working example
- Webhooks Integration for real-time event notifications
- Signature Request Configuration for advanced signature settings