Flower Identifier Android demonstrates a complete on-device image classification path for 102 flower classes. It combines system image input, bounded bitmap decoding, TensorFlow Lite inference, lifecycle-aware state management, and a compact Material 3 interface.
Curated repository notice
This repository contains a curated engineering demonstration of the published Flower Identifier Android application. The complete production UI, proprietary visual design, animations, music, branding implementation, and original screen architecture are intentionally not included.
The screenshots below show the real application published on Google Play. The source code in this repository uses a simplified Material 3 interface to demonstrate the underlying Android and TensorFlow Lite engineering.
The following screenshots are from the production application available on Google Play. The public repository intentionally uses a simplified demonstration interface and does not include the complete production UI source.
View the published FlowerApp application on Google Play
- Recognizes 102 flower categories with a MobileNetV2 TensorFlow Lite model.
- Runs inference fully on the Android device with no image upload.
- Accepts gallery input through the system Photo Picker.
- Captures camera input through a non-exported
FileProviderand app cache. - Reports the top-one label, confidence, and inference-only latency.
- Uses a
ViewModelandStateFlowfor predictable UI state. - Validates model tensor types, shapes, and label alignment at runtime.
- Bounds bitmap decoding and honors EXIF orientation.
- Requests no Internet or broad storage permission.
- Includes no analytics, advertisements, tracking, Firebase, or backend service.
The curated demo separates UI, state, image handling, and inference responsibilities. The classifier is loaded lazily, reused across predictions, serialized for safe access, and closed with the ViewModel lifecycle. Decode and inference work run away from the main thread. The UI presents explicit idle, loading, success, and error states.
Compose UI -> FlowerViewModel -> FlowerImageProcessor -> SafeBitmapDecoder
-> ImagePreprocessor
-> FlowerClassifier
-> TensorFlow Lite
MainActivityhosts the Compose application and ViewModel.FlowerDemoScreenrenders controls, preview, status, and prediction output.FlowerUiStatedefines idle, loading, success, and error states.FlowerViewModelcoordinates work and exposes state throughStateFlow.FlowerImageProcessorconnects image decoding to classification.SafeBitmapDecoderbounds decoded dimensions and applies EXIF orientation.TemporaryCameraFileManagermanages scoped cache files and cleanup.ImagePreprocessorresizes images and writes normalized RGB tensors.FlowerClassifierowns the interpreter and validates the model contract.PredictionSelectorperforms deterministic top-one selection.
- Choose an image with the system Photo Picker or capture one with the camera.
- Decode the image at a bounded size and correct its orientation.
- Resize it to 224 x 224 and normalize RGB values.
- Run the TensorFlow Lite model locally.
- Select the highest output value and display its label, confidence, and latency.
- Remove temporary camera content after processing or cancellation.
The model is loaded once when first needed. Before inference, the application confirms that the runtime model exposes the expected input and output tensors and that 102 labels are available. The input buffer is rewound before each invocation. Output values already represent the model's softmax probabilities, so the application applies top-one argmax without a second softmax.
| Item | Value |
|---|---|
| Model | MobileNetV2 TensorFlow Lite |
| Input shape | 1 x 224 x 224 x 3 |
| Input type | FLOAT32 |
| Color format | RGB |
| Normalization | Pixel values divided by 255.0 |
| Output shape | 1 x 102 |
| Output type | FLOAT32 |
| Output activation | Softmax |
| Selection | Top-one argmax |
| Labels | 102 |
The Android application uses the same TensorFlow Lite model and 102-class label mapping published in the related Flower Classification project.
Selected images are decoded with a bounded target size before a 224 x 224 model bitmap is produced. RGB channels are written as FLOAT32 values divided by 255.0. Android 9 and newer use ImageDecoder; Android 8 uses sampled BitmapFactory decoding. EXIF orientation is applied where needed.
FlowerViewModel publishes immutable state through StateFlow. Each request moves through loading and then either success or error. Reset returns the UI to idle and releases preview data. The image processor performs decode and inference work on a background dispatcher.
- Inference runs locally on the device.
- The app does not request Internet permission.
- Gallery images are accessed through the system Photo Picker and are not permanently copied by the demo.
- Camera captures use temporary app cache storage exposed through a non-exported
FileProvider. - Temporary camera files are removed after processing, cancellation, reset, or stale-file cleanup.
- No image is uploaded.
- No analytics, advertisements, tracking, Firebase, or backend service is included.
- No broad storage permission is requested.
The displayed latency measures only the TensorFlow Lite interpreter invocation. It excludes image selection, camera interaction, bitmap decoding, and UI rendering. Timing varies by device, Android version, thermal state, and current system load, so the repository does not claim a guaranteed latency.
.
├── app/
│ ├── build.gradle.kts
│ └── src/
│ ├── main/
│ │ ├── assets/ # TensorFlow Lite model and labels
│ │ ├── java/.../flowerapp/
│ │ │ ├── classifier/ # Contract, preprocessing, selection
│ │ │ ├── data/ # Image processing coordinator
│ │ │ ├── ui/ # Simplified Compose demo
│ │ │ ├── utils/ # Decode and temporary file handling
│ │ │ ├── viewmodel/ # StateFlow application state
│ │ │ └── MainActivity.kt
│ │ └── res/ # Generic app resources and safe XML
│ └── test/ # Local unit tests
├── docs/images/
│ ├── branding/ # Approved application logo
│ └── google-play/ # Official published screenshots
├── gradle/ # Version catalog and wrapper
├── build.gradle.kts
├── settings.gradle.kts
├── README.md
├── LICENSE
└── THIRD_PARTY_NOTICES.md
- Kotlin
- Android SDK 36, minimum SDK 26
- Jetpack Compose and Material 3
- AndroidX Lifecycle, ViewModel, and StateFlow integration
- Android Photo Picker, Activity Result APIs, and FileProvider
- AndroidX ExifInterface
- TensorFlow Lite and TensorFlow Lite Support
- JUnit 4 for local tests
- Android Studio with a compatible recent version
- JDK 17 or newer
- Android SDK 36
- Included Gradle wrapper
- Clone the future repository.
- Open the repository root in Android Studio.
- Allow Gradle to sync.
- Ensure Android SDK 36 is installed.
- Run the
appconfiguration on an Android 8.0 or newer device.
To run the verified local validation sequence:
./gradlew --no-daemon clean :app:testDebugUnitTest :app:lintDebug :app:assembleDebugThe validation suite covers the model contract, image preprocessing, temporary camera file cleanup, ViewModel state transitions, startup behavior, and privacy policy constraints.
- 16 local unit tests passed with 0 failures.
- Android lint completed with 0 errors and 17 warnings.
- Debug assembly passed.
- Instrumentation tests were not run.
- The project owner completed manual Android Studio and device testing successfully.
The remaining lint warnings are dependency and version advisories plus upstream TensorFlow Lite native-library 16 KB alignment notices. The repository does not claim zero warnings.
Model training, dataset preparation, evaluation, and TensorFlow Lite conversion are documented in the separate Flower Classification repository. This Android repository focuses on safe on-device integration and does not include the Oxford dataset images.
The published production application is available at:
https://play.google.com/store/apps/details?id=com.zaeri.sabourinia.flowerapp
The Google Play listing represents the released application. This repository does not contain its complete production UI source.
- The curated interface is an engineering demonstration, not the production interface.
- Classification is limited to the 102 trained flower categories.
- The model does not implement calibrated uncertainty or non-flower rejection.
- Results can be incorrect and should not be treated as scientific identification.
- Latency and behavior vary across Android devices.
- Device instrumentation coverage is not included in this repository.
- Upstream model, dataset, dependency, and media terms remain applicable.
Alireza Zaeri and Fatemeh Sabourinia
This project's original source code is licensed under the MIT License. See the LICENSE file for details.
The MIT License does not automatically relicense third-party dependencies, pretrained components, datasets, model inputs, Google Play materials, or documentation images. See THIRD_PARTY_NOTICES.md.
Upstream projects and data sources retain their own terms. See THIRD_PARTY_NOTICES.md for component links, license notes, and model and dataset limitations.






