VitalSnap Permissions and Operations

Native Android ==> OCR module

Validic provides an activity ValidicOCRActivity to encapsulate the OCRFragment. It will perform the necessary permission checking for Camera permissions.

Create a ActivityResultLauncher to launch the ValidicOCRActivity and handle the result after the engine has converged on a Measurement

val ocrLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {  
        if (it.resultCode == Activity.RESULT_OK) {  
            it.data?.let { intent ->  
                val result = intent.getSerializableExtra(ValidicOCRActivity.RECORD_KEY) as Measurement  
                val bitmap = intent.getParcelableExtra<Bitmap>(ValidicOCRActivity.IMAGE_KEY) as Bitmap  
                Toast.makeText(requireActivity(), "Retrieved Inform Measurement ${result.logId}", Toast.LENGTH_LONG).show()  
                lifecycleScope.launch {  
                    SessionV2.getInstance(requireContext()).submit(result, bitmap)  
                }  
            }  
        } else if (it.resultCode == ValidicOCRActivity.ERROR_WRITING_FILE) {  
            ValidicLog.e("Error writing file while trying to perform OCR read.")  
        }  
    }

Then create an Intent and launch the ValidicOCRActivity. The Camera permission will be requested if it is not granted.

val intent = Intent(requireContext(), ValidicOCRActivity::class.java)  
intent.putExtra(ValidicOCRActivity.PERIPHERAL_ID, selectedPeripheral.peripheralID)  
ocrLauncher.launch()

ValidicOCRFragment

An instance of the ValidicOCRController class is used to manage the recognition process. AnOCRPeripheral represents the peripheral being scanned. The controller is initialized with a peripheral object.

The recognition process involves a fragment that contains the camera preview and an overlay image.

OCR processing begins as soon as the fragment is injected into the view. An instance of ValidicOCRResultListener must be registered to receive intermediate and final results. The camera capture session ends when the fragment is paused or when a result is converged.

The ValidicOCRController requires an OCRPeripheral for its initializers.

Once a peripheral is obtained, construct the ValidicOCRController and assign it an instance of ValidicOCRResultListener:

ValidicOCRController ocrController = ValidicOCRController.initWithOCRPeripheral(peripheral);  
ocrController.setListener(listener);

Runtime unit selection

For any glucose meter in our lineup of supported meters, you can now specify mmol/l or mg/dL at runtime for a given reading. If no unit is provided, mg/dL is assumed.

For the Zewa 11110 thermometer, you can specify Celsius or Fahrenheit at runtime for a given reading. If no unit is provided, Fahrenheit is assumed.

ValidicOCRController ocrController = ValidicOCRController.initWithOCRPeripheral(peripheral, GlucoseUnit.MMOLL);

Example

VitalSnap processing begins when the ocr fragment is injected into your view.

Injection Example:

ocrController.injectOCRFragment(getFragmentManager().beginTransaction(),  
                R.id.activity_ocr_fragment_container)  
                .commit();

Processing is stopped when the fragment is paused or a final value has been converged. If no value has been converged on, the fragment will resume processing onResume. To restart or to take additional readings with the same peripheral, simply call restartOCR on the ValidicOCRController.

ocrController.restartOCR();

Listener

During OCR processing, ValidicOCRResultListener will be called with partial results until the ValidicOCRController converges on a result. When the ValidicOCRController interprets a result with high confidence the Camera will stop and the listener's completion method will be called.

The recognized values returned in the record should be visually validated by the user. The cropped preview image can be displayed to the user to validate the recognized values before uploading to the Validic API.

if (validicOCRPeripheral.getType() == Peripheral.PeripheralType.GlucoseMeter) {  
  val measurement = VitalSnapTransformer . asInformMeasurement (vitalsnapResult, validicOCRPeripheral)  
  Log.v(TAG, "Blood glucose captured: " + measurement.metrics?.first { it.type == BloodGlucose.Type.value }.value)  
}

After verifying the Measurement is correct, submit the record and the image to be uploaded to the server:

scope.launch {  
  SessionV2.getInstance(context).submit(measurement, bitmap)  
}