DEV Community

Cover image for Building an AI Receipt Scanner for Android with Kotlin and ML Kit
Sunasara MohsinAli
Sunasara MohsinAli

Posted on

Building an AI Receipt Scanner for Android with Kotlin and ML Kit

Building an AI Receipt Scanner for Android with Kotlin and ML Kit

Receipts contain a lot of useful information: purchase dates, product names, prices, sellers, invoice numbers, and sometimes warranty details.

The problem is that most receipts are still stored as images, PDFs, emails, or physical paper.

If you're building a mobile app that needs to turn receipts into structured data, simple OCR is only the beginning.

In this article, I'll explain the approach I used to build an AI-powered receipt scanning workflow for an Android application.

The project is part of Wornivo, a warranty and subscription management app designed to help users organize receipts, warranties, and recurring subscriptions.


The Problem

A user may have hundreds of receipts spread across:

  • Email
  • WhatsApp
  • Gallery
  • Downloads
  • Cloud storage
  • Physical documents

Manually entering every receipt into an app isn't a great experience.

For example, a receipt might contain:

text
ABC ELECTRONICS

Samsung Galaxy S25
Purchase Date: 12/04/2026
Amount: ₹74,999

Warranty: 12 Months
Invoice No: INV-29382

The goal is to turn this unstructured document into useful structured information.

The basic workflow looks like this:

Receipt Image
      ↓
OCR
      ↓
Raw Text
      ↓
AI Extraction
      ↓
Structured Data
      ↓
Database
Enter fullscreen mode Exit fullscreen mode

1. Capturing the Receipt

The first step is getting a good image.

A mobile camera can introduce several problems:

Perspective distortion
Poor lighting
Blur
Shadows
Reflections
Cropped receipts

For Android applications, CameraX is a practical option for building the camera layer.

The basic flow is:

CameraX

Capture Image

Crop / Improve Image

OCR

The better the input image, the better the OCR result.

2. Extracting Text with ML Kit

Once the image is captured, the next step is OCR.

Google ML Kit provides on-device text recognition that can be used to extract text from images.

A simplified implementation can look like this:

val image = InputImage.fromFilePath(context, imageUri)

recognizer.process(image)
    .addOnSuccessListener { result ->
        val extractedText = result.text

        // Send extracted text to the next processing step
    }
    .addOnFailureListener {
        // Handle OCR failure
    }
Enter fullscreen mode Exit fullscreen mode

The result might look like:

ABC ELECTRONICS
Samsung Galaxy S25
12/04/2026
₹74,999
INV-29382
Warranty 12 Months

This is useful, but OCR doesn't actually understand what each value means.

It only gives us text.

3. OCR Is Not the Same as Data Extraction

This is one of the important lessons when building receipt-processing workflows.

OCR answers:

What text is visible in this image?

But the application needs to answer:

What does this text mean?

For example:

12/04/2026

could represent:

Purchase date
Invoice date
Delivery date
Warranty start date

Similarly:

₹74,999

could represent:

Product price
Discounted price
Total amount
Tax-inclusive amount

This is where structured extraction becomes important.

4. Using AI to Understand the Receipt

After OCR, the extracted text can be processed by an AI model.

Instead of asking the model for a simple summary, the application can request structured fields.

For example:

{
  "merchant": "ABC Electronics",
  "product_name": "Samsung Galaxy S25",
  "purchase_date": "2026-04-12",
  "price": 74999,
  "currency": "INR",
  "invoice_number": "INV-29382",
  "warranty_months": 12
}
Enter fullscreen mode Exit fullscreen mode

Now the application has data that can actually be used by the rest of the product.

The important distinction is:

OCR = Text extraction

AI = Meaning and structured extraction

Combining the two creates a much more useful workflow.

5. Why Structured JSON Matters

Returning structured data makes the rest of the application easier to build.

Instead of passing around a large text string:

ABC Electronics Samsung Galaxy S25...

the application can work with defined fields:

data class ReceiptData(
    val merchant: String?,
    val productName: String?,
    val purchaseDate: String?,
    val price: Double?,
    val currency: String?,
    val invoiceNumber: String?,
    val warrantyMonths: Int?
)
Enter fullscreen mode Exit fullscreen mode

The extracted information can then be validated and stored locally.

6. Storing Receipt Data Locally

For an Android application, local persistence is important.

A saved receipt shouldn't become inaccessible just because the user temporarily loses internet connectivity.

A common architecture is:

UI
 ↓
ViewModel
 ↓
Repository
 ↓
Room Database

A receipt record could contain:

Receipt
├── id
├── merchant
├── productName
├── purchaseDate
├── price
├── invoiceNumber
├── warrantyMonths
└── warrantyExpiryDate
Enter fullscreen mode Exit fullscreen mode

Room also makes it easier to search and filter saved purchase information.

7. Automatically Calculating Warranty Expiry

Once the purchase date and warranty duration are available, the application can calculate the warranty expiry date.

For example:

Purchase Date
12 April 2026

Warranty
12 Months

Expiry
12 April 2027

This turns a basic receipt scanner into a useful warranty-management workflow.

Instead of simply storing a receipt, the application can use the extracted information to create a reminder.

8. Handling Imperfect Receipts

Real-world receipts are messy.

A production application cannot assume that every receipt will look like a clean example.

Missing Warranty Information

The receipt might not contain the warranty period.

The application should not invent a value.

Instead:

Warranty: Not detected

The user can then add the information manually.

Poor OCR

If the image is blurry, OCR may produce incorrect text.

The application should provide a review and edit step before saving important information.

Multiple Dates

A receipt can contain several dates.

The extraction layer should distinguish between:

Purchase Date
Invoice Date
Delivery Date
Warranty Expiry

rather than blindly selecting the first date it finds.

Multiple Products

A single invoice can contain multiple products.

A more advanced structure could look like:

{
  "merchant": "ABC Electronics",
  "purchase_date": "2026-04-12",
  "items": [
    {
      "name": "Samsung Galaxy S25",
      "price": 74999
    },
    {
      "name": "Phone Case",
      "price": 1499
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

9. Validation Is Important

AI extraction can be useful, but AI output should not automatically be treated as perfect data.

Important fields should be validated before saving.

For example:

Purchase Date
✓ Valid date

Price
✓ Valid amount

Warranty
⚠ Not detected

The user should also be able to correct extracted information.

This is especially important when processing documents from different stores and invoice formats.

10. Offline-First Architecture

For a receipt and warranty management application, local data availability is important.

A simplified architecture can look like this:

            Android App
                |
      +---------+---------+
      |                   |
   Camera              Local DB
      |                  Room
      ↓                   |
    OCR                   |
      ↓                   |
     AI                   |
      ↓                   |
Enter fullscreen mode Exit fullscreen mode

Structured Data ------------+

Previously saved receipts and warranty information can remain available even when the network isn't available.

Cloud or AI processing can be used where necessary, while local persistence can handle the user's saved records.

11. From Receipt Scanner to Warranty Manager

A basic receipt scanner does this:

Image → Text

A more useful workflow does this:

Image
  ↓
OCR
  ↓
AI Extraction
  ↓
Product
  ↓
Purchase Date
  ↓
Warranty
  ↓
Expiry Date
  ↓
Reminder
Enter fullscreen mode Exit fullscreen mode

The final result isn't just extracted text.

It becomes actionable information.

For example:

Your laptop warranty expires in 30 days.

That's much more useful than simply having a photo of the invoice sitting in a gallery.

12. The Same Architecture Can Handle Subscriptions

The same concept can also be applied to recurring subscriptions.

For example:

Netflix
₹649 / month
Renewal: 15th

Spotify
₹119 / month
Renewal: 22nd

Cloud Storage
₹130 / month
Renewal: 5th

Now the application can help users understand recurring spending in addition to managing warranties.

This is another part of the problem Wornivo is designed to address.

13. Lessons From Building This Workflow

There are several important lessons when building this type of feature.

  1. OCR alone isn't enough

Text recognition is only the first step.

The application still needs to understand the meaning of the extracted text.

  1. AI output needs validation

AI can produce incomplete or incorrect information.

Important fields should be validated before being stored.

  1. Users need an edit step

Even good OCR and AI extraction can make mistakes.

Users should always be able to review and correct extracted information.

  1. Don't invent missing information

If the receipt doesn't contain a warranty period, the application should return something like:

Warranty: Not detected

instead of guessing.

  1. Local persistence matters

Previously saved purchase information should remain accessible even when the user is offline.

The Complete Architecture

The complete workflow can be represented as:

CameraX
                ↓
          Receipt Image
                ↓
        Image Processing
                ↓
            ML Kit OCR
                ↓
          Extracted Text
                ↓
          AI Processing
                ↓
        Structured Receipt
                ↓
          Validation / Edit
                ↓
           Room Database
                ↓
      Warranty / Subscription
                ↓
            Reminders
Enter fullscreen mode Exit fullscreen mode

Each layer has a specific responsibility.

This makes the system easier to maintain and gives you more flexibility when improving individual components.

Building It for a Real Product

This receipt-scanning workflow is part of Wornivo, a mobile application focused on managing warranties, receipts, invoices, and subscriptions.

The goal is simple:

Turn scattered purchase information into organized, useful records.

Instead of keeping a receipt as just another image in your gallery, the application can turn it into information that can be searched, managed, and used for reminders.

You can learn more about Wornivo here:

Wornivo App: https://play.google.com/store/apps/details?id=com.mobicolon.warrivo

Website Link : https://wornivo.com/
Conclusion

Building an AI receipt scanner isn't just about adding OCR to an Android application.

The real challenge is turning messy real-world documents into reliable, structured information.

The overall pipeline is:

Capture
   ↓
OCR
   ↓
AI Extraction
   ↓
Validation
   ↓
Local Storage
   ↓
Actionable Information
Enter fullscreen mode Exit fullscreen mode

For warranty management, that information can become a warranty expiry reminder.

For subscriptions, it can become a renewal and spending tracker.

For users, the end result is much simpler:

Less searching. Less manual entry. Better organization.

If you're building something similar, I'd be interested to hear how you're handling OCR accuracy, AI extraction, and validation in your own Android projects.

Top comments (0)