Android integration guide
Scan a payment card with CardScan 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.
The cardscan repository contains a demonstration app for the CardScan product. To build and install this library follow the following steps:
- 1.Clone the repository from githubgit clone --recursive https://github.com/getbouncer/cardscan-android
- 2.Build the library using gradle or android studio. a. Using android studio, open the directory
cardscan-android
. Install the app on your device or an emulator by clicking the play button in the top right of android studio.b. Using gradle, build the demo app by executing the following command:./gradlew cardscan-demo:assembleReleaseThis will create a release APK in thecardscan-demo/build/outputs/apk
directory. Copy this file to your device and install it.
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.The SDK also provides methods
CardScanActivity.isScanReady()
and CardScanActivity.isNameAndExpiryScanReady()
which return true if the ML models used for scanning are downloaded or available through the SDK.These libraries are published in the maven central repository, so for most gradle configurations you only need to add the dependencies to your app's
build.gradle
file:dependencies {
implementation 'com.getbouncer:cardscan-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'
}
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"
This library provides a user interface through which payment cards can be scanned. API keys can be created through the Bouncer API console.
Kotlin
Java
class LaunchActivity : AppCompatActivity, CardScanActivityResultHandler {
private const val API_KEY = "<your_api_key_here>"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_launch)
findViewById(R.id.scanCardButton).setOnClickListener { _ ->
CardScanActivity.start(
activity = LaunchActivity.this,
apiKey = API_KEY,
enableEnterCardManually = true,
// expiry extraction is in beta. See the comment below.
enableExpiryExtraction = true,
// name extraction is in beta. See the comment below.
enableNameExtraction = true
)
}
/*
* To test name and/or expiry extraction, please first provision an API
* key, then reach out to [email protected] with details about your
* use case and estimated volumes.
*
* If you are not planning to use name or expiry extraction, you can
* omit the line below.
*/
CardScanActivity.warmUp(
context = this,
apiKey = API_KEY,
initializeNameAndExpiryExtraction = true
)
}
override fun onActivityResult(
requestCode: Int,
resultCode: Int,
data: Intent?
) {
super.onActivityResult(requestCode, resultCode, data)
if (CardScanActivity.isScanResult(requestCode)) {
CardScanActivity.parseScanResult(resultCode, data, this)
}
}
override fun cardScanned(scanId: String?, scanResult: ScanResult) {
// a payment card was scanned successfully
}
override fun enterManually(scanId: String?) {
// the user wants to enter a card manually
}
override fun userCanceled(scanId: String?) {
// the user canceled the scan
}
override fun cameraError(scanId: String?) {
// scan was canceled due to a camera error
}
override fun analyzerFailure(scanId: String?) {
// scan was canceled due to a failure to analyze camera images
}
override fun canceledUnknown(scanId: String?) {
// scan was canceled for an unknown reason
}
}
class LaunchActivity extends AppCompatActivity
implements CardScanActivityResultHandler {
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 ->
CardScanActivity.start(
activity = LaunchActivity.this,
apiKey = API_KEY,
enableEnterCardManually = true,
// expiry extraction is in beta. See the comment below.
enableExpiryExtraction = true,
// name extraction is in beta. See the comment below.
enableNameExtraction = true
)
);
/*
* To test name and/or expiry extraction, please first provision an API
* key, then reach out to [email protected] with details about your
* use case and estimated volumes.
*
* If you are not planning to use name or expiry extraction, you can
* omit the line below.
*/
CardScanActivity.warmUp(
this,
API_KEY,
/* enableNameAndExpiryExtraction */ true
);
}
@Override
protected void onActivityResult(
int requestCode,
int resultCode,
@Nullable Intent data
) {
super.onActivityResult(requestCode, resultCode, data);
if (CardScanActivity.isScanResult(requestCode)) {
CardScanActivity.parseScanResult(resultCode, data, this);
}
}
@Override
public void cardScanned(
@Nullable String scanId,
@NotNull CardScanActivityResult scanResult
) {
// a payment card was scanned successfully
}
@Override
public void enterManually(@Nullable String scanId) {
// the user wants to enter a card manually
}
@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
}
}
CardScan will attempt to update the ML models used to scan payment cards. To ensure these models are upgraded by the time CardScan runs, please make sure to call the
warmUp
method on CardScan 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.
*/
CardScanActivity.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.
*/
CardScanActivity.warmUp(this, API_KEY, false);
}
}
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.Note that name extraction requires additional permissions on your API key. Please contact us as [email protected] to add that permission.
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);
This library is built to be customized to fit your UI.
To modify arrangement or UI functionality, you can create a custom implementation of this library. See the example single-activity demo app.
Though CardScan supports several cards, you may need to add support for cards specific to your business, instructions can be found in the card support docs.
Adam Wushensky, Sam King, Zain ul Abi Din, and Sven Kuhne
This library is available under paid and free licenses. See the LICENSE file for the full license text.
In short, this library will remain free forever for non-commercial applications, but use by commercial applications is limited to 90 days, after which time a licensing agreement is required. We're also adding some legal liability protections.
After this period commercial applications need to convert to a licensing agreement to continue to use this library.
- Details of licensing (pricing, etc) are available at https://cardscan.io/pricing, or you can contact us at [email protected].
What’s allowed under the license:
- Free use for any app for 90 days (for demos, evaluations, hackathons, etc).
- Any modifications as needed to work in your app
What’s not allowed under the license:
- Commercial applications using the license for longer than 90 days without a license agreement.
- Using us now in a commercial app today? No worries! Just email [email protected] and we’ll get you set up.
- Redistribution under a different license
- Removing attribution
- Modifying logos
- Indemnification: using this free software is ‘at your own risk’, so you can’t sue Bouncer Technologies, Inc. for problems caused by this library
Last modified 1yr ago