# Setup Accura Finger

### **To initialize sdk on app start:**

```
FingerEngine fingerEngine = new FingerEngine();
FingerEngine.SDKModel sdkModel = fingerEngine.initEngine(your activity context);

if (sdkModel.i > 0) { // if license is valid
     if (sdkModel.isFingerEnable) // RecogType.FINGER_PRINT
}
```

***

### **Set CameraView**

```
Must have to extend com.accura.finger.print.sdk.motiondetection.SensorsActivity to your activity.
- Make sure your activity orientation locked from Manifest. Because auto rotate not support.

private CameraView cameraView;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.your layout);

    // Recog type selection base on your license data
    RecogType recogType = RecogType.FingerPrint;

    // initialized camera
    initCamera();
}

private void initCamera() {
    //<editor-fold desc="To get status bar height">
    Rect rectangle = new Rect();
    Window window = getWindow();
    window.getDecorView().getWindowVisibleDisplayFrame(rectangle);
    int statusBarTop = rectangle.top;
    int contentViewTop = window.findViewById(Window.ID_ANDROID_CONTENT).getTop();
    int statusBarHeight = contentViewTop - statusBarTop;
    //</editor-fold>

    RelativeLayout linearLayout = findViewById(R.id.ocr_root); // layout width and height is match_parent

    cameraView = new CameraView(this);
    
    if (recogType == RecogType.FINGER_PRINT) {
        // fingerType = FingerEngine.FINGER_ENROLL or FingerEngine.FINGER_VERIFY
        // fingerSideType = FingerEngine.LEFT_HAND  or FingerEngine.RIGHT_HAND
        cameraView.setFingerType(fingerType, fingerSideType);
        cameraView.setUserName(userName);
    }
    cameraView.setRecogType(recogType)
            .setFrameView(ocr_frame) // make sure ocr_frame 4 child layout same as used in this demo app
            .setFlashMode(CameraView.FLASH_MODE_ON) // CameraView.FLASH_MODE_OFF
            .setView(linearLayout) // To add camera view
            .setCameraFacing(0) // To set selfie(1) or rear(0) camera.
            .setFingerCallback(this)  // To get scanning status
            .setStatusBarHeight(statusBarHeight)  // To remove Height from Camera View if status bar visible
//                Optional setup
//                .setEnableMediaPlayer(false) // false to disable default sound and true to enable sound and default it is true
//                .setCustomMediaPlayer(MediaPlayer.create(this, /*custom sound file*/)) // To add your custom sound and Must have to enable media player
            .init();  // initialized camera
}

/**
 * To handle camera on window focus update
 * @param hasFocus
 */
@Override
public void onWindowFocusChanged(boolean hasFocus) {
    if (cameraView != null) {
        cameraView.onWindowFocusUpdate(hasFocus);
    }
}

@Override
protected void onResume() {
    super.onResume();
    if (cameraView != null) cameraView.onResume();
}

@Override
protected void onPause() {
    cameraView.onPause();
    if (cameraView != null) super.onPause();
}

@Override
protected void onDestroy() {
    if (cameraView != null) cameraView.onDestroy();
    super.onDestroy();
}

/**
 * Call {@link CameraView#startOcrScan(boolean isReset)} To start Camera Preview
 */
@Override
public void onUpdateLayout(int width, int height) {
    if (cameraView != null) cameraView.startOcrScan(false);
}

/**
 * Override this method after scan complete to get data
 * @param result   Getting scanned finger data
 * FingerEngine.FINGER_ENROLL - List of FingerModel to enroll user
 * FingerEngine.FINGER_VERIFY - Single object of FingerModel to verify user with enrolled users
 */
@Override
public void onScannedComplete(Object result) {
    // display data on ui thread
    Log.e("TAG", "onScannedComplete: ");
    if (result != null && recogType == RecogType.FINGER_PRINT) {
    	// make sure release camera view before open result screen
    	// if (cameraView != null) cameraView.release(true);
        FingerEngine fingerEngine = new FingerEngine();
        Runnable runnable = () -> {
            if (fingerType.equals(FingerEngine.FINGER_ENROLL)) {
                List<?> list = new ArrayList<>();
                if (result.getClass().isArray() ) {
                    list = Arrays.asList((Object[])result);
                } else if (result instanceof Collection) {
                    list = new ArrayList<>((Collection<?>) result);
                }
                long uniqueID = -1;
                FingerModel fingerModel = null;
                for (Object o : list) {
                    fingerModel = (FingerModel) o;
                    uniqueID = dbHelper.addUser(fingerModel, uniqueID);
                }
                
                // Access data from database
                List<FingerModel> fingerModels = dbhelper.getUserByUniqueID(fingerModel);
                
                // Proccsing fingerprint images
                fingerEngine.processImage(fingerModels);
                
                // To manage local database
                for (FingerModel model : fingerModels){
                    dbhelper.updateFeatures(model);
                }
                
                
                boolean isValid = fingerEngine.fingerValidation(fingerModels, 0);
                if (isValid) {
                    Toast.makeText(this, "Enrollment Failed, Bad Prints Detected", Toast.LENGTH_SHORT).show()
                    
                    // delete user from local database
                    for (FingerModel model : fingerModels){
                        dbhelper.deleteUser(model);
                    }
                    return;
                }
                List<FingerModel> fingerAPIModels = dbhelper.getAllUser(fingerModels.get(0), false);

                JSONObject object = new JSONObject();
                boolean _isValid = fingerEngine.checkingEnrollment(fingerModels, fingerAPIModels, object);
                if (_isValid) {
                    Toast.makeText(this, "Member successfully added", Toast.LENGTH_SHORT).show()
                } else {
                    // delete user from local database
                    for (FingerModel model : fingerModels){
                        dbhelper.deleteUser(model);
                    }
                    Toast.makeText(this, "Enrollment failed, Found duplicate with " + object.getString("name"), Toast.LENGTH_SHORT).show()
                }
                
            } else if (result instanceof FingerModel) {
                ((FingerModel) result).setUserName(uniqueName); // set enrolled user name to match with
                ((FingerModel) result).setUniqueID(uniqueId); // set enrolled unique Id to match with
                FingerModel.setModel((FingerModel) result);
                
                fingerEngine.processImage(fingerModel);
                List<FingerModel> fingerModels = new DatabaseHelper(FingerActivity.this).getAllUser(fingerModel, true);
                float v2 = fingerEngine.fingerAuthentication(fingerModel, fingerModels, 0, new JSONObject(), "", null);
                
                Toast.makeText(this, "Hello " + fingerModel.getUserName() + ",\n" + fingerModel.getStrings()[0], Toast.LENGTH_SHORT).show();
                
            }
        };
        runOnUiThread(runnable);
    } else Toast.makeText(this, "Failed", Toast.LENGTH_SHORT).show();
}

/**
 * @param errorMessage To display process message.
 *                null if message is not available
 * @param isShowAnim  To set your custom animation
 */
@Override
public void onProcessUpdate(int titleCode, String errorMessage, boolean isShowAnim) {
// make sure update view on ui thread
    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            // Review FingerActivity.java file for UI changes and messages 
   
            if (errorMessage != null) {
                Toast.makeText(context, getErrorMessage(errorMessage), Toast.LENGTH_SHORT).show(); // display message
            } else {
                Log.e(TAG, isShowAnim); // show/hide animation
            }
        }
    });
}

private String getErrorMessage(String s) {
    switch (s) {
        case FingerEngine.ACCURA_ERROR_CODE_RIGHT_HAND:
            return "Please place right hand 4 fingers in frame;
        case FingerEngine.ACCURA_ERROR_CODE_LEFT_HAND:
            return "Please place left hand 4 fingers in frame";
        case FingerEngine.ACCURA_ERROR_CODE_KEEP_DISTANCE:
            return "Keep distance between Fingers;
        case FingerEngine.ACCURA_ERROR_CODE_AWAY:
            return "Keep fingers slightly away from the Camera";
        case FingerEngine.ACCURA_ERROR_CODE_CLOSER:
            return "Keep fingers close to the Camera;
        case FingerEngine.ACCURA_ERROR_CODE_MESSAGE:
            return "Move and place your fingers properly";
        default:
            return s;
    }
}

@Override
public void onProgress(float progress) {
    // To display scanning progress
    Toast.makeText(context, progress, Toast.LENGTH_SHORT).show();
}

@Override
public void onError(String errorMessage) {
    // Scanning is getting stop
    Runnable runnable = () -> Toast.makeText(context, errorMessage, Toast.LENGTH_LONG).show();
    runOnUiThread(runnable);
}
```

***

### ProGuard

Depending on your ProGuard (DexGuard) config and usage, you may need to include the following lines in your proguards.

```
-keep public class com.machinezoo.sourceafis.**
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.accurascan.com/solutions/finger-biometrics/android/setup-accura-finger.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
