SkillAgentSearch skills...

MLDocumentScanner

This project shows the implementation for the Machine Learning Document Scanner. The sample project contains a button, open the camera and scan the document, and using the Intent to open and preview the pdf file.

Install / Use

/learn @NicosNicolaou16/MLDocumentScanner

README

ML Document Scanner

Linktree Site X LinkedIn Medium YouTube Google Developer Profile

This project demonstrates the implementation of the Google ML Kit Document Scanner API in Android using Jetpack Compose. It provides a seamless interface to scan physical documents, digitize them, and handle the resulting PDF or JPEG files.

[!IMPORTANT]
Read the full technical guide here:
👉 Machine Learning Document (PDF) Scanner in Android - Medium 👈

✨ Features

  • High-Quality Scanning: Leverages Google's ML Kit for advanced edge detection and perspective correction.
  • Multi-Format Support: Export scans as high-quality JPEG images or as a multi-page PDF.
  • Customizable UI: Configure page limits, gallery imports, and scanner modes (Base, Filter, Full).
  • Compose Integration: Uses rememberLauncherForActivityResult for a clean, reactive implementation in Jetpack Compose.
  • Intent Preview: Automatically handles PDF URI results to open and preview documents in external viewers.

🛠️ Tech Stack

📸 Demo

<p align="left"> <a title="Document Scanner Demo"> <img src="examples/example_gif.gif" height="500" width="230"> </a> </p>

🚀 Quick Start

Step 1 - Add the library

Groovy

ext {
    playServicesMlkitDocumentScanner = "16.0.0"
}

dependencies {
    implementation 'com.google.android.gms:play-services-mlkit-document-scanner:$playServicesMlkitDocumentScanner'
}

Kotlin DSL

ext {
    playServicesMlkitDocumentScanner = "16.0.0"
}

dependencies {
    implementation("com.google.android.gms:play-services-mlkit-document-scanner:$playServicesMlkitDocumentScanner")
}

libs.versions.toml

[version]
playServicesMlkitDocumentScanner = "16.0.0"

[libraries]
play-services-mlkit-document-scanner = { group = "com.google.android.gms", name = "play-services-mlkit-document-scanner", version.ref = "playServicesMlkitDocumentScanner" }
dependencies {
    // ML Kit
    implementation(libs.play.services.mlkit.document.scanner)
}

Step 2 - Setup the Builder

Builder Configuration

val options = GmsDocumentScannerOptions.Builder().apply {
    setGalleryImportAllowed(false)
    setPageLimit(2)
    setResultFormats(RESULT_FORMAT_JPEG, RESULT_FORMAT_PDF)
    setScannerMode(SCANNER_MODE_FULL)
}.build()

Step 3 - Main Implementation

Get the PDF URI

@Composable
fun Scanner(
    innerPadding: PaddingValues
) {
    /**
     * registerForActivityResult for Activity/Fragment instead of the rememberLauncherForActivityResult (For Compose)
     * */
    val scannerLauncher =
        rememberLauncherForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) { result ->
            if (result.resultCode == RESULT_OK) {
                val data =
                    GmsDocumentScanningResult.fromActivityResultIntent(result.data)
                /**
                 * Option 1 to show the pdf as image uri
                 * */
                data?.pages?.let { pages ->
                    for (page in pages) {
                        val imageUri = page.imageUri
                    }
                }
                /**
                 * Option 2 to show the pdf as pdf uri
                 * */
                data?.pdf?.let { pdf ->
                    val pdfUri = pdf.uri
                    val pageCount = pdf.pageCount
                    // handle pdf uri and open it via Intent
                    openPdfWithIntent(pdfUri)
                }
            }
        }

    // Other Code Here - UI
}

Set the Builder Configuration

val scanner = GmsDocumentScanning.getClient(options)

UI

@Composable
fun Scanner(
    innerPadding: PaddingValues
) {
    //Other Code Here

    ElevatedButton(
        content = {
            Text(
                text = stringResource(id = R.string.scan),
                style = TextStyle(fontSize = 21.sp)
            )
        },
        modifier = Modifier.size(height = 70.dp, width = 250.dp),
        onClick = {
            /**
             * start the scanner
             * */
            scanner.getStartScanIntent(this@MainActivity)
                .addOnSuccessListener { intentSender ->
                    scannerLauncher.launch(
                        IntentSenderRequest.Builder(intentSender).build()
                    )
                }
                .addOnFailureListener {
                    Log.d("exception", "error")
                }
        }
    )
}

🔧 Versioning

  • Target SDK: 36
  • Minimum SDK: 29
  • Kotlin Version: 2.3.10
  • Gradle Version: 9.0.1

📚 References

⭐ Stargazers

If you enjoy this project, please give it a star! Check out all the stargazers here: Stargazers on GitHub

🙏 Support & Contributions

This project is actively maintained. Feedback, bug reports, and feature requests are welcome! Please feel free to open an issue or submit a pull request.

Related Skills

View on GitHub
GitHub Stars5
CategoryEducation
Updated1mo ago
Forks0

Languages

Kotlin

Security Score

90/100

Audited on Feb 27, 2026

No findings