Migration Guide: MRZScanner SDK to to barKoder SDK (Android)

This guide explains how to replace the MRZScanner SDK with the barKoder SDK in an existing Android app. It assumes MRZScanner is already integrated and you’re now migrating to barKoder while preserving as much of your current app structure and UI as possible.

The goal is to show you:

• The key conceptual differences between MRZScanner and barKoder
How the MRZ result model changes
• Which parts of your code you need to update

MRZScanner SDK #

• Uses a Fragment (MRZScanner) in XML
• You implement MRZScannerListener with successfulScan(withResult:).
• You get a strongly typed MRZResultModel with properties like first_name, date_of_birth_readable, etc.

barKoder SDK #


• Gives you a View (BarkoderView) that you embed.
• You implement BarkoderResultCallback with scanningFinished(decoderResults:thumbnails:image:).
• The MRZ data comes as a JSON-like dictionary in decoderResult.extra.
• SDK configuration (vibration, session closing, duplicate threshold, etc.) lives in BarkoderConfig.

1. Migration checklist #

1. Remove MRZScanner SDK aar or depndency and imports. 
2.Integrate barKoder SDK (Using Official Documentation)
For detailed instructions on integrating barKoder into your Android project, please refer to the barKoder Android SDK installation guide
barKoder Android SDK installation guide
3.Replace fragment with a BarkoderView property in your xml file .
4.Configure BarkoderView with: BarkoderConfig(applicationContext , licenseKey) decoderConfig.IDDocument.enabled = true for MRZ/ID documents.• Optional: config.setVibrateOnSuccessEnabled, config.setImageResultEnabled, etc.
6.Update your listener in activity class to conform to BarkoderResultCallback and implement scanningFinished(decoderResults:thumbnails:image:).
7.Start scanning with try barkoderView.startScanning(this).
8.Update all places that used MRZResultModel to now read MRZ fields from DecoderResult.extra ([AnyHashable: Any]).


2. Initialization & licensing #

Before – MRZScannerSDK #

                import com.scansolutions.mrzscannerlib.MRZResultModel
import com.scansolutions.mrzscannerlib.MRZScanner
import com.scansolutions.mrzscannerlib.MRZScannerListener
import com.scansolutions.mrzscannerlib.ScannerType 

class ScannerActivity : BaseActivity<ScannerContract.View, ScannerPresenter>(),    MRZScannerListener, { 

private fun setupScanner() {    
scanner = supportFragmentManager.findFragmentById(R.id.scannerFragment) as MRZScanner   
MRZScanner.setIDActive(sharedPreferencesHelper.getIDActiveSetting())    MRZScanner.setPassportActive(sharedPreferencesHelper.getPassportActiveSetting())    MRZScanner.setVisaActive(sharedPreferencesHelper.getVisaActiveSetting())    MRZScanner.setMaxThreads(sharedPreferencesHelper.getMaxCPUCoresSetting())    MRZScanner.registerWithLicenseKey(this, getString(R.string.*mrz_key*))    scanner?.setScanningRectangle(SCANNING_RECT_X,SCANNING_RECT_Y,SCANNING_RECT_WIDTH,    SCANNING_RECT_HEIGHT) 

override fun successfulScanWithResult(resultModel: MRZResultModel) {
val resultDataModel = AMRZResultDataModel(resultModel)        resultDataModel.portrait = resultModel.portrait        
resultDataModel.signature = resultModel.signature        
resultDataModel.fullImage = resultModel.fullImage        
resultDataModel.idBack = resultModel.idBack        
resultDataModel.idFront = resultModel.idFront 
   }
}
            


After – barKoder SDK #

                import com.barkoder.Barkoder;
import com.barkoder.BarkoderConfig;
import com.barkoder.BarkoderHelper;
import com.barkoder.BarkoderView;
import com.barkoder.interfaces.BarkoderResultCallback;

public class MainActivity extends AppCompatActivity implements BarkoderResultCallback {
   protected void onCreate(Bundle savedInstanceState) {    
      super.onCreate(savedInstanceState);    
      setContentView(R.layout.activity_main);

       var barkoderConfig = new BarkoderConfig(getApplicationContext(), "LICENSE_KEY",
        new Barkoder.LicenseCheckListener() {
            @Override
            public void onLicenseCheck(Barkoder.LicenseCheckResult licenseCheckResult) {
                Log.i(TAG, "license check result: " + licenseCheckResult.message);                   
              });

       bkdView.config = barkoderConfig
       setBarkoderSettings()
       bkdView.config.decoderConfig.IDDocument.enabled = true
       bkdView.startScanning(this)
    }

override fun scanningFinished(
results: Array<Barkoder.Result>,
thumbnails: Array<Bitmap>,
resultImage: Bitmap?
) {
   results.forEach { result ->
    result.images?.forEach { img ->
        when ([img.name](http://img.name/)) {
            "main"      -> mainBitmap = img.image
            "document"  -> documentBitmap = img.image
            "signature" -> signatureBitmap = img.image
            "picture"   -> pictureBitmap = img.image
         }
     }
  }
}`

private fun setBarkoderSettings() {
    // These are optional settings, otherwise default values will be used    
bkdView.config.let{ config ->
     // Optional: image results (thumbnail & full image) 
       config.isImageResultEnabled = true
       config.setThumbnailOnResultEnabled(true)
    // Behaviour similar to "single scan then stop" 
       config.isCloseSessionOnResultEnabled = true
    // Your MRZ → barKoder “vibration” mapping:
       config.isVibrateOnSuccessEnabled = true
       config.decoderConfig.decodingSpeed = Barkoder.DecodingSpeed.*Slow*
       config.barkoderResolution = BarkoderResolution.*FHD*
       config.isBeepOnSuccessEnabled = true
       config.setRegionOfInterest(0f, 30f, 100f, 40f)    
  }  
}
            

Note: You must have a valid license with IDDocument enabled. If you start the scanner with IDDocument enabled but your license doesn’t include it, the scanner will return the result: “ID Document decoder type is not licensed!”.In barKoder there are no separate settings for (ID, Visa,Passport). Enabling idDocument automatically:Enables all ID types (ID, Passport, Visa) Validates country codes Supports upside-down (rotated) scanning by default.To stop the scanner you can call stopScanning()


3.MRZ result data: what changes and how to adapt #

3.1 What you used to get (MRZResultModel) #

From successfulScan(withResult:):

                override fun successfulScanWithResult(resultModel: MRZResultModel) {
// MRZScanner properties:
result.document_type
result.document_number
result.given_names
result.surnames
result.nationality
result.issuing_country
result.sex
result.date_of_birth_readable
result.date_of_birth_raw
result.expiration_date_readable
result.expiration_date_raw
result.estimated_issuing_date_readable
result.estimated_issuing_date_raw
result.optional_value
result.personal_number_raw
}
            

3.2 What you now get (barKoder) #

In the extra field, the JSON contains three variants of the data:
• “normal” – normalized values (for example, the document type for a passport is “P”)
• “formatted” – human-readable values (for example, the document type is “Passport”)
• “raw” – the full MRZ string

From scanningFinished:

                override fun scanningFinished(
results: Array&lt;Barkoder.Result&gt;?,
thumbnails: Array&lt;Bitmap&gt;?,
resultImage: Bitmap?
) {
  // 1. Check if we have any results
    if (results.isNullOrEmpty()) return
  // 2. Take the first scanned result
        val result = results[0]
  // 3. Find the JSON string in extra fields
        var jsonStr = ""
       result.extra?.forEach { kv -&gt;
            if (kv.key.equals("JSON", ignoreCase = true)) {
                jsonStr = kv.value?.trim() ?: ""
                  return@forEach
               }
                       }
        // 4. Parse the JSON if available
                if (jsonStr.isNotEmpty()) {
                         try {
       // Clean up string
               jsonStr = jsonStr.replace("\n", "")
                                .replace("\r", "")
                                .replace("\t", "")
       // Convert to JSON object
                    val mrzObject = JSONObject(jsonStr)
                    val fields = mrzObject.getJSONObject("normal")// "normal" = formatted
       // 5. Extract MRZ fields
                    val documentType = fields.optString("document_type")
                    val firstName = fields.optString("first_name")
                    val lastName = fields.optString("last_name")
                    val nationality = fields.optString("nationality")
                    val gender = fields.optString("gender")
                    val documentNumber = fields.optString("document_number")
                    val dateOfBirth = fields.optString("date_of_birth")
                    val dateOfExpiry = fields.optString("date_of_expiry")
                    val rawMRZ = mrzObject.optString("raw") // full MRZ string
               } catch (e: JSONException) {
                 Log.e("Barkoder", "JSON parsing error", e)
         }
      } else {
          Log.d("Barkoder", "No JSON data found in result")
     }
}
            


3.3 Side-by-side property differences #

Old New
document_typedocument_type
document_numberdocument_number
given_namesfirst_name
surnameslast_name
nationalitynationality
issuing_countryissuing_country
sexgender
date_of_birth_rawdate_of_birth
expiration_date_rawdate_of_expiry
estimated_issuing_date_rawdate_of_issuance_estimated
personal_number_rawpersonal_number
optional_valueoptional_data


4.Behavioral features: continuous scanning, duplicates, vibration #

4.1 Vibration #

MRZScanner #

                MRZScanner.setEnableVibrationOnSuccess(true)
            

barKoder #

                bkdView.config.isVibrateOnSuccessEnabled = true
            

4.2 Beep #

barKoder #

                bkdView.config.isBeepOnSuccessEnabled = true
            

4.3 Scan once then stop vs continuous scanning #

With MRZScanner you had:

                 mrzScanner.setContinuousScanningEnabled(false)
            

With barKoder, the equivalent behaviour is to close the session after the first result:
// SINGLE-SCAN MODE

                bkdView.config.isCloseSessionOnResultEnabled = true
            

For continuous scanning, keep the session open and tweak the duplicate threshold:

// keep session open

                bkdView.config.isCloseSessionOnResultEnabled = false
            


                bkdView.config.thresholdBetweenDuplicatesScans = 5
            

closeSessionOnResultEnabled controls whether scanning stops after the first result, and thresholdBetweenDuplicatesScans controls how often the same code is scanned.
If you previously used setIgnoreDuplicates(true) in MRZScanner,set:

                bkdView.config.thresholdBetweenDuplicatesScans = -1
            

// scan it only once, no duplicates


5.Quick “Old → New” Cheat Sheet #

5.1 Callbacks #

OLD #

                class ScannerActivity : AppCompatActivity(), MRZScannerListener,{
override fun successfulScanWithResult(resultModel: MRZResultModel) {
           }
  }
            

NEW #

                class MainActivity : AppCompatActivity(), BarkoderResultCallback {
override fun scanningFinished(results: Array&lt;Barkoder.Result&gt;?, thumbnails: Array&lt;Bitmap&gt;?, resultImage: Bitmap?) {
       }
 }
            

5.2 MRZ Mode #

OLD #

                mrzSanner?.setScannerType(scannerType)
MRZScanner.setIDActive(true)
MRZScanner.setPassportActive(true)
MRZScanner.setVisaActive(true)
            

NEW #

                bkdView.config.decoderConfig.IDDocument.enabled = true
            

Page Contents