Skip to content

About

Google ML Kit Document Scanner for Delphi/FMX Android — JPEG & PDF output, one unit, zero UI code

Resources

Stars

17 stars

Watchers

2 watching

Forks

Latest commit

 

History

4 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 

Repository files navigation

delphi-docscanner

A production-ready Delphi/FMX JNI bridge for Google ML Kit Document Scanner on Android. Scan documents with automatic edge detection, perspective correction, and cropping — output as JPEG or multi-page PDF.

One unit. One singleton call. Zero UI code.

Features

  • Automatic document detection and edge recognition
  • Perspective correction and cropping
  • JPEG output (per page) and PDF output (multi-page)
  • Gallery import support
  • ML Kit availability check (IsMLKitAvailable)
  • Re-entrancy protection (IsScanning)
  • Configurable output directory (OutputSubDir)

Requirements

  • RAD Studio 12 Athens or later
  • Target platform: Android 32-bit or 64-bit
  • Minimum Android API: 21 (Android 5.0)
  • Google Play Services on the target device

Installation

1. Download the dependencies

The scanner requires two Android libraries. They are published as .aar files on Google's Maven repository (not Maven Central — com.google.android.gms:* artifacts are only hosted by Google):

Dependency Version Direct download (.aar)
play-services-mlkit-document-scanner 16.0.0 dl.google.com
mlkit-common (com.google.mlkit:common) 18.11.0 dl.google.com

RAD Studio's Java references only accepts .jar files, so extract the classes.jar from inside each .aar (an .aar is a ZIP archive), rename it (e.g. play-services-mlkit-document-scanner-16.0.0.jar) and put it in your project's lib\ folder.

Alternative: Download via Gradle

Create a build.gradle in your lib\ folder — this resolves all transitive dependencies automatically:

plugins { id 'java' }
repositories {
    google()
    mavenCentral()
}
configurations { mlkit }
dependencies {
    mlkit 'com.google.android.gms:play-services-mlkit-document-scanner:16.0.0'
}
task copyDeps(type: Copy) {
    from configurations.mlkit
    into "$projectDir/deps"
}

Run: gradle copyDeps

2. Add the JARs to your Delphi project

In RAD Studio:

  1. Project > Options > Delphi Compiler > Other > Java references
  2. Add both .jar files (the classes.jar extracted from each .aar)
  3. Set Container to Classes.dex

3. Add Search Path

Add the path to Source\ to your Delphi project search path:

Project > Options > Delphi Compiler > Search path:

<path-to>\delphi-docscanner\Source

4. AndroidManifest.template.xml

Add the following entries inside the <application> tag of your AndroidManifest.template.xml:

<!-- Google ML Kit Document Scanner -->
<service
    android:name="com.google.mlkit.common.internal.MlKitComponentDiscoveryService"
    android:exported="false"
    android:directBootAware="true">
    <meta-data
        android:name="com.google.firebase.components:com.google.mlkit.common.internal.CommonComponentRegistrar"
        android:value="com.google.firebase.components.ComponentRegistrar" />
</service>

<activity
    android:name="com.google.mlkit.vision.documentscanner.internal.GmsDocumentScanningDelegateActivity"
    android:exported="false"
    android:screenOrientation="portrait"
    android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen" />

Important: These entries must be placed inside <application>...</application>, not at the root level. Without them, the scanner will fail silently at runtime.

Quick Start

uses
  mxDocScannerUnit;

procedure TForm1.btnScanClick(Sender: TObject);
begin
  if not TmxDocScanner.Instance.IsMLKitAvailable then
  begin
    ShowMessage('ML Kit Document Scanner not available on this device.');
    Exit;
  end;

  TmxDocScanner.Instance.StartScan(
    5,           // max pages
    True,        // allow gallery import
    dsfJPEG,     // output format: dsfJPEG or dsfPDF
    procedure(const AFilePath: string; APageIndex, ATotalPages: Integer)
    begin
      // Called once per page (JPEG) or once (PDF)
      ShowMessage('Page ' + IntToStr(APageIndex + 1) + ': ' + AFilePath);
    end,
    procedure(const AErrorMessage: string)
    begin
      ShowMessage('Error: ' + AErrorMessage);
    end
  );
end;

Custom output directory

Scanned files are saved to <SharedPictures>/<OutputSubDir>/. The default subdirectory is mxDocScanner. To change it:

TmxDocScanner.Instance.OutputSubDir := 'MyApp';

Set this before calling StartScan.

API Reference

TmxDocScanner

Member Description
class function Instance: TmxDocScanner Singleton access
class procedure ReleaseInstance Free the singleton (typically not needed)
function IsMLKitAvailable: Boolean Check if ML Kit Document Scanner is available on the device
procedure StartScan(...) Start a document scan
property IsScanning: Boolean True while a scan is in progress
property OutputSubDir: string Subdirectory name for scanned files (default: 'mxDocScanner')

StartScan parameters

Parameter Type Description
AMaxPages Integer Maximum number of pages to scan
AGalleryImport Boolean Allow importing images from gallery
AFormat TDocScanFormat dsfJPEG for JPEG per page, dsfPDF for multi-page PDF
AOnPageResult TDocScanPageCallback Called per scanned page with file path, page index, and total pages. In PDF mode, JPEG callbacks fire first (for preview), then one PDF callback.
AOnError TDocScanErrorCallback Called on error or cancellation with message
AMode TDocScanMode Scanner mode (optional, default: dsmFull)

Types

TDocScanMode   = (dsmBase, dsmBaseWithFilter, dsmFull);
TDocScanFormat = (dsfJPEG, dsfPDF);

TDocScanPageCallback  = reference to procedure(
  const AFilePath: string; APageIndex, ATotalPages: Integer);
TDocScanErrorCallback = reference to procedure(
  const AErrorMessage: string);

Scanner modes

Mode Description
dsmBase Basic scanning (edge detection, cropping)
dsmBaseWithFilter Basic scanning + image filters
dsmFull Full features: edge detection, cropping, rotation, filters (default)

PDF mode behavior

In PDF mode (dsfPDF), the scanner delivers both JPEG and PDF results:

  1. AOnPageResult is called once per page with the JPEG file path (useful for preview)
  2. AOnPageResult is called once more with the PDF file path

This allows apps to show page previews while also receiving the final PDF for upload or storage.

Edge Cases

Scenario Behavior
Device without Google Play Services IsMLKitAvailable returns False
User cancels scan Error callback fires with 'Scan cancelled', IsScanning resets to False
PDF mode with 1 page Produces a single-page PDF, JPEG preview callback fires first
Multiple concurrent scan calls Blocked by IsScanning check, error callback fired
Non-Android platform StartScan fires error callback: 'Document Scanner is only available on Android'

Known Limitations

  • Internal ML Kit API: The unit uses com.google.mlkit.common.sdkinternal.MlKitContext for manual initialization, which is an internal Google API. This is necessary because Delphi does not support Android ContentProvider-based auto-initialization. The class has been stable across ML Kit versions, but could change without notice in future SDK updates.
  • Google Play Services required: The scanner depends on Google Play Services. Devices without GMS (e.g., Huawei) are not supported. Use IsMLKitAvailable to check at runtime.
  • Singleton pattern: TmxDocScanner is designed for main-thread use. Do not call StartScan from background threads.

Cleanup

The singleton is automatically released in the finalization section. To release it manually:

TmxDocScanner.ReleaseInstance;

License

MIT License — see LICENSE for details.

Copyright (c) 2026 MicrotronX - Speditionssoftware vom Profi

About

Google ML Kit Document Scanner for Delphi/FMX Android — JPEG & PDF output, one unit, zero UI code

Resources

Stars

17 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages