This is a submission for the Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass.
Nature Quest (pocket edition) is taking Gemma 4 E2B outside into the outdoor environment with no internet connection, fully Offline.
What I Built
Pocket Nature Quest is a fully offline Android field companion that turns one outdoor photo into a short Look · Listen · Move quest.
The idea is deliberately a little paradoxical: use AI on a phone to encourage someone to stop looking at their phone. Help user achieve wellness by observing their natural environment. The screen is only the starting point. A user takes a photo, optionally adds GPS context, chooses a time and energy level, and receives three simple actions to complete outside.
The app is designed for walkers, families, travelers, nature beginners, or anyone who wants a small push to notice their surroundings more carefully. It does not need Wi-Fi, an API key, web search, or online geocoding. The photo, coordinates, prompt, and generated quest stay on the device.
An accidental by design
This project began with a misunderstanding. My first prompt did not clearly explain the mobile, fully local application I had in mind, and my AI coding assistant moved too quickly into implementing a polished web prototype without first discussing the architecture with me.
I share responsibility for that. I had a design in mind, but I had not communicated it clearly. The assistant also should have paused for requirements plan and involved me before implementation. We effectively built the project twice.
That mistake became useful. It gave me two versions of the same product idea:
- a fast web prototype using Gemini 3.6 Flash through an API; and
- the actual challenge entry: a Flutter Android application running the open-weight Gemma 4 E2B model locally through LiteRT-LM.
The web version is not my challenge submission. I used it only as a comparison point while evaluating the local Android experience.
More importantly, the reset changed how I worked. I defined the requirements, selected the target device and local model, rejected web search and reverse geocoding, tested the application outdoors, evaluated its output, and reported the failures. The coding assistant acted as an implementation partner and mentor under those decisions. That process taught me as much as the final code.
Demo
- Source code: github.com/beoncloud8/week-1-touch-grass-android
- Reference device: Samsung Galaxy A25 5G, 8 GB RAM, Android 16
-
Model: Gemma 4 E2B in
.litertlmformat, running entirely on-device
Short Android demo
Pocket Nature Quest running on the Samsung Galaxy A25 with local, on-device Gemma inference.
Sunset Pier test scene 1: calm waterfront, shoreline plants, skyline, terraces, and white paper-boat sculptures.
Sunset Pier test scene 2: large floral cone sculptures on a wooden deck beside the water.
I took the app to Sunset Pier, a waterfront area beside a mangrove forest with space to walk, take photos, sit, dine, and drink coffee. This was the right kind of test: not a desk demo, but an actual walk where the generated quest had to match a real place.
Field results
I tested two photos with both versions. These are informal observations from one phone and two scenes, not a scientific benchmark.
| Scene | Settings | Local Gemma 4 E2B | Gemini 3.6 Flash web prototype |
|---|---|---|---|
| Waterfront and paper boats | 15 minutes · Curious | 1.5–2 minutes | 2–3 seconds |
| Floral sculptures and deck | 10 minutes · Gentle | 1–1.5 minutes | 2–3 seconds |
For the first photo, local Gemma produced:
- Look — Observe the surface of the water. Notice that the water appears relatively calm with some ripples.
- Listen — Ambient sounds. Listen for sounds from the water or the surroundings.
- Move — Walk along the edge. Walk beside the landscaped foreground area.
For the second photo, local Gemma asked me to examine the colors and shapes of the floral arrangements, listen for water sounds, and walk slowly along the wooden deck.
The cloud model was much faster and its language was more specific. It noticed the paper-boat sculptures, shoreline plants, terraced sections, floral textures, railing, skyline, and changing perspective. Gemma's wording was stiffer and more general.
From the first photo, the cloud model produced
- Look - Compare Boat Sculptures and Shoreline Plants. Scan the calm water to locate the white paper-boat sculptures floating offshore. Then observe the green groundcover spreading across the shoreline rocks below the walkway wall.
- Listen - Tune In to Waterfront Sounds. Pause near the edge of the promenade and close your eyes for 30 seconds. Listen for the gentle lap of water against the embankment or birds along the shoreline foliage.
- Move - Trace the Terraced Pathway. Walk slowly along the upper paved deck toward the viewing area overlooking the floating boats, staying safely behind all railings and walls.
We can see that the cloud model produce more articulate output, but the local model succeeded at the part that mattered most to this experiment: it looked at a real photo, created a safe three-part activity, and did so without sending my photo or precise location anywhere.
That trade-off became my main lesson. “Better” does not mean only richer prose or lower latency. For a tool intended for trails, waterfronts, rural areas, or private family outings, offline availability and data ownership are also product features.
Code
beoncloud8
/
week-1-touch-grass-android
Fully offline Flutter field companion powered by on-device Gemma 4 E2B
Pocket Nature Quest — Android
Pocket Nature Quest is a fully offline Flutter field companion for the Hacktoberfest 2026 Week 1 Touch Grass challenge. Take one outdoor photo and Gemma 4 E2B creates a short mission for your eyes, ears, and feet—without sending the photo or location to a server.
This repository is the Android application. The earlier web prototype remains a separate project and is not a runtime dependency.
Product flow
- Import a local
gemma-4-E2B-it.litertlmmodel once. - Take or choose an outdoor photo.
- Optionally add a place description and device GPS coordinates.
- Choose the available time and energy level.
- Generate a validated Look · Listen · Move field card locally.
- Start low-distraction field mode and put the phone down.
Why the model is not in Git or the APK
The E2B model is several gigabytes. Committing it would make the repository and APK impractical and would blur the model's…
The application source is MIT licensed. The Gemma model weights are not committed to Git or bundled in the APK; users select their separately downloaded .litertlm model on the phone.
The central inference flow lives behind LocalGemmaService, keeping model management out of the UI. The response must parse into exactly three distinct steps—Look, Listen, and Move—before the application displays it.
final model = await FlutterEdgeAi.getActiveModel(
maxTokens: 2048,
preferredBackend: PreferredBackend.gpu,
preferredVisionBackend: PreferredBackend.gpu,
supportImage: true,
maxNumImages: 1,
);
final chat = await model.createChat(
supportImage: true,
systemInstruction: _systemInstruction,
temperature: .35,
topK: 32,
maxOutputTokens: 700,
);
How I Built It
The stack is intentionally small:
- Flutter and Dart for the Android interface
- Gemma 4 E2B, an open-weight multimodal model
-
LiteRT-LM through
flutter_edge_aiandflutter_edge_ai_litertlm -
image_pickerfor the camera and gallery -
imagefor orientation correction and memory-conscious resizing -
geolocatorfor optional raw coordinates -
file_pickerandpath_providerfor importing and preserving the local model
The flow is:
camera or gallery
↓
resize image to 768 px
↓
optional GPS coordinates + time + energy
↓
safety-first structured prompt
↓
Gemma 4 E2B via LiteRT-LM
↓
validate JSON as Look · Listen · Move
↓
low-distraction field card and timer
The model prompt prohibits claims about uncertain species, edibility or medical advice, touching wildlife, trespassing, climbing, entering water, and leaving a safe path. Coordinates are treated only as context; the app performs no reverse geocoding.
A bug that only appeared on the second run
The first outdoor test worked, but reopening the application later produced:
Bad state: No active inference model set.
Use FlutterEdgeAi.installModel() first.
The model file still existed. The problem was lifecycle and storage: the UI treated “a model file is listed” as equivalent to “the model is active,” and the imported 2.4 GB model was referenced through a temporary file-picker cache path.
I changed the app to copy the selected model into durable application storage, verify actual activation on startup, restore it when necessary, and block generation while preparation is still running. Then I installed the new APK over the old one, migrated the model, force-closed the app, reopened it, and verified that the active model pointed to the permanent path.
That failure was a useful reminder: a successful first inference is not the same as a reliable mobile application. Restart testing matters.
Why Does Open Innovation Matter?
The open model is not decoration in this project. It is the reason the Android version can exist as designed.
With Gemma 4 E2B running locally:
- a walk can start somewhere with no mobile signal;
- private photos never need to leave the phone;
- raw GPS coordinates stay under the user's control;
- there is no API key to expose and no per-request inference bill;
- the inference layer and prompt can be inspected, changed, or replaced; and
- the experience remains available even if a hosted service is unreachable.
The comparison also kept me honest about the costs. On my mid-range Galaxy A25, local inference took roughly one to two minutes, while Gemini returned more detailed writing in seconds. A compact edge model requires tighter prompts, patient UX, and realistic expectations.
For Pocket Nature Quest, I accept that cost because the application is meant to work outside—and because a photo of where someone is standing, combined with GPS coordinates, is exactly the kind of data that deserves a local-first option.
My Agent Session
I used Codex as a coding assistant and mentor during planning, implementation, debugging, and testing. I made the product decisions and evaluated the app on a physical phone outdoors; the assistant generated and revised significant parts of the code and helped diagnose the model lifecycle bug.
Open the curated Agent Session on DEV
This article was drafted with meaningful AI assistance and reviewed against my own test notes and observations.
What I Learned
My biggest lesson was not a Flutter API. It was that requirements are part of programming.
When I did not explain the intended platform, constraints, and role of the local model, we produced the wrong thing—even though it was beautiful and functional. Once I wrote down those decisions and asked for a plan before implementation, I became more involved and learned more from the work.
I also learned that evaluating software in its real setting changes the conversation. At Sunset Pier I could see both the limitations of a small local model and the value of an application that continued to work privately, with no network dependency.
Next I would improve the prompt with a few examples to make Gemma's language warmer and less repetitive, add structured latency measurements over more scenes, and continue testing memory use on mid-range Android hardware.
Prize Categories
- Best Use of Gemma


Top comments (1)
tr.ee/dev-to
Some comments have been hidden by the post's author - find out more