To add our SDK to your own application, you should add it to the build process of your application. Currently we only support doing this using Gradle.
Adding the SDK to your gradle build file consist of two steps:
To add the repository to your project, open the settings.gradle file in your application.
Edit the repositories part of your settings.gradle, so that it contains the following:
maven {
credentials {
username 'ExampleUsername'
password 'ExamplePassword'
}
url "https://custom-ocr.klippa.com/sdk/android/maven"
}
maven { url "https://jitpack.io" }
We add jitpack.io because some of our dependencies are hosted there. If your settings.gradle already contains jitpack.io, don't add it.
The full repositories section of your settings.gradle might look like this now:
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.PREFER_SETTINGS)
repositories {
google()
mavenCentral()
maven {
credentials {
username 'ExampleUsername'
password 'ExamplePassword'
}
url "https://custom-ocr.klippa.com/sdk/android/maven"
}
maven { url "https://jitpack.io" }
}
}
Edit the dependencies part of your build.gradle, so that it contains the following:
implementation 'com.klippa:utility_meter_scanner:0.0.2'
The full dependencies section of your build.gradle might look like this now:
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
implementation 'com.klippa:utility_meter_scanner:0.0.2'
}
When you build your app now, it should download our library as dependency, and with that all dependencies of our library.
To start the scanner, import our package:
// Add to the top of your file
import com.klippa.utilitymeterscanner.KlippaUtilityMeterScanner
// Add to the top of your file
import com.klippa.utilitymeterscanner.KlippaUtilityMeterScanner;
Then start our scanner Activity from your own Activity:
// We use this constant to keep track of our activity request.
companion object {
const val KLIPPA_UTILITY_SCANNER_REQUEST_CODE = 1
}
private fun startKlippaUtilityMeterScanner() {
// Add license
KlippaUtilityMeterScanner.license = "replace-with-received-license"
// Launch the KlippaUtilityMeterScanner
val klippaUtilityMeterScanner = Intent(this, KlippaUtilityMeterScanner::class.java)
startActivityForResult(klippaUtilityMeterScanner, this.KLIPPA_UTILITY_SCANNER_REQUEST_CODE)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == this.KLIPPA_UTILITY_SCANNER_REQUEST_CODE && resultCode == RESULT_OK) {
val receivedData = data ?: return
val extras = receivedData.extras ?: return
if (extras.containsKey(KlippaUtilityMeterScanner.EXTRACTED_ITEMS)) {
val extractedItems: ArrayList<ExtractedGroupOfItems> = extras.getParcelableArrayList<ExtractedGroupOfItems>(KlippaUtilityMeterScanner.EXTRACTED_ITEMS) as ArrayList<ExtractedGroupOfItems>
Toast.makeText(this, "Result was " + extractedItems.size + " items", Toast.LENGTH_LONG).show()
}
} else if (requestCode == this.KLIPPA_UTILITY_SCANNER_REQUEST_CODE && resultCode == RESULT_CANCELED) {
var error: String? = null
if (data != null) {
error = data.getStringExtra(KlippaUtilityMeterScanner.ERROR)
}
if (error != null) {
Toast.makeText(this, "Scanner was canceled with error: $error", Toast.LENGTH_LONG).show()
} else {
Toast.makeText(this, "Scanner was canceled", Toast.LENGTH_LONG).show()
}
} else {
super.onActivityResult(requestCode, resultCode, data)
}
}
// We use this constant to keep track of our activity request.
public static int KLIPPA_UTILITY_SCANNER_REQUEST_CODE = 1;
private void startKlippaUtilityMeterScanner() {
// Add license
KlippaUtilityMeterScanner.Setup.setLicense("replace-with-received-license");
// Launch the Klippa Scanner
Intent klippaUtilityMeterScanner = new Intent(this, KlippaUtilityMeterScanner.class);
startActivityForResult(klippaUtilityMeterScanner, KLIPPA_UTILITY_SCANNER_REQUEST_CODE);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == KLIPPA_UTILITY_SCANNER_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
/* Get the ArrayList of extracted items */
if (data != null) {
if (data.hasExtra(KlippaUtilityMeterScanner.EXTRACTED_ITEMS)) {
ArrayList<ExtractedGroupOfItems> items = data.getParcelableArrayListExtra(KlippaUtilityMeterScanner.EXTRACTED_ITEMS);
Toast.makeText(this, "Result was " + items.size() + " items", Toast.LENGTH_LONG).show();
}
}
} else if (requestCode == KLIPPA_UTILITY_SCANNER_REQUEST_CODE && resultCode == Activity.RESULT_CANCELED) {
String error = null;
if (data != null) {
error = data.getStringExtra(KlippaUtilityMeterScanner.ERROR);
}
if (error != null) {
Toast.makeText(this, "Scanner was canceled with error: " + error, Toast.LENGTH_LONG).show();
} else {
Toast.makeText(this, "Scanner was canceled", Toast.LENGTH_LONG).show();
}
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
The SDK has a few customizing settings, the following methods are available:
// Set object detection sensitivity
KlippaUtilityMeterScanner.model.threshold = 0.5f
// Which values can be edited during review screen.
KlippaUtilityMeterScanner.extractionModel.canEditKeys = arrayListOf("QR-Code", "Barcode", "Value")
// Whether to show the icon to enable "multi-document-mode"
KlippaUtilityMeterScanner.menu.allowMultiDocumentsMode = true
// Whether the "multi-document-mode" should be enabled by default.
KlippaUtilityMeterScanner.menu.isMultiDocumentsModeEnabled = true
// Whether the crop mode (object detection) should be enabled by default.
KlippaUtilityMeterScanner.menu.isCropEnabled = true
// If you would like to enable automatic capturing of images.
KlippaUtilityMeterScanner.menu.allowTimer = true
KlippaUtilityMeterScanner.menu.isTimerEnabled = true
KlippaUtilityMeterScanner.durations.timerDuration = 0.5
// Ability to disable/hide the shutter button.
KlippaUtilityMeterScanner.shutterButton.allowShutterButton = true
KlippaUtilityMeterScanner.shutterButton.hideShutterButton = false
// Define the max resolution of the output file. It’s possible to set only one of these values. We will make sure the picture fits in the given resolution. We will also keep the aspect ratio of the image.
KlippaUtilityMeterScanner.images.resolutionMaxWidth = 1920
KlippaUtilityMeterScanner.images.resolutionMaxHeight = 1080
// Set the output quality (between 0-100) of the jpg encoder. Default is 100.
KlippaUtilityMeterScanner.images.outputQuality = 95
// Where to put the image results.
KlippaUtilityMeterScanner.images.outputDirectory = "/sdcard/utilitymeterscanner"
// The filename to use for the output images, supports replacement tokens %dateTime% and %randomUUID%.
KlippaUtilityMeterScanner.images.outputFileName = "KlippaUtilityMeterScannerExample-%dateTime%-%randomUUID%"
// To limit the amount of images that can be taken.
KlippaUtilityMeterScanner.images.imageLimit = 5
// The threshold sensitive the motion detection is. (lower value is higher sensitivity, default 50).
KlippaUtilityMeterScanner.images.imageMovingSensitivity = 50
// To add extra horizontal and / or vertical padding to the cropped meter image.
KlippaUtilityMeterScanner.images.cropPadding = Size(100, 100)
// The warning message when someone should move closer to a meter, should be a string.
KlippaUtilityMeterScanner.messages.moveCloserMessage = "Move closer to the meter"
// The warning message when the camera preview has to much motion to be able to automatically take a photo.
KlippaUtilityMeterScanner.messages.imageMovingMessage = "Camera is moving too much"
// The message to display when the limit has been reached.
KlippaUtilityMeterScanner.messages.imageLimitReached = "You have reached the limit"
// After capture, show a checkmark preview with this success message, instead of a preview of the image.
KlippaUtilityMeterScanner.messages.successMessage = "Success"
KlippaUtilityMeterScanner.durations.successPreviewDuration = 0.4
// What the default color conversion will be (grayscale, original).
KlippaUtilityMeterScanner.colors.defaultColor = KlippaUtilityMeterScanner.DefaultColor.ORIGINAL
// The amount of seconds the preview should be visible for, should be a float.
KlippaUtilityMeterScanner.durations.previewDuration = 1.5
// Whether to save the images to the gallery
KlippaUtilityMeterScanner.storeImagesToGallery = false
// Set object detection sensitivity
KlippaUtilityMeterScanner.Setup.getModel().setThreshold(0.5f);
// Which values can be edited during review screen.
KlippaUtilityMeterScanner.Setup.getExtractionModel().setCanEditKeys(Arrays.asList("QR-Code", "Barcode", "Value"));
// Whether to show the icon to enable "multi-document-mode"
KlippaUtilityMeterScanner.Setup.getMenu().setAllowMultiDocumentsMode(true);
// Whether the "multi-document-mode" should be enabled by default.
KlippaUtilityMeterScanner.Setup.getMenu().setMultiDocumentsModeEnabled(true);
// Whether the crop mode (object detection) should be enabled by default.
KlippaUtilityMeterScanner.Setup.getMenu().setCropEnabled(true);
// If you would like to enable automatic capturing of images.
KlippaUtilityMeterScanner.Setup.getMenu().setAllowTimer(true);
KlippaUtilityMeterScanner.Setup.getMenu().setTimerEnabled(true);
KlippaUtilityMeterScanner.Setup.getDurations().setTimerDuration(0.5);
// Ability to disable/hide the shutter button.
KlippaUtilityMeterScanner.Setup.getShutterButton().setAllowShutterButton(true);
KlippaUtilityMeterScanner.Setup.getShutterButton().setHideShutterButton(false);
// Define the max resolution of the output file. It’s possible to set only one of these values. We will make sure the picture fits in the given resolution. We will also keep the aspect ratio of the image.
KlippaUtilityMeterScanner.Setup.getImages().setResolutionMaxWidth(1920);
KlippaUtilityMeterScanner.Setup.getImages().setResolutionMaxHeight(1080);
// Set the output quality (between 0-100) of the jpg encoder. Default is 100.
KlippaUtilityMeterScanner.Setup.getImages().setOutputQuality(95);
// Where to put the image results.
KlippaUtilityMeterScanner.Setup.getImages().setOutputDirectory("/sdcard/utilitymeterscanner");
// The filename to use for the output images, supports replacement tokens %dateTime% and %randomUUID%.
KlippaUtilityMeterScanner.Setup.getImages().setOutputFileName("KlippaUtilityMeterScannerExample-%dateTime%-%randomUUID%");
// To limit the amount of images that can be taken.
KlippaUtilityMeterScanner.Setup.getImages().setImageLimit(5);
// The threshold sensitive the motion detection is. (lower value is higher sensitivity, default 50).
KlippaUtilityMeterScanner.Setup.getImages().setImageMovingSensitivity(50);
// To add extra horizontal and / or vertical padding to the cropped meter image.
KlippaUtilityMeterScanner.Setup.getImages().setCropPadding(new Size(100, 100));
// The warning message when someone should move closer to a meter, should be a string.
KlippaUtilityMeterScanner.Setup.getMessages().setMoveCloserMessage("Move closer to the meter");
// The warning message when the camera preview has to much motion to be able to automatically take a photo.
KlippaUtilityMeterScanner.Setup.getMessages().setImageMovingMessage("Camera is moving too much");
// The message to display when the limit has been reached.
KlippaUtilityMeterScanner.Setup.getMessages().setImageLimitReached("You have reached the limit");
// After capture, show a checkmark preview with this success message, instead of a preview of the image.
KlippaUtilityMeterScanner.Setup.getMessages().setSuccessMessage("Success");
KlippaUtilityMeterScanner.Setup.getDurations().setSuccessPreviewDuration(0.4);
// What the default color conversion will be (grayscale, original).
KlippaUtilityMeterScanner.Setup.getColors().setDefaultColor(KlippaUtilityMeterScanner.DefaultColor.ORIGINAL);
// The amount of seconds the preview should be visible for, should be a float.
KlippaUtilityMeterScanner.Setup.getDurations().setPreviewDuration(1.5);
// Whether to save the images to the gallery
KlippaUtilityMeterScanner.Setup.setStoreImagesToGallery(true);
Add or edit the file android/app/src/main/res/values/colors.xml, add the following:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="klippa_scanner_sdk_color_Primary">#2dc36a</color>
<color name="klippa_scanner_sdk_color_PrimaryDark">#308D53</color>
<color name="klippa_scanner_sdk_color_Accent">#2dc36a</color>
<color name="klippa_scanner_sdk_color_Overlay">#2dc36a</color>
<color name="klippa_scanner_sdk_color_Warning">#BFFF0000</color>
<color name="klippa_scanner_sdk_color_IconDisabledColor">#80FFFFFF</color>
<color name="klippa_scanner_sdk_color_IconEnabledColor">#FFFFFFFF</color>
<color name="klippa_scanner_sdk_color_ReviewIconColor">#FFFFFFFF</color>
</resources>
Because our SDK includes OpenCV, which includes native code which in turn generates a native library (.so file) for every architecture, the APK size can increase quite a bit by using our SDK.
To minimize the impact of the SDK on your app size, you can enable APK splitting in your build.grade, like this:
android {
// Other options
splits {
abi {
enable true
universalApk false
reset()
include 'arm64-v8a', 'armeabi-v7a', 'x86', 'x86_64'
}
}
// Other options
}
In our example app (which contains not much more than the SDK), this resulted in the following APK files:
While creating a single APK file creates a file that is 41MB, since most phones are ARM, on average APK splitting will result in a 32.7MB smaller APK.
Please note that all APK files should be signed and uploaded to the Play Store to get a release that works on all devices.
The JavaDoc of the latest version is available for download here.
The following versions are available:
Version | Gradle dependency | JavaDoc |
---|---|---|
0.0.2 | implementation 'com.klippa:utility_meter_scanner:0.0.2' | Download |
0.0.1 | implementation 'com.klippa:utility_meter_scanner:0.0.1' | Download |