Skip to content

Commit 612feaa

Browse files
authored
Merge pull request #17 from blinkcard/release/v2.9.1
Release/v2.9.1
2 parents 706f5ce + 6a2a940 commit 612feaa

File tree

11 files changed

+536
-69
lines changed

11 files changed

+536
-69
lines changed

BlinkCard/android/build.gradle

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,23 @@ rootProject.allprojects {
2323
apply plugin: 'com.android.library'
2424

2525
android {
26-
compileSdkVersion 28
26+
27+
if (project.android.hasProperty("namespace")) {
28+
namespace 'com.microblink.blinkcard.flutter'
29+
}
30+
31+
compileSdkVersion 34
2732

2833
defaultConfig {
29-
minSdkVersion 16
34+
minSdkVersion 21
3035
}
3136
lintOptions {
3237
disable 'InvalidPackage'
3338
}
3439
}
3540

3641
dependencies {
37-
implementation('com.microblink:blinkcard:2.9.0@aar') {
42+
implementation('com.microblink:blinkcard:2.9.3@aar') {
3843
transitive = true
3944
}
40-
}
45+
}

BlinkCard/android/src/main/java/com/microblink/blinkcard/flutter/BlinkCardFlutterPlugin.java

Lines changed: 152 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33
import android.app.Activity;
44
import android.content.Context;
55
import android.content.Intent;
6+
import android.graphics.Bitmap;
7+
import android.graphics.BitmapFactory;
68
import androidx.annotation.NonNull;
9+
import android.util.Base64;
710
import java.util.*;
811

912
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
@@ -24,6 +27,14 @@
2427
import com.microblink.blinkcard.uisettings.UISettings;
2528
import com.microblink.blinkcard.uisettings.ActivityRunner;
2629
import com.microblink.blinkcard.locale.LanguageUtils;
30+
import com.microblink.blinkcard.directApi.DirectApiErrorListener;
31+
import com.microblink.blinkcard.directApi.RecognizerRunner;
32+
import com.microblink.blinkcard.entities.recognizers.RecognizerBundle;
33+
import com.microblink.blinkcard.hardware.orientation.Orientation;
34+
import com.microblink.blinkcard.metadata.MetadataCallbacks;
35+
import com.microblink.blinkcard.metadata.recognition.FirstSideRecognitionCallback;
36+
import com.microblink.blinkcard.recognition.RecognitionSuccessType;
37+
import com.microblink.blinkcard.view.recognition.ScanResultListener;
2738

2839

2940
import com.microblink.blinkcard.flutter.recognizers.RecognizerSerializers;
@@ -39,16 +50,21 @@ public class BlinkCardFlutterPlugin implements FlutterPlugin, MethodCallHandler,
3950
private static final String CHANNEL = "blinkcard_scanner";
4051

4152
private static final int SCAN_REQ_CODE = 1904;
42-
private static final String METHOD_SCAN = "scanWithCamera";
53+
private static final String METHOD_SCAN_CAMERA = "scanWithCamera";
54+
private static final String METHOD_SCAN_DIRECT_API = "scanWithDirectApi";
4355

4456
private static final String ARG_LICENSE = "license";
4557
private static final String ARG_LICENSE_KEY = "licenseKey";
4658
private static final String ARG_LICENSEE = "licensee";
4759
private static final String ARG_SHOW_LICENSE_WARNING = "showTimeLimitedLicenseKeyWarning";
4860
private static final String ARG_RECOGNIZER_COLLECTION = "recognizerCollection";
4961
private static final String ARG_OVERLAY_SETTINGS = "overlaySettings";
62+
private static final String ARG_FRONT_IMAGE = "frontImage";
63+
private static final String ARG_BACK_IMAGE = "backImage";
5064

65+
private boolean mFirstSideScanned = false;
5166
private RecognizerBundle mRecognizerBundle;
67+
private RecognizerRunner mRecognizerRunner;
5268

5369
private MethodChannel channel;
5470
private Context context;
@@ -85,21 +101,26 @@ private void setupPlugin(Context context, BinaryMessenger messenger) {
85101
public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
86102
setLicense((Map)call.argument(ARG_LICENSE));
87103

88-
if (call.method.equals(METHOD_SCAN)) {
104+
if (call.method.equals(METHOD_SCAN_CAMERA)) {
89105
pendingResult = result;
90106

91107
JSONObject jsonOverlaySettings = new JSONObject((Map)call.argument(ARG_OVERLAY_SETTINGS));
92108
JSONObject jsonRecognizerCollection = new JSONObject((Map)call.argument(ARG_RECOGNIZER_COLLECTION));
93-
try {
94-
LanguageUtils.setLanguageAndCountry(jsonOverlaySettings.getString("language"),
95-
jsonOverlaySettings.getString("country"),
96-
context);
97-
} catch (Exception e) {}
109+
setLanguage(jsonOverlaySettings);
98110
mRecognizerBundle = RecognizerSerializers.INSTANCE.deserializeRecognizerCollection(jsonRecognizerCollection);
99111
UISettings uiSettings = OverlaySettingsSerializers.INSTANCE.getOverlaySettings(context, jsonOverlaySettings, mRecognizerBundle);
100112

101113
startScanning(SCAN_REQ_CODE, uiSettings);
102114

115+
} else if (call.method.equals(METHOD_SCAN_DIRECT_API)) {
116+
pendingResult = result;
117+
118+
JSONObject jsonRecognizerCollection = new JSONObject((Map)call.argument(ARG_RECOGNIZER_COLLECTION));
119+
String frontImage = call.argument(ARG_FRONT_IMAGE);
120+
String backImage = call.argument(ARG_BACK_IMAGE);
121+
122+
scanWithDirectApi(jsonRecognizerCollection, frontImage, backImage);
123+
103124
} else {
104125
result.notImplemented();
105126
}
@@ -108,18 +129,30 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
108129

109130
@SuppressWarnings("unchecked")
110131
private void setLicense(Map licenseMap) {
111-
MicroblinkSDK.setShowTrialLicenseWarning((boolean)licenseMap.getOrDefault(ARG_SHOW_LICENSE_WARNING, true));
132+
if (licenseMap.get(ARG_SHOW_LICENSE_WARNING) != null) {
133+
MicroblinkSDK.setShowTrialLicenseWarning((boolean) licenseMap.get(ARG_SHOW_LICENSE_WARNING));
134+
} else {
135+
MicroblinkSDK.setShowTrialLicenseWarning(true);
136+
}
112137

113-
String licenseKey = (String)licenseMap.get(ARG_LICENSE_KEY);
114-
String licensee = (String)licenseMap.getOrDefault(ARG_LICENSEE, null);
138+
String licenseKey = (String) licenseMap.get(ARG_LICENSE_KEY);
139+
String licensee = (String) licenseMap.get(ARG_LICENSEE);
115140

116141
if (licensee == null) {
117142
MicroblinkSDK.setLicenseKey(licenseKey, context);
118143
} else {
119144
MicroblinkSDK.setLicenseKey(licenseKey, licensee, context);
120145
}
121146

122-
MicroblinkSDK.setIntentDataTransferMode(IntentDataTransferMode.PERSISTED_OPTIMISED);
147+
MicroblinkSDK.setIntentDataTransferMode(IntentDataTransferMode.PERSISTED_OPTIMISED);
148+
}
149+
150+
private void setLanguage(JSONObject jsonOverlaySettings) {
151+
try {
152+
LanguageUtils.setLanguageAndCountry(jsonOverlaySettings.getString("language"),
153+
jsonOverlaySettings.getString("country"),
154+
context);
155+
} catch (Exception e) {}
123156
}
124157

125158
private void startScanning(int requestCode, UISettings uiSettings) {
@@ -132,6 +165,113 @@ private void startScanning(int requestCode, UISettings uiSettings) {
132165
}
133166
}
134167

168+
private void scanWithDirectApi(JSONObject jsonRecognizerCollection, String frontImage, String backImage) {
169+
ScanResultListener mScanResultListenerBackSide = new ScanResultListener() {
170+
@Override
171+
public void onScanningDone(@NonNull RecognitionSuccessType recognitionSuccessType) {
172+
mFirstSideScanned = false;
173+
handleDirectApiResult(recognitionSuccessType);
174+
}
175+
@Override
176+
public void onUnrecoverableError(@NonNull Throwable throwable) {
177+
handleDirectApiError(throwable.getMessage());
178+
}
179+
};
180+
181+
FirstSideRecognitionCallback mFirstSideRecognitionCallback = new FirstSideRecognitionCallback() {
182+
@Override
183+
public void onFirstSideRecognitionFinished() {
184+
mFirstSideScanned = true;
185+
}
186+
};
187+
188+
ScanResultListener mScanResultListenerFrontSide = new ScanResultListener() {
189+
@Override
190+
public void onScanningDone(@NonNull RecognitionSuccessType recognitionSuccessType) {
191+
if (mFirstSideScanned) {
192+
//multiside recognizer used
193+
if (!backImage.isEmpty() && backImage != null) {
194+
processImage(backImage, mScanResultListenerBackSide);
195+
} else if (recognitionSuccessType != RecognitionSuccessType.UNSUCCESSFUL) {
196+
handleDirectApiResult(recognitionSuccessType);
197+
} else {
198+
handleDirectApiError("Could not extract the information from the front side and back side is empty!");
199+
}
200+
} else if (!mFirstSideScanned && recognitionSuccessType != RecognitionSuccessType.UNSUCCESSFUL){
201+
//singleside recognizer used
202+
handleDirectApiResult(recognitionSuccessType);
203+
} else {
204+
mFirstSideScanned = false;
205+
handleDirectApiError("Could not extract the information with DirectAPI!");
206+
}
207+
}
208+
@Override
209+
public void onUnrecoverableError(@NonNull Throwable throwable) {
210+
handleDirectApiError(throwable.getMessage());
211+
}
212+
};
213+
214+
setupRecognizerRunner(jsonRecognizerCollection, mFirstSideRecognitionCallback);
215+
216+
if (!frontImage.isEmpty()) {
217+
processImage(frontImage, mScanResultListenerFrontSide);
218+
} else {
219+
handleDirectApiError("The provided image for the 'frontImage' parameter is empty!");
220+
}
221+
}
222+
223+
private void setupRecognizerRunner(JSONObject jsonRecognizerCollection, FirstSideRecognitionCallback mFirstSideRecognitionCallback) {
224+
if (mRecognizerRunner != null) {
225+
mRecognizerRunner.terminate();
226+
}
227+
mRecognizerBundle = RecognizerSerializers.INSTANCE.deserializeRecognizerCollection(jsonRecognizerCollection);
228+
try {
229+
mRecognizerRunner = RecognizerRunner.getSingletonInstance();
230+
} catch (Exception e) {
231+
handleDirectApiError("DirectAPI not supported: " + e);
232+
}
233+
234+
MetadataCallbacks metadataCallbacks = new MetadataCallbacks();
235+
metadataCallbacks.setFirstSideRecognitionCallback(mFirstSideRecognitionCallback);
236+
mRecognizerRunner.setMetadataCallbacks(metadataCallbacks);
237+
mRecognizerRunner.initialize(context, mRecognizerBundle, throwable -> handleDirectApiError("Failed to initialize recognizer with DirectAPI: " + throwable.getMessage()));
238+
}
239+
240+
private void processImage(String base64Image, ScanResultListener scanResultListener) {
241+
Bitmap image = base64ToBitmap(base64Image);
242+
if (image != null) {
243+
mRecognizerRunner.recognizeBitmap(
244+
base64ToBitmap(base64Image),
245+
Orientation.ORIENTATION_LANDSCAPE_RIGHT,
246+
scanResultListener
247+
);
248+
} else {
249+
handleDirectApiError("Could not decode the Base64 image!");
250+
}
251+
}
252+
253+
private void handleDirectApiResult(RecognitionSuccessType recognitionSuccessType) {
254+
if (recognitionSuccessType != RecognitionSuccessType.UNSUCCESSFUL) {
255+
if (pendingResult == null) {
256+
return;
257+
}
258+
JSONArray resultList = RecognizerSerializers.INSTANCE.serializeRecognizerResults(mRecognizerBundle.getRecognizers());
259+
pendingResult.success(resultList.toString());
260+
}
261+
pendingResult = null;
262+
}
263+
private Bitmap base64ToBitmap(String base64String) {
264+
byte[] decodedBytes = android.util.Base64.decode(base64String, Base64.DEFAULT);
265+
return BitmapFactory.decodeByteArray(decodedBytes, 0, decodedBytes.length);
266+
}
267+
268+
private void handleDirectApiError(String errorMessage) {
269+
pendingResult.error("", errorMessage, null);
270+
if (mRecognizerRunner != null) {
271+
mRecognizerRunner.resetRecognitionState(true);
272+
}
273+
}
274+
135275
@Override
136276
public void onDetachedFromActivity() {}
137277

@@ -185,5 +325,4 @@ public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
185325
pendingResult = null;
186326
return true;
187327
}
188-
}
189-
328+
}

0 commit comments

Comments
 (0)