Skip to main content

Capture Signature

Some transactions require a handwritten signature for authorization. The SDK signals this through onTransactionUIEvent, and your app is responsible for showing a signature pad and returning the result.

Launch the Signature Activity​

Register an activity result launcher to receive the signature once captured:

private final ActivityResultLauncher<Intent> authorizationResultLauncher =
registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
if (result.getResultCode() == Activity.RESULT_OK) {
Intent data = result.getData();
String path = data != null ? data.getStringExtra("signature_path") : null;
writeLog("Signature saved at: " + path);

String base64Signature = data != null ? data.getStringExtra("signature_base64") : null;
if (base64Signature != null) {
writeLog("Base64 Signature: " + base64Signature);
tapSDK.setAuthorizationCaptured(path, base64Signature);
} else {
writeLog("No Base64 signature received");
}
}
});
Submitting the signature is required

Reading signature_path / signature_base64 off the activity result is not enough — the SDK's transaction flow is paused waiting for the signature and will not proceed until you call:

tapSDK.setAuthorizationCaptured(signaturePath, signatureBase64);

Skipping this call leaves the transaction stuck: no further onTransactionUIEvent or onTransactionResult callbacks will fire.

ParameterTypeNotes
signaturePathStringThe signature_path extra from your signature activity's result.
signatureBase64StringThe signature_base64 extra from your signature activity's result.

The SDK's transaction result can arrive while the user is still signing. If your onTransactionResult fires before setAuthorizationCaptured has been called, hold the result (e.g. in a field) and process it only after submission completes, instead of navigating away while signing is still in progress.

Trigger the Launcher​

In your TapCallback's onTransactionUIEvent, watch for the signature-required event and launch your signature activity:

@Override
public void onTransactionUIEvent(int event) {
switch (event) {
case 1: // signature required
Intent intent = new Intent(this, SignatureActivity.class);
authorizationResultLauncher.launch(intent);
break;
default:
writeLog("onTransactionUIEvent: Unhandled event (" + event + ")");
break;
}
}

Sample Signature Activity​

public class SignatureActivity extends Activity {

private SignaturePad signaturePad;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.signature_pad_activity);

signaturePad = findViewById(R.id.signature_pad);

Button clearButton = findViewById(R.id.clear_button);
clearButton.setOnClickListener(v -> signaturePad.clear());

Button saveButton = findViewById(R.id.save_button);
saveButton.setOnClickListener(v -> {
Bitmap signatureBitmap = signaturePad.getSignatureBitmap();
if (signatureBitmap != null) {
String signatureBase64 = saveSignatureImage(signatureBitmap);
Intent resultIntent = getIntent();
resultIntent.putExtra("signature_base64", signatureBase64);
setResult(Activity.RESULT_OK, resultIntent);
finish();
} else {
Toast.makeText(this, "Please provide a signature first", Toast.LENGTH_SHORT).show();
}
});
}

private String saveSignatureImage(Bitmap bitmap) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, byteArrayOutputStream);
byte[] byteArray = byteArrayOutputStream.toByteArray();
return Base64.encodeToString(byteArray, Base64.NO_WRAP);
}
}

SignaturePad is your own (or a third-party) signature-capture view — the SDK only signals when a signature is needed via onTransactionUIEvent; it doesn't provide the capture UI itself.

Event code

The 1 in onTransactionUIEvent above is the app-defined constant for "signature required" in both reference integrations this documentation was verified against. It isn't a named constant exposed by the SDK itself — define your own constant for readability if you prefer.