MobbScan Cordova: Customize UI
Introduction
MobbScan allows the customization of the user interface, making it a flexible product that can fits in any application indenpendently of its look & feel.
Fixed Mode
The orientation of the camera can be locked with the following function:
MobbScanAPI.setFixedMode("LANDSCAPE", () => console.log("success!"), console.error);
Or:
MobbScanAPI.setFixedMode("PORTRAIT", () => console.log("success!"), console.error);
Customize Document Detection UI
When the method MobbScanAPI.scanDocumentForSide
is called, a camera screen appears with an overlay, which can be customized using the following method:
MobbScanAPI.setDocumentDetectionInterface(uiClass, onSuccess, onFailure);
Where the arguments are:
uiClass
is the class name of the new overlay.onSuccess
is a callback which will be called if the UI has been set correctly.onFailure
is a callback which will be called if some error happens.
When an unsupported document is being scanned the UI is different, it should be set with the following method:
MobbScanAPI.setOtherDocumentDetectionInterface(uiClass, onSuccess, onFailure);
The uiClass
should refer to Android and iOS native classes. Check the documentation of the native SDKs for more details about how to build these classes:
Examples
MobbScanDemoDocumentDetectionInterface.java
package com.mobbeel.mobbscan.cordovaplugindemo;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Point;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.view.Display;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import com.mobbeel.mobbscan.MobbScan;
import com.mobbeel.mobbscan.RotateAnimation;
import com.mobbeel.mobbscan.api.MobbScanAPI;
import com.mobbeel.mobbscan.api.MobbScanAPIError;
import com.mobbeel.mobbscan.api.MobbScanDocumentSide;
import com.mobbeel.mobbscan.api.detection.MobbScanDocumentDetectionTrack;
import com.mobbeel.mobbscan.api.listener.IDDocumentDetectionFeedbackListener;
import com.mobbeel.mobbscan.api.listener.IDDocumentDetectionListener;
import com.mobbeel.mobbscan.api.result.MobbScanDetectionFeedbackResult;
import com.mobbeel.mobbscan.api.result.MobbScanDetectionResult;
import com.mobbeel.mobbscan.api.result.MobbScanDetectionResultData;
import com.mobbeel.mobbscan.utils.DetectedImage;
public class MobbScanDemoDocumentDetectionInterface extends AppCompatActivity {
private static final float ES_ID_CARD_V2_WIDTH = 1011;
private static final float ES_ID_CARD_V2_HEIGHT = 637;
private MobbScanDocumentDetectionTrack detectionTrack;
private MobbScanDocumentSide documentSide;
private ViewGroup cameraViewContainer;
private RelativeLayout borders;
private LinearLayout feedbackMessage;
private int rotation;
private int orientation;
private float aspectRatio = ES_ID_CARD_V2_HEIGHT / ES_ID_CARD_V2_WIDTH;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
readExtras();
configureViews();
configureDetector();
startDetection();
}
private void readExtras() {
documentSide = (MobbScanDocumentSide) getIntent().getSerializableExtra(MobbScan.DOCUMENT_SIDE_KEY);
}
private void configureViews() {
setContentView(R.layout.mobbscandemo_document_detection);
cameraViewContainer = (ViewGroup) findViewById(R.id.cameraViewContainer);
borders = (RelativeLayout) findViewById(R.id.borders);
feedbackMessage = (LinearLayout) findViewById(R.id.feedbackMessage);
borders.setVisibility(View.GONE);
feedbackMessage.setVisibility(View.GONE);
MobbScanAPI.FixedMode fixedMode = MobbScanAPI.getInstance().getFixedMode();
if(fixedMode != MobbScanAPI.FixedMode.NONE) {
rotateView(fixedMode.value);
}
adjustCameraViewDimen();
}
private void configureDetector() {
detectionTrack = new MobbScanDocumentDetectionTrack(cameraViewContainer);
MobbScanAPI.getInstance().setDocumentDetectionTrack(detectionTrack);
MobbScanAPI.getInstance().setIdDocumentDetectionFeedbackListener(getIdDocumentDetectionFeedbackListener());
}
@NonNull
private IDDocumentDetectionFeedbackListener getIdDocumentDetectionFeedbackListener() {
return new IDDocumentDetectionFeedbackListener() {
@Override
public void onIDDocumentDetection(MobbScanDetectionFeedbackResult result) {
processDetectionEvent(result);
}
@Override
public void onNewOrientationDetected(final int rotationDegrees) {
rotateView(rotationDegrees);
adjustCameraViewDimen();
}
};
}
private void rotateView(int rotationDegrees) {
rotation = rotationDegrees;
switch (rotationDegrees) {
case 0:
orientation = Configuration.ORIENTATION_PORTRAIT;
break;
case 270:
orientation = Configuration.ORIENTATION_LANDSCAPE;
break;
case 180:
orientation = Configuration.ORIENTATION_PORTRAIT;
break;
case 90:
orientation = Configuration.ORIENTATION_LANDSCAPE;
break;
}
}
private void adjustCameraViewDimen() {
feedbackMessage.setRotation(rotation);
borders.startAnimation(new RotateAnimation(borders, aspectRatio, getSize(), orientation));
}
private void processDetectionEvent(MobbScanDetectionFeedbackResult result) {
}
private void startDetection() {
MobbScanAPI.getInstance().detectDocument(documentSide, getScanListener());
borders.setVisibility(View.VISIBLE);
borders.startAnimation(new RotateAnimation(borders, aspectRatio, getSize(), orientation));
feedbackMessage.setVisibility(View.VISIBLE);
}
private Point getSize(){
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
return size;
}
private IDDocumentDetectionListener getScanListener() {
return new IDDocumentDetectionListener() {
@Override
public void onIDDocumentDetected(MobbScanDetectionResult result, MobbScanDetectionResultData resultData, MobbScanAPIError error) {
processScanEvent(resultData);
}
};
}
private void processScanEvent(MobbScanDetectionResultData resultData) {
DetectedImage.getInstance().setImage(resultData.getImage());
Intent resultIntent = new Intent();
resultIntent.putExtra(MobbScan.DOCUMENT_SIDE_KEY, documentSide);
setResult(MobbScan.DETECT_DOCUMENT_ACTIVITY_REQUEST_CODE, resultIntent);
finish();
}
@Override
protected void onPause() {
super.onPause();
if (detectionTrack != null) {
detectionTrack.onPause();
}
}
@Override
protected void onResume() {
super.onResume();
if (detectionTrack != null) {
detectionTrack.onResume();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (detectionTrack != null) {
detectionTrack.onDestroy();
}
}
}
MobbScanDemoDocumentDetectionInterface.h
#import <UIKit/UIKit.h>
#import <MobbScanSDK-iOS/MobbScanSDK-iOS.h>
#import "MobbScanDocumentDetectionInterfaceProtocol.h"
@interface MobbScanDemoDocumentDetectionInterface : UIViewController <MobbScanDocumentDetectionInterfaceProtocol>
@property (nonatomic, strong) NSString *scanId;
@property (nonatomic, assign) MobbScanDocumentSide documentSide;
@property (nonatomic, copy) IDDocumentDetected detectionResult;
@property (nonatomic, copy) IDDocumentScanned scanResult;
@end
MobbScanDemoDocumentDetectionInterface.m
#import "MobbScanDemoDocumentDetectionInterface.h"
#import "BorderView.h"
@interface MobbScanDemoDocumentDetectionInterface ()
@property (nonatomic, strong) MobbScanAPI *mobbScanAPI;
@property (nonatomic, strong) MobbScanDocumentDetectionTrack *detectionTrack;
@property (weak, nonatomic) IBOutlet UIView *cameraViewContainer;
@property (weak, nonatomic) IBOutlet UIButton *cancelButton;
@property (weak, nonatomic) IBOutlet BorderView *border;
@end
@implementation MobbScanDemoDocumentDetectionInterface
#pragma mark - View Controller methods
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
self.mobbScanAPI = [MobbScanAPI getInstance];
self.detectionTrack = [[MobbScanDocumentDetectionTrack alloc] init];
[self.detectionTrack setCameraViewContainer:self.cameraViewContainer];
[self.mobbScanAPI setDocumentDetectionTrack:self.detectionTrack];
[self.mobbScanAPI setDocumentDetectionFeedback:^(MobbScanDetectionFeedbackResult result, MobbScanDetectionFeedbackResultData *_Nullable resultData, NSError *_Nullable error) {
NSLog(@"Detection state: %@", NSStringFromMobbScanDetectionFeedbackResult(result));
}];
[self.mobbScanAPI detectDocumentSide:self.documentSide
withDetectionResult:^(MobbScanDetectionResult result, MobbScanDetectionResultData *_Nullable resultData, NSError *_Nullable error) {
self.detectionResult(result, resultData, error);
[self dismissViewControllerAnimated:YES completion:nil];
}];
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskLandscapeRight;
}
- (BOOL)shouldAutorotate {
return YES;
}
#pragma mark - User interaction
- (IBAction)cancelButtonTouched:(id)sender {
[self.detectionTrack onPause];
[self dismissViewControllerAnimated:YES completion:nil];
}
@end
MobbScanDemoDocumentDetectionInterface.xib
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="13771" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina5_5" orientation="landscape">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13772"/>
<capability name="Aspect ratio constraints" minToolsVersion="5.1"/>
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="MobbScanDemoDocumentDetectionInterface">
<connections>
<outlet property="border" destination="Py0-m8-FOf" id="R2g-O4-lIF"/>
<outlet property="cameraViewContainer" destination="D9C-rf-e5F" id="aEK-lu-Xjl"/>
<outlet property="cancelButton" destination="crY-If-Qtf" id="FSJ-pY-baj"/>
<outlet property="view" destination="iN0-l3-epB" id="Xns-dx-sqC"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="iN0-l3-epB">
<rect key="frame" x="0.0" y="0.0" width="736" height="414"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="D9C-rf-e5F" userLabel="Camera View Container">
<rect key="frame" x="0.0" y="0.0" width="736" height="414"/>
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
</view>
<view opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Py0-m8-FOf" customClass="BorderView">
<rect key="frame" x="105.66666666666669" y="41.333333333333343" width="524.66666666666652" height="331.33333333333326"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="mobbscandemo_document_placeholder.png" translatesAutoresizingMaskIntoConstraints="NO" id="bc1-gS-Vgk" userLabel="Feedback Image">
<rect key="frame" x="237.33333333333331" y="87.333333333333314" width="48" height="36"/>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Coloca tu documento" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ZWz-1g-dpx" userLabel="Feedback Message 1">
<rect key="frame" x="142" y="123.3333333333333" width="240" height="31.333333333333329"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleTitle1"/>
<color key="textColor" red="0.0" green="0.75294117650000003" blue="0.87843137250000003" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="dentro del marco de referencia" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="xt8-md-wxb" userLabel="Feedback Message 2">
<rect key="frame" x="136" y="154.66666666666666" width="251" height="21"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="17"/>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="hasta que la imagen se capture automáticamente" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="sjn-Jy-dvd" userLabel="Feedback Message 3">
<rect key="frame" x="73.666666666666657" y="175.66666666666666" width="375.66666666666674" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<constraints>
<constraint firstItem="sjn-Jy-dvd" firstAttribute="top" secondItem="xt8-md-wxb" secondAttribute="bottom" id="9Fe-x2-hBx"/>
<constraint firstItem="xt8-md-wxb" firstAttribute="centerX" secondItem="Py0-m8-FOf" secondAttribute="centerX" id="DjI-9M-JvJ"/>
<constraint firstItem="bc1-gS-Vgk" firstAttribute="centerX" secondItem="ZWz-1g-dpx" secondAttribute="centerX" id="PuZ-UR-8RF"/>
<constraint firstItem="sjn-Jy-dvd" firstAttribute="centerX" secondItem="xt8-md-wxb" secondAttribute="centerX" id="bmH-YE-fdF"/>
<constraint firstItem="ZWz-1g-dpx" firstAttribute="centerX" secondItem="xt8-md-wxb" secondAttribute="centerX" id="df9-WG-qZJ"/>
<constraint firstItem="bc1-gS-Vgk" firstAttribute="bottom" secondItem="ZWz-1g-dpx" secondAttribute="top" id="hSy-q1-vgG"/>
<constraint firstItem="ZWz-1g-dpx" firstAttribute="bottom" secondItem="xt8-md-wxb" secondAttribute="top" id="iNr-RG-J7S"/>
<constraint firstItem="xt8-md-wxb" firstAttribute="centerY" secondItem="Py0-m8-FOf" secondAttribute="centerY" id="pra-uh-hv1"/>
<constraint firstAttribute="width" secondItem="Py0-m8-FOf" secondAttribute="height" multiplier="1011:637" id="vxe-Sb-WGa"/>
</constraints>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="color" keyPath="strokeColor">
<color key="value" red="0.0" green="0.75294117647058822" blue="0.8784313725490196" alpha="1" colorSpace="calibratedRGB"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="number" keyPath="lineWidth">
<real key="value" value="3"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="number" keyPath="dashWidth">
<real key="value" value="7"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="number" keyPath="dashGap">
<real key="value" value="6"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="number" keyPath="cornerWidth">
<real key="value" value="20"/>
</userDefinedRuntimeAttribute>
</userDefinedRuntimeAttributes>
</view>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="crY-If-Qtf" userLabel="Cancel Button">
<rect key="frame" x="698" y="0.0" width="30" height="44"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleTitle1"/>
<state key="normal" title="x">
<color key="titleColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</state>
<connections>
<action selector="cancelButtonTouched:" destination="-1" eventType="touchUpInside" id="sgS-5L-IfM"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="Py0-m8-FOf" firstAttribute="centerX" secondItem="vUN-kp-3ea" secondAttribute="centerX" id="8Es-Dx-HZM"/>
<constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="crY-If-Qtf" secondAttribute="trailing" constant="8" id="BHb-QL-mP5"/>
<constraint firstItem="vUN-kp-3ea" firstAttribute="bottom" secondItem="D9C-rf-e5F" secondAttribute="bottom" id="P2F-64-lGM"/>
<constraint firstItem="D9C-rf-e5F" firstAttribute="leading" secondItem="vUN-kp-3ea" secondAttribute="leading" id="e4X-Ef-6gO"/>
<constraint firstItem="Py0-m8-FOf" firstAttribute="height" secondItem="iN0-l3-epB" secondAttribute="height" multiplier="0.8" id="pL9-TW-SbD"/>
<constraint firstItem="crY-If-Qtf" firstAttribute="top" secondItem="vUN-kp-3ea" secondAttribute="top" id="rAA-hf-p2g"/>
<constraint firstItem="vUN-kp-3ea" firstAttribute="trailing" secondItem="D9C-rf-e5F" secondAttribute="trailing" id="t6T-VF-eQB"/>
<constraint firstItem="D9C-rf-e5F" firstAttribute="top" secondItem="vUN-kp-3ea" secondAttribute="top" id="vm9-d3-YrI"/>
<constraint firstItem="Py0-m8-FOf" firstAttribute="centerY" secondItem="vUN-kp-3ea" secondAttribute="centerY" id="zGp-l8-Zba"/>
</constraints>
<viewLayoutGuide key="safeArea" id="vUN-kp-3ea"/>
</view>
</objects>
<resources>
<image name="mobbscandemo_document_placeholder.png" width="48" height="36"/>
</resources>
</document>
Customize MRZ Detection UI
When the method MobbScanAPI.startScanForDocumentMrz
is called, a camera screen appears with an overlay, which can be customized using the following method:
MobbScanAPI.setDocumentMrzDetectionInterface(uiClass, onSuccess, onFailure);
Where the arguments are:
uiClass
is the class name of the new overlay.onSuccess
is a callback which will be called if the UI has been set correctly.onFailure
is a callback which will be called if some error happens.
Check the documentation of the native SDKs for more details about how to build these classes:
Examples
MobbScanDemoDocumentMrzDetectionInterface.java
package com.mobbeel.mobbscan.cordovaplugindemo;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Point;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.graphics.drawable.LayerDrawable;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.view.Display;
import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import com.mobbeel.mobbscan.MobbScan;
import com.mobbeel.mobbscan.RotateAnimation;
import com.mobbeel.mobbscan.api.MobbScanAPI;
import com.mobbeel.mobbscan.api.MobbScanAPIError;
import com.mobbeel.mobbscan.api.MobbScanDocumentSide;
import com.mobbeel.mobbscan.api.ScanOperation;
import com.mobbeel.mobbscan.api.ScanOperationMRZ;
import com.mobbeel.mobbscan.api.detection.MobbScanDocumentDetectionTrack;
import com.mobbeel.mobbscan.api.listener.IDDocumentDetectionFeedbackListener;
import com.mobbeel.mobbscan.api.listener.IDDocumentDetectionListener;
import com.mobbeel.mobbscan.api.result.MobbScanDetectionFeedbackResult;
import com.mobbeel.mobbscan.api.result.MobbScanDetectionMRZResultData;
import com.mobbeel.mobbscan.api.result.MobbScanDetectionResult;
import com.mobbeel.mobbscan.api.result.MobbScanDetectionResultData;
import com.mobbeel.mobbscan.document.iddocumentmrz.IDDocumentMRZ;
import com.mobbeel.mobbscan.utils.DetectedImage;
import com.mobbeel.mobbscan.ux.FocusView;
import com.mobbeel.mobbscan.ux.OnMarginsUpdates;
public class MobbScanDemoDocumentMrzDetectionInterface extends AppCompatActivity {
private static final float ES_ID_CARD_V2_WIDTH = 1011;
private static final float ES_ID_CARD_V2_HEIGHT = 637;
private MobbScanDocumentDetectionTrack detectionTrack;
private LinearLayout feedbackMessage;
private ViewGroup cameraViewContainer;
private RelativeLayout borders;
private FocusView focusView;
private int rotation;
private int orientation;
private float aspectRatio = ES_ID_CARD_V2_HEIGHT / ES_ID_CARD_V2_WIDTH;
private ScanOperationMRZ.SCAN_MRZ_MODE scanMode;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
readExtras();
configureViews();
configureDetector();
startDetection();
}
private void readExtras() {
String mode = getIntent().getStringExtra(MobbScan.MRZ_MODE);
switch(mode) {
case "DEFAULT":
scanMode = ScanOperationMRZ.SCAN_MRZ_MODE.DEFAULT;
break;
case "WITH_CROPPED_DOCUMENT":
scanMode = ScanOperationMRZ.SCAN_MRZ_MODE.WITH_CROPPED_DOCUMENT;
break;
case "FORCE_CROPPED_DOCUMENT":
scanMode = ScanOperationMRZ.SCAN_MRZ_MODE.FORCE_CROPPED_DOCUMENT;
break;
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
switch (keyCode) {
case KeyEvent.KEYCODE_BACK:
finish();
return true;
}
return super.onKeyDown(keyCode, event);
}
private void configureViews() {
setContentView(R.layout.mobbscandemo_document_mrz_detection);
cameraViewContainer = findViewById(R.id.cameraViewContainer);
feedbackMessage = findViewById(R.id.feedbackMessage);
borders = findViewById(R.id.borders);
feedbackMessage.setVisibility(View.GONE);
focusView = findViewById(R.id.focusView);
focusView.setMarginsListener(new OnMarginsUpdates() {
@Override
public void onUpdate(float marginLeft, float marginTop, float marginRight, float marginBottom) {
detectionTrack.setMRZClearZone(marginLeft, marginTop, marginRight, marginBottom);
}
});
MobbScanAPI.FixedMode fixedMode = MobbScanAPI.getInstance().getFixedMode();
if(fixedMode != MobbScanAPI.FixedMode.NONE) {
rotateView(fixedMode.value);
}
adjustCameraViewDimen();
}
private void configureDetector() {
detectionTrack = new MobbScanDocumentDetectionTrack(cameraViewContainer);
MobbScanAPI.getInstance().setDocumentDetectionTrack(detectionTrack);
MobbScanAPI.getInstance().setIdDocumentDetectionFeedbackListener(getIdDocumentDetectionFeedbackListener());
}
private void startDetection() {
ScanOperation scanOperation = new ScanOperationMRZ.Builder().scanMrzMode(ScanOperationMRZ.SCAN_MRZ_MODE.DEFAULT).build();
if (scanMode != null) {
scanOperation = new ScanOperationMRZ.Builder().scanMrzMode(scanMode).build();
}
MobbScanAPI.getInstance().scan(scanOperation, getScanListener());
}
private Point getSize() {
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
return size;
}
@NonNull
private IDDocumentDetectionFeedbackListener getIdDocumentDetectionFeedbackListener() {
return new IDDocumentDetectionFeedbackListener() {
@Override
public void onIDDocumentDetection(MobbScanDetectionFeedbackResult result) {
processDetectionEvent(result);
}
@Override
public void onNewOrientationDetected(final int rotationDegrees) {
rotateView(rotationDegrees);
adjustCameraViewDimen();
}
};
}
private void rotateView(int rotationDegrees) {
rotation = rotationDegrees;
detectionTrack.setDocumentBounds(new RectF(0, 0, detectionTrack.getCameraViewContainer().getWidth(),
detectionTrack.getCameraViewContainer().getHeight()));
switch (rotationDegrees) {
case 0:
orientation = Configuration.ORIENTATION_PORTRAIT;
break;
case 270:
orientation = Configuration.ORIENTATION_LANDSCAPE;
break;
case 180:
orientation = Configuration.ORIENTATION_PORTRAIT;
break;
case 90:
orientation = Configuration.ORIENTATION_LANDSCAPE;
break;
}
}
private void adjustCameraViewDimen() {
feedbackMessage.setRotation(rotation);
focusView.setRotation(rotation);
borders.startAnimation(new RotateAnimation(borders, aspectRatio, getSize(), orientation));
}
private IDDocumentDetectionListener getScanListener() {
return new IDDocumentDetectionListener() {
@Override
public void onIDDocumentDetected(MobbScanDetectionResult result, MobbScanDetectionResultData resultData, MobbScanAPIError error) {
processScanEvent(resultData);
}
};
}
private void processDetectionEvent(MobbScanDetectionFeedbackResult result) {
if (result == MobbScanDetectionFeedbackResult.DOCUMENT_DETECTED_HOLD_ON) {
processDetectedEvent();
detectionTrack.onPause();
} else if (result == MobbScanDetectionFeedbackResult.SEARCHING_DOCUMENT) {
focusView.setVisibility(View.INVISIBLE);
processNotDetectedEvent();
} else {
processNotDetectedEvent();
}
}
private void processScanEvent(MobbScanDetectionResultData resultData) {
DetectedImage.getInstance().setImage(resultData.getImage());
IDDocumentMRZ idDocumentMRZ = (IDDocumentMRZ) ((MobbScanDetectionMRZResultData) resultData).getDocument();
Intent resultIntent = new Intent();
resultIntent.putExtra(MobbScan.MRZ_RESULT_KEY, idDocumentMRZ);
setResult(MobbScan.DETECT_MRZ_ACTIVITY_REQ_CODE, resultIntent);
finish();
}
private void processDetectedEvent() {
setBorderColor(ContextCompat.getColor(this, R.color.mobbscan_document_detected));
}
private void processNotDetectedEvent() {
setBorderColor(ContextCompat.getColor(this, R.color.mobbscan_document_not_detected));
}
@Override
protected void onPause() {
super.onPause();
if (detectionTrack != null) {
detectionTrack.onPause();
}
}
@Override
protected void onResume() {
super.onResume();
if (detectionTrack != null) {
detectionTrack.onResume();
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (detectionTrack != null) {
detectionTrack.onDestroy();
}
}
private void setBorderColor(int color) {
int borderStrokeWidth = (int) getResources().getDimension(R.dimen.mobbscan_border_stroke_width);
int borderDashWidth = (int) getResources().getDimension(R.dimen.mobbscan_border_stroke_dash_width);
int borderDashGap = (int) getResources().getDimension(R.dimen.mobbscan_border_stroke_dash_gap);
int borderCornerStrokeWidth = (int) getResources().getDimension(R.dimen.mobbscan_border_corner_stroke_width);
Drawable borderDrawable = ContextCompat.getDrawable(this, R.drawable.mobbscan_document_detection_border);
LayerDrawable borderLayerDrawable = (LayerDrawable) borderDrawable;
GradientDrawable borderGradientDrawable = (GradientDrawable) borderLayerDrawable.findDrawableByLayerId(R.id.border);
borderGradientDrawable.setStroke(borderStrokeWidth, color, borderDashWidth, borderDashGap);
RelativeLayout constraintLayout = findViewById(R.id.borders);
constraintLayout.setBackground(borderDrawable);
setCornersColor(borderCornerStrokeWidth, color);
}
private void setCornersColor(int width, int color) {
setTopStartCornerStroke(width, color);
setTopEndCornerStroke(width, color);
setBottomStartCornerStroke(width, color);
setBottomEndCornerStroke(width, color);
}
private void setTopStartCornerStroke(int width, int color) {
LayerDrawable topStartCornerLayerDrawable = (LayerDrawable) ContextCompat.getDrawable(this, R.drawable.mobbscan_document_detection_top_start_corner);
GradientDrawable topStartCornerTopGradientDrawable = (GradientDrawable) topStartCornerLayerDrawable.findDrawableByLayerId(R.id.top_start_corner_top);
topStartCornerTopGradientDrawable.setStroke(width, color);
GradientDrawable topStartCornerStartGradientDrawable = (GradientDrawable) topStartCornerLayerDrawable.findDrawableByLayerId(R.id.top_start_corner_start);
topStartCornerStartGradientDrawable.setStroke(width, color);
RelativeLayout constraintLayout = findViewById(R.id.topStartCorner);
constraintLayout.setBackground(topStartCornerLayerDrawable);
}
private void setTopEndCornerStroke(int width, int color) {
LayerDrawable topEndCornerLayerDrawable = (LayerDrawable) ContextCompat.getDrawable(this, R.drawable.mobbscan_document_detection_top_end_corner);
GradientDrawable topEndCornerTopGradientDrawable = (GradientDrawable) topEndCornerLayerDrawable.findDrawableByLayerId(R.id.top_end_corner_top);
topEndCornerTopGradientDrawable.setStroke(width, color);
GradientDrawable topEndCornerEndGradientDrawable = (GradientDrawable) topEndCornerLayerDrawable.findDrawableByLayerId(R.id.top_end_corner_end);
topEndCornerEndGradientDrawable.setStroke(width, color);
RelativeLayout constraintLayout = (RelativeLayout) findViewById(R.id.topEndCorner);
constraintLayout.setBackground(topEndCornerLayerDrawable);
}
private void setBottomStartCornerStroke(int width, int color) {
LayerDrawable bottomStartCornerLayerDrawable = (LayerDrawable) ContextCompat.getDrawable(this, R.drawable.mobbscan_document_detection_bottom_start_corner);
GradientDrawable bottomStartCornerBottomGradientDrawable = (GradientDrawable) bottomStartCornerLayerDrawable.findDrawableByLayerId(R.id.bottom_start_corner_bottom);
bottomStartCornerBottomGradientDrawable.setStroke(width, color);
GradientDrawable bottomStartCornerStartGradientDrawable = (GradientDrawable) bottomStartCornerLayerDrawable.findDrawableByLayerId(R.id.bottom_start_corner_start);
bottomStartCornerStartGradientDrawable.setStroke(width, color);
RelativeLayout constraintLayout = (RelativeLayout) findViewById(R.id.bottomStartCorner);
constraintLayout.setBackground(bottomStartCornerLayerDrawable);
}
private void setBottomEndCornerStroke(int width, int color) {
LayerDrawable bottomEndCornerLayerDrawable = (LayerDrawable) ContextCompat.getDrawable(this, R.drawable.mobbscan_document_detection_bottom_end_corner);
GradientDrawable bottomEndCornerBottomGradientDrawable = (GradientDrawable) bottomEndCornerLayerDrawable.findDrawableByLayerId(R.id.bottom_end_corner_bottom);
bottomEndCornerBottomGradientDrawable.setStroke(width, color);
GradientDrawable bottomEndCornerEndGradientDrawable = (GradientDrawable) bottomEndCornerLayerDrawable.findDrawableByLayerId(R.id.bottom_end_corner_end);
bottomEndCornerEndGradientDrawable.setStroke(width, color);
RelativeLayout constraintLayout = (RelativeLayout) findViewById(R.id.bottomEndCorner);
constraintLayout.setBackground(bottomEndCornerLayerDrawable);
}
}
Customize Video Conference UI
When the method MobbScanVideoAPI.start
is called, a camera screen appears with an overlay, which can be customized using the following method:
MobbScanVideoAPI.setVideoInterface((uiClass, onSuccess, onFailure);
Where the arguments are:
uiClass
is the class name of the new overlay.onSuccess
is a callback which will be called if the UI has been set correctly.onFailure
is a callback which will be called if some error happens.
Customize UI messages
Check the documentation of the native SDKs for more details about this topic: