Capture the bank cards using Bank Card Recognition feature by Huawei ML Kit in Android (Kotlin)
Tags: kotlin, mlkit, android, xml
Published: 2022-08-22 06:36:00


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6zilehpp4dt0baecwlxq.png)
**Introduction**

In this article, we can learn how to recognize bank cards using **Huawei ML Kit** of **Bank Card Recognition** feature. The bank card recognition service recognizes bank cards in camera streams within an angle offset of **15** degrees and extracts key information such as **card number** and **expiration date**. This service works with the **ID card** recognition service to offer a host of popular functions such as identity verification and bank **card number input**, making user operations easier than ever.

**Use Cases**

The bank card recognition service can extract bank card information in its original structure, which is useful for identity verification in financial services and bank card binding for payment in e-commerce apps. For example, in the past, when binding a bank card for online payment, users have to manually input their card numbers. It is easy to make mistakes. At present, with the bank card recognition service, inputting bank card numbers is automatic, thereby quick and accurate, greatly improving user experience.

**Precautions**

In the current version, only camera stream-based bank card recognition is supported.

**Requirements**

1. Any operating system (MacOS, Linux and Windows).

2. Must have a Huawei phone with HMS 4.0.0.300 or later.

3. Must have a laptop or desktop with Android Studio, Jdk 1.8, SDK platform 26 and Gradle 4.6 and above installed.

4. Minimum API Level 21 is required.

5. Required EMUI 9.0.0 and later version devices.

**How to integrate HMS Dependencies**

- First register as Huawei developer and complete identity verification in Huawei developers website, refer to register a [Huawei ID](https://developer.huawei.com/consumer/en/doc/start/registration-and-verification-0000001053628148).

- Create a project in android studio, refer [Creating an Android Studio Project](https://developer.huawei.com/consumer/en/codelab/HMSPreparation/index.html#1).

- Generate a **SHA-256 certificate fingerprint**.

- To generate **SHA-256 certificate fingerprint**. On right-upper corner of android project click **Gradle**, choose **Project Name > Tasks > android**, and then click **signingReport**, as follows.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/aflkigomqgjdn7n8z3bb.png)


Note: Project Name depends on the user created name.

- [Create an App in AppGallery Connect](https://developer.huawei.com/consumer/en/codelab/HMSPreparation/index.html#0).

- Download the **agconnect-services.json** file from **App information**, copy and paste in android **Project** under **app** directory, as follows.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wrk7ec8m5l2z96as99ur.png)


- Enter **SHA-256 certificate fingerprint** and click **Save** button, as follows.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hmzpl4uw1hfh8k15hhos.png)


- Click **Manage APIs** tab and enable **ML Kit**.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/i2896zmqv28akmezkikh.png)

- Add the below maven URL in **build.gradle(Project**) file under the repositories of **buildscript**, **dependencies** and **allprojects**, refer [Add Configuration](https://developer.huawei.com/consumer/en/codelab/HMSPreparation/index.html#6).

```
maven { url 'http://developer.huawei.com/repo/' }
classpath 'com.huawei.agconnect:agcp:1.4.1.300'
```


- Add the below plugin and dependencies in **build.gradle(Module)** file.

```
apply plugin: 'com.huawei.agconnect'
// Huawei AGC
implementation 'com.huawei.agconnect:agconnect-core:1.5.0.300'
// ML Kit Bank Card Recognition
implementation 'com.huawei.hms:ml-computer-card-bcr:3.5.0.300'
```

- Now Sync the gradle.

- Add the required permission to the **AndroidManifest.xml** file.

```
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
```


**Let us move to development**

I have created a project on Android studio with empty activity let us start coding.

In the **MainActivity.kt** we can find the business logic for buttons.

```
class MainActivity : AppCompatActivity() {

    var startCapture: Button? = null
    var permissions = arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA)

    private val callback: MLBcrCapture.Callback = object : MLBcrCapture.Callback {
        override fun onSuccess(bankCardResult: MLBcrCaptureResult) {
            // Processing for successful recognition.
            val stringBuffer = StringBuffer()
            stringBuffer.append("Issuer Name :" + bankCardResult.issuer)
            stringBuffer.append("\n")
            stringBuffer.append("Organization Name :" + bankCardResult.organization)
            stringBuffer.append("\n")
            stringBuffer.append("Card Number :" + bankCardResult.number)
            stringBuffer.append("\n")
            stringBuffer.append("Expiery Date :" + bankCardResult.expire)
            stringBuffer.append("\n")
            stringBuffer.append("Card Type :" + bankCardResult.type)
            stringBuffer.append("\n")
            createDialog(stringBuffer.toString())
        }
        override fun onCanceled() {
            // Processing for recognition request cancellation.
            Toast.makeText(this@MainActivity, "Cancelled", Toast.LENGTH_SHORT).show()
        }
        // Callback method used when no text is recognized or a system exception occurs during recognition.
        // retCode: result code.
        // bitmap: bank card image that fails to be recognized.
        override fun onFailure(retCode: Int, bitmap: Bitmap) {
            // Processing logic for recognition failure.
            Toast.makeText(this@MainActivity, retCode.toString(), Toast.LENGTH_SHORT).show()
        }
        override fun onDenied() {
            // Processing for recognition request deny scenarios, for example, the camera is unavailable.
            Toast.makeText(this@MainActivity, "Denied", Toast.LENGTH_SHORT).show()
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        requestPermission()
        startCapture = findViewById(R.id.start_capture)
        startCapture!!.setOnClickListener(View.OnClickListener { startCaptureActivity(callback) })

    }

    private fun startCaptureActivity(callback: MLBcrCapture.Callback) {
        val config = MLBcrCaptureConfig.Factory() // Set the expected result type of bank card recognition.
                // MLBcrCaptureConfig.RESULT_NUM_ONLY: Recognize only the bank card number.
                // MLBcrCaptureConfig.RESULT_SIMPLE: Recognize only the bank card number and validity period.
                // MLBcrCaptureConfig.ALL_RESULT: Recognize information such as the bank card number, validity period, issuing bank, card organization, and card type.
                .setResultType(MLBcrCaptureConfig.RESULT_ALL) // Set the recognition screen display orientation.
                // MLBcrCaptureConfig.ORIENTATION_AUTO: adaptive mode. The display orientation is determined by the physical sensor.
                // MLBcrCaptureConfig.ORIENTATION_LANDSCAPE: landscape mode.
                // MLBcrCaptureConfig.ORIENTATION_PORTRAIT: portrait mode.
                .setOrientation(MLBcrCaptureConfig.ORIENTATION_AUTO)
                .create()
        val bankCapture = MLBcrCaptureFactory.getInstance().getBcrCapture(config)
        bankCapture.captureFrame(this, callback)
    }

    private fun requestPermission() {
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED ||
            ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, permissions, 111)
        }
    }

    @SuppressLint("InflateParams")
    private fun createDialog(retrievedText: String) {
        val wm = this@MainActivity.getSystemService(WINDOW_SERVICE) as WindowManager
        val width = wm.defaultDisplay.width
        val height = wm.defaultDisplay.height
        val dialog = Dialog(this@MainActivity, R.style.MyDialog)
        val view: View = LayoutInflater.from(this@MainActivity).inflate(R.layout.layout_for_dialog, null)
        (view.findViewById<View>(R.id.retrieved_information) as TextView).text = retrievedText
        val params = dialog.window!!.attributes
        params.width = WindowManager.LayoutParams.MATCH_PARENT
        params.height = WindowManager.LayoutParams.WRAP_CONTENT
        dialog.setContentView(view)
        dialog.window!!.setGravity(Gravity.CENTER)
        dialog.window!!.setWindowAnimations(R.style.MyDialog)
        dialog.show()
    }


}
```


In the **activity_main.xml** we can create the UI screen.

```
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/start_capture"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Start Capture"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
```

The layout for the dialog is **layout_for_dialog.xml**.

```
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <TextView
            android:id="@+id/retrieved_information"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingLeft="10dp"
            android:paddingRight="10dp"
            android:scrollbars="vertical"
            android:textColor="@color/black" />
    </LinearLayout>

</ScrollView>
```

**Demo**


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qd9ozsg8uobpfwt13biy.gif)

**Tips and Tricks**

1. Make sure you are already registered as Huawei developer.

2. Set minSDK version to 21 or later, otherwise you will get AndriodManifest merge issue.

3. Make sure you have added the agconnect-services.json file to app folder.

4. Make sure you have added SHA-256 fingerprint without fail.

5. Make sure all the dependencies are added properly.

**Conclusion**

In this article, we have learned how to recognize bank cards using **Huawei ML Kit** of **Bank Card Recognition** feature. The bank card recognition service recognizes bank cards in camera streams within an angle offset of **15 degrees** and extracts key information such as **card number** and **expiration** **date**. This service works with the **ID card** recognition service to offer a host of popular functions such as identity verification and bank **card number input**, making user operations easier than ever.

I hope you have read this article. If you found it is helpful, please provide likes and comments.

**Reference**

**ML Kit** – [Bank Card Recognition](https://developer.huawei.com/consumer/en/doc/development/hiai-Guides/bank-card-recognition-0000001050038118)

**ML Kit** – [Training Video](https://developer.huawei.com/consumer/en/training/course/video/101628260104789916)