fix OCR in apx

This commit is contained in:
davmar
2026-08-29 18:02:35 +02:00
parent b3171d921b
commit 35d5c90d81
4 changed files with 36 additions and 12 deletions
+4
View File
@@ -34,6 +34,10 @@ android {
// TODO: Add your own signing config for the release build. // TODO: Add your own signing config for the release build.
// Signing with the debug keys for now, so `flutter run --release` works. // Signing with the debug keys for now, so `flutter run --release` works.
signingConfig = signingConfigs.getByName("debug") signingConfig = signingConfigs.getByName("debug")
// Flutter turns R8 on for release. That strips ML Kit classes
// discovered via manifest metadata / JNI, so OCR fails in the APK.
isMinifyEnabled = false
isShrinkResources = false
proguardFiles( proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"), getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro", "proguard-rules.pro",
+15 -10
View File
@@ -1,10 +1,15 @@
# ML Kit text recognition ships Latin only; the plugin still references # ML Kit text recognition is wired up through manifest metadata, reflection,
# optional script packs that are not in this app. # and JNI. R8 otherwise strips those classes and OCR fails in release APKs.
-dontwarn com.google.mlkit.vision.text.chinese.ChineseTextRecognizerOptions$Builder -keep class com.google.mlkit.** { *; }
-dontwarn com.google.mlkit.vision.text.chinese.ChineseTextRecognizerOptions -keep class com.google.android.gms.internal.mlkit_** { *; }
-dontwarn com.google.mlkit.vision.text.devanagari.DevanagariTextRecognizerOptions$Builder -keep class com.google.android.gms.internal.mlkit_vision_** { *; }
-dontwarn com.google.mlkit.vision.text.devanagari.DevanagariTextRecognizerOptions -keep class com.google.android.libraries.vision.** { *; }
-dontwarn com.google.mlkit.vision.text.japanese.JapaneseTextRecognizerOptions$Builder -keep class com.google_mlkit_commons.** { *; }
-dontwarn com.google.mlkit.vision.text.japanese.JapaneseTextRecognizerOptions -keep class com.google_mlkit_text_recognition.** { *; }
-dontwarn com.google.mlkit.vision.text.korean.KoreanTextRecognizerOptions$Builder -keep class * implements com.google.firebase.components.ComponentRegistrar { *; }
-dontwarn com.google.mlkit.vision.text.korean.KoreanTextRecognizerOptions
# The Flutter plugin references optional script packs that this app does not ship.
-dontwarn com.google.mlkit.vision.text.chinese.**
-dontwarn com.google.mlkit.vision.text.devanagari.**
-dontwarn com.google.mlkit.vision.text.japanese.**
-dontwarn com.google.mlkit.vision.text.korean.**
+2
View File
@@ -1,5 +1,7 @@
org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError
android.useAndroidX=true android.useAndroidX=true
# Flutter enables R8 for release by default. That breaks on-device ML Kit OCR.
shrink=false
# This newDsl flag was added by the Flutter template # This newDsl flag was added by the Flutter template
android.newDsl=false android.newDsl=false
# This builtInKotlin flag was added by the Flutter template # This builtInKotlin flag was added by the Flutter template
+15 -2
View File
@@ -103,10 +103,17 @@ class _ScanScreenState extends State<ScanScreen> {
_error = 'No text found in this image.'; _error = 'No text found in this image.';
} }
}); });
} catch (error) { } on PlatformException catch (error) {
debugPrint('OCR failed: ${error.code} ${error.message}');
if (!mounted) return; if (!mounted) return;
setState(() { setState(() {
_error = 'Could not read text from this image.'; _error = _ocrFailureMessage(error.message);
});
} catch (error) {
debugPrint('OCR failed: $error');
if (!mounted) return;
setState(() {
_error = _ocrFailureMessage(error.toString());
}); });
} finally { } finally {
await recognizer.close(); await recognizer.close();
@@ -120,6 +127,12 @@ class _ScanScreenState extends State<ScanScreen> {
} }
} }
String _ocrFailureMessage(String? detail) {
const fallback = 'Could not read text from this image.';
if (detail == null || detail.trim().isEmpty) return fallback;
return '$fallback\n$detail';
}
Future<void> _openReview(String rawText) async { Future<void> _openReview(String rawText) async {
final items = ReceiptParser.parse(rawText); final items = ReceiptParser.parse(rawText);
if (!mounted) return; if (!mounted) return;