DinoHub is a local-first Android app for AI-powered image analysis using Gemini Nano — Google's on-device large language model. Point the camera at something, pick an expert persona, and get an analysis without your image ever leaving the device.
The name comes from the original use case: identifying fossils. But the expert system is fully customizable — you can create any persona with any system prompt.
Requires a device with Gemini Nano support (Pixel 9 series or newer with AICore installed).
- Expert personas — Create named experts with custom system prompts (e.g. paleontologist, geologist, botanist). Switch between them from the camera screen.
- On-device inference — All processing runs locally via Google ML Kit's Gemini Nano. No network calls, no data uploaded.
- Streaming responses — Analysis text streams in token-by-token in real time.
- Follow-up questions — Ask follow-up questions on any analysis. The full conversation history (image turn + Q&A) is folded into each inference request.
- Conversation memory — Optionally inject an expert's past analyses as context for new captures. Configurable window size.
- Truncation handling — When Gemini Nano hits its token limit, a Continue button resumes the response from where it left off.
- Full-screen image viewer — Tap any fossil image to view it full-screen. Save to gallery or share directly from the detail view.
- Markdown rendering — Analysis output is rendered as formatted markdown once the response completes.
- In-app log console — Settings screen exposes a live log console for debugging inference requests and token counts.
- Background processing — WorkManager runs inference off the main thread so the UI stays responsive.
- Android Studio Meerkat or newer
- Android device running API 26+ (Android 8.0+)
- Gemini Nano availability: Pixel 9 / Pixel 9 Pro / Pixel 9 Pro XL / Pixel 9 Pro Fold with AICore
- On the device: Settings → Apps → AI Core → ensure it is installed and up to date
-
Clone the repository:
git clone https://github.com/dev-ansung/Dino.git cd Dino -
Open the project in Android Studio.
-
Connect a supported Pixel device via USB with developer mode enabled.
-
Run the
appconfiguration. The app will install and launch. -
On first launch, open Settings and check the Gemini Nano status. If it shows Downloadable, tap Download Model and wait for the download to complete before capturing.
The app requests:
CAMERA— required for image capture
DinoHub follows a layered architecture with clear separation between data, inference, and UI.
app/
└── src/main/java/dev/ansung/dino/
├── data/local/ # Room database
│ ├── entities/ # ExpertEntity, TaskEntity, FossilEntity, FollowUpEntity
│ ├── dao/ # ExpertDao, TaskDao, FossilDao, FollowUpDao
│ └── AppDatabase.kt # Room DB v6, migrations 1→6
├── engine/ # Inference layer
│ ├── DinoEngine.kt # Shared data classes: HistoryMessage, AnalyzeResult, EngineStatus
│ ├── NanoEngineImpl.kt# ML Kit Gemini Nano client wrapper
│ └── InferenceRunner.kt # Orchestrates initial analysis, continuation, follow-ups
├── worker/
│ └── ProcessingWorker.kt # WorkManager CoroutineWorker for background inference
├── ui/
│ ├── main/ # Camera preview, expert selector, capture flow
│ ├── history/ # Fossil list, detail view, follow-up Q&A
│ ├── settings/ # Expert CRUD, engine status, model download, log console
│ └── theme/ # Material 3 color, typography, theme
├── util/
│ ├── DinoLog.kt # In-app log sink
│ └── ImageActions.kt # Save to gallery, share intent helpers
└── DinoApplication.kt # App singleton: database, NanoEngineImpl, InferenceRunner
Single-turn API, multi-turn UX. ML Kit's Gemini Nano API is single-turn (one request, one response). Multi-turn conversation is emulated by folding the full history into a single TextPart as a User: … / Assistant: … transcript prepended to each new request.
WorkManager for inference. Initial analysis runs in a CoroutineWorker so it survives process death and app backgrounding. The worker writes streaming tokens directly to the Room database; the UI observes via Flow.
InferenceRunner as the single inference entry point. InferenceRunner centralizes bitmap decoding, history assembly, NanoEngineImpl.analyze() invocation, and database write-back for all three inference modes (initial, continuation, follow-up). ViewModels delegate to it rather than duplicating logic.
Room @Relation for joined queries. The history list fetches FossilWithTask (fossil + its associated task) in a single @Transaction query using @Relation, avoiding in-memory joins.
| Table | Purpose |
|---|---|
experts |
Named personas with system prompts and memory settings |
tasks |
One task per capture; tracks status (PENDING → PROCESSING → COMPLETED / FAILED) |
fossils |
Stores the LLM response for a task; truncated flag signals MAX_TOKENS hit |
follow_ups |
Per-fossil Q&A pairs, each with its own truncated flag |
MIT License
Copyright (c) 2025 dev-ansung
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.