Android integration guide
Scan a payment card for fraud protection with CardVerify Check for Android.
- Android API level 21 or higher
- AndroidX compatibility
- Kotlin coroutine compatibility
Note: Your app does not have to be written in kotlin to integrate this library, but must be able to depend on kotlin functionality.
We try to keep our SDK as small as possible while maintaining good performance. The size impact including our SDK into your app varies depending on some features of your app:
We also provide custom implementations of the TensorFlow Lite library that are stripped-down to only support the functions our SDK uses. These custom implementations can drastically reduce the size of the SDK overall.
TF Flavor | Size (not bundled) | Size (bundled) | Dependency |
TensorFlow official release | 4.00MB | 1.00MB | org.tensorflow:tensorflow-lite:2.4.0 |
Bouncer TF all architectures | 2.12MB | 0.62MB | com.getbouncer:tensorflow-lite:2.1.0004 |
Bouncer TF arm only | 1.06MB | 0.62MB | com.getbouncer:tensorflow-lite-arm-only:2.1.0004 |
There are two variants of our ML models that you can choose to include in your application; the larger size, faster performing and smaller size, slower performing models. If selecting the slower performing models, the SDK will still attempt to download the faster models over the internet once your app has launched. This helps reduce the size of your app while still guaranteeing performance.
Flavor | Size (not bundled) | Size (bundled) | Dependency |
full size | 2.9 MB | 2.7 MB | com.getbouncer:scan-payment-full:2.1.0004 |
minimal | 1.6 MB | 1.2 MB | com.getbouncer:scan-payment-minimal:2.1.0004 |
download only | 0.0 MB | 0.0 MB | no dependency required |
Given the above table, select the framework you'll be using to calculate the impact that the bouncer SDK will have on the size of your application:
Using download only models | Base SDK | TFLite Framework | Total |
App supports all architectures and not bundled | 1.0 MB | 2.1 MB | 3.1 MB |
App supports ARM only and not bundled | 1.0 MB | 1.1 MB | 2.1 MB |
App released as bundle | 1.0 MB | 0.6 MB | 1.6 MB |
App already uses TFLite | 1.0 MB | 0.0 MB | 1.0 MB |
Using minimal models | Base SDK | TFLite Framework | Total |
App supports all architectures and not bundled | 2.99 MB | 2.12 MB | 5.11 MB |
App supports ARM only and not bundled | 2.99 MB | 1.06 MB | 4.05 MB |
App already uses TFLite and not bundled | 2.99 MB | 0.0 MB | 2.99 MB |
App released as bundle | 2.04 MB | 0.62 MB | 2.66 MB |
App already uses TFLite and bundled | 2.04 MB | 0.0 MB | 2.04 MB |
Using full size models | Base SDK | TFLite Framework | Total |
App supports all architectures and not bundled | 3.9 MB | 2.1 MB | 6.0 MB |
App supports ARM only and not bundled | 3.9 MB | 1.1 MB | 5.0 MB |
App released as bundle | 3.9 MB | 0.6 MB | 4.5 MB |
App already uses TFLite | 3.9 MB | 0.0 MB | 3.9 MB |
Bouncer provides a method
Scan.isDeviceArchitectureArm()
which will return true if the device is running an ARM architecture. This can be used to determine if the device supports scanning when the -arm-only
TFLite framework is in use.dependencies {
implementation 'com.getbouncer:cardverify-ui:2.1.0004'
// you must select one of the following tensorflow-lite libraries. See the
// above chart to understand how each will affect the size of your app.
// If you're already using tensorflow lite elsewhere in your project, make
// sure you depend on the TFLite framework.
implementation 'org.tensorflow:tensorflow-lite:2.4.0'
// If you need to support both ARM and x86 devices (< 1% of all android
// devices), include this dependency.
implementation 'com.getbouncer:tensorflow-lite:2.1.0004'
// If you only plan to support ARM devices, use this library
implementation 'com.getbouncer:tensorflow-lite-arm-only:2.1.0004'
}
If you are already using CardScan, leave that dependency in place.
By default, all of the ML models used to scan are downloaded during the call to
CardScanActivity.warmUp
. However, if you're concerned about scanning in areas with poor network connectivity, you may also want to include default versions of the scanning ML models in your app. Doing so will guarantee that scan will be available regardless of download speed or network connectivity.There are two options for including ML models by default into your app: 1. minimal models 2. full models
See the charts above to determine how each of these dependencies will impact the size of your app.
The full models are the same as those downloaded over the network. By adding this dependency to your app, you can ensure the maximum performance of the SDK regardless of network connection, but at the cost of a larger SDK.
dependencies {
implementation "com.getbouncer:scan-payment-full:2.1.0004"
}
The minimal models perform slightly slower than the full ML models. The SDK will attempt to download the full versions of the models during
CardScanActivity.warmUp
, which will override the minimal models. However, in the event the download takes too long or fails, the minimal ML models ensure that the scan will still function with only a small impact to performance.dependencies {
implementation "com.getbouncer:scan-payment-minimal:2.1.0004"
}
By default, bouncer uses the Android Camera 1 API. To use Camera2 or CameraX, add one of the following imports:
implementation "com.getbouncer:scan-camerax:2.1.0004"
// OR
implementation "com.getbouncer:scan-camera2:2.1.0004"
The library provides three forms of verification:
- Network
- Local
- ZeroFraud
This is the standard way of verifying payment cards. It involves integration with Bouncer servers to run the most complete set of validation logic on the results from the scan.
To use network verification, use the
com.getbouncer.cardverify.ui.network
packages to launch the verification flow.Important note: At no point does any sensitive information (e.g. card number) leave the device.
This is a less stringent verification flow than network verification, as the verification logic runs locally on the device. In cases where it is not viable to send a payload to Bouncer servers, this can be used to verify the authenticity of a card, but will be less accurate than network verification.
To use local verification, use the
com.getbouncer.cardverify.ui.local
packages to launch the verification flow.This flow is designed for verifying the authenticity of cards when adding them to a platform. It is the same as network verification, but does not return an encrypted payload from the scan. Instead, the payload is automatically uploaded to bouncer servers, where the result of the card add scan can be referenced later, for example during a transaction attempt.
To use zerofraud verification, use the
com.getbouncer.cardverify.ui.zerofraud
packages to launch the verification flow.This library provides a user interface through which payment cards can be verified. API keys can be created through the Bouncer API console. Please contact support to ensure the correct permissions have been added to your API key.
CardVerify will download ML models for use in verifying the authenticity of payment cards. To ensure these models are downloaded by the time CardVerify runs, please make sure to call the
warmUp
method on CardVerify as early in the app flow as possible. In most cases, this can be done in the onApplicationCreate
method of your app. Note that warmUp
processes on a background thread and will not affect your app's startup time.If your app doesn't already listen to application lifecycle events, you can extend the
Application
object and connect it using your manifest by setting android:name
on your application node:<application
android:icon="..."
android:label="..."
android:roundIcon="..."
android:name=".MyApplication">
...
</application>
Create a class with the same name:
Kotlin
Java
const val API_KEY = "<your_api_key_here>";
class MyApplication : Application() {
override fun onCreate() {
super.onCreate();
/*
* CardScan will attempt to update the ML models used to scan payment
* cards. By placing the call to the `warmUp` method in the
* `onApplicationCreate` method of your app, you allow the most time
* possible for models to upgrade. Note that `warmUp` processes on a
* background thread and will not affect your app's startup time.
*
* Note: the last parameter, `initializeNameAndExpiryExtraction`,
* determines if name and expiry extraction (beta feature) should be
* turned on.
*/
CardVerifyActivity.warmUp(this, API_KEY, initializeNameAndExpiryExtraction = false)
}
}
public class MyApplication extends Application {
public static final String API_KEY = "<your_api_key_here>";
@Override
public void onCreate() {
super.onCreate();
/*
* CardScan will attempt to update the ML models used to scan payment
* cards. By placing the call to the `warmUp` method in the
* `onApplicationCreate` method of your app, you allow the most time
* possible for models to upgrade. Note that `warmUp` processes on a
* background thread and will not affect your app's startup time.
*
* Note: the last parameter, `false`, determines if name and expiry
* extraction (beta feature) should be turned on.
*/
CardVerifyActivity.warmUp(this, API_KEY, false);
}
}
To start the flow,
CardVerifyActivity
provides a start
method which takes the required parameters and launches the flow. Pass in the payment card details that you want to verify, including the IIN (first six digits) and last four digits of the payment card.Kotlin
Java
class LaunchActivity : Activity, CardVerifyActivityResultHandler {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_launch)
findViewById(R.id.scanCardButton).setOnClickListener { _ ->
CardVerifyActivity.start(
activity = LaunchActivity.this,
apiKey = MyApplication.API_KEY,
iin = requiredCardNumber.take(6),
lastFour = requiredCardNumber.takeLast(4)
)
}
}
override fun onActivityResult(
requestCode: Int,
resultCode: Int,
data: Intent
) {
super.onActivityResult(requestCode, resultCode, data)
if (CardVerifyActivity.isVerifyResult(requestCode)) {
CardVerifyActivity.parseVerifyResult(resultCode, data, this)
}
}
override fun cardScanned(
instanceId: String?,
scanId: String?,
scanResult: ScanResult,
payloadVersion: Int,
encryptedPayload: String
) {
/*
* The user scanned a card. Details of the card are in the `scanResult`
* variable. Send the value in the `encryptedPayload` variable to
* Bouncer servers to check if the card is genuine. See the server
* integration documentation for details.
*/
}
override fun userMissingCard(scanId: String?) {
// The user does not have possession of this card
}
override fun enterManually(scanId: String?) {
// The user wants to manually enter a card
}
override fun userCanceled(scanId: String?) {
// The user canceled the scan.
}
override fun cameraError(scanId: String?) {
// The scan failed because of a camera error.
}
override fun analyzerFailure(scanId: String?) {
// The scan failed to analyze images from the camera.
}
override fun canceledUnknown(scanId: String?) {
// The scan was canceled due to unknown reasons.
}
}
class LaunchActivity
extends AppCompatActivity
implements CardVerifyActivityResultHandler {
private static final String API_KEY = "<your_api_key_here>";
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_launch);
findViewById(R.id.scanCardButton).setOnClickListener(v ->
CardVerifyActivity.start(
activity = LaunchActivity.this,
apiKey = MyApplication.API_KEY,
iin = requiredCardNumber.take(6),
lastFour = requiredCardNumber.takeLast(4)
)
);
}
@Override
protected void onActivityResult(
int requestCode,
int resultCode,
@Nullable Intent data
) {
super.onActivityResult(requestCode, resultCode, data);
if (CardVerifyActivity.isVerifyResult(requestCode)) {
CardVerifyActivity.parseVerifyResult(resultCode, data, this);
}
}
@Override
public void cardScanned(
@Nullable String instanceId,
@Nullable String scanId,
@NotNull ScanResult scanResult,
int payloadVersion,
@NotNull String encryptedPayload
) {
/*
* The user scanned a card. Details of the card are in the `scanResult`
* variable. Send the value in the `encryptedPayload` variable to
* Bouncer servers to check if the card is genuine. See the server
* integration documentation for details.
*/
}
@Override
public void userMissingCard(@Nullable String scanId) {
// The user does not have possession of this card
}
@Override
public void enterManually(@Nullable String scanId) {
// The user wants to manually enter a card
}
@Override
public void userCanceled(@Nullable String scanId) {
// the user canceled the scan
}
@Override
public void cameraError(@Nullable String scanId) {
// scan was canceled due to a camera error
}
@Override
public void analyzerFailure(@Nullable String scanId) {
// scan was canceled due to a failure to analyze camera images
}
@Override
public void canceledUnknown(@Nullable String scanId) {
// scan was canceled for an unknown reason
}
}
CardVerify will return an encrypted payload containing information about the payment card the user scanned. As in the example above, you can receive this payload using your activity or fragment's
onActivityResult
method.Name and expiry extraction are in beta, and must be manually enabled. The following steps enable them:
- 1.In the
warmUp
method, set the optionalinitializeNameAndExpiryExtraction
parameter totrue
. - 2.In the
start
method, set the optionalenableNameExtraction
and/orenableExpiryExtraction
parameters totrue
.
The scanner will now attempt to extract the cardholder name and card expiry during scan, and will return the values in the
cardScanned
method.To fine-tune the number of images that name and expiry extraction use, see the advanced customization documentation.
By default, the SDK will download updates to ML models used to extract card information. To disable model downloading, set the following flag to
false
before calling warmup or starting the scan:Kotlin
Java
com.getbouncer.scan.framework.Config.downloadModels = false
com.getbouncer.scan.framework.Config.setDownloadModels(false);
CardVerify is built to be customized to fit your UI.
To modify arrangement or UI functionality, CardVerify can be used as a library for your custom implementation. See the example single-activity demo app.
A licensing agreement is required to use this library.
- Details of licensing (pricing, etc) are available at
Last modified 2yr ago