An Android app that identifies cars from photos using AI, rates how rare they are, and turns car spotting into a collection game.
Kotlin
4
4 commits
updated Oct 13, 2026
An Android app that identifies cars from photos using AI, rates how rare they are,
and turns car spotting into a collection game.
Features · Rarity Tiers · Build It · Scoring · Troubleshooting · Contributing
Take a photo of a car (or pick one from your gallery) and CarScanner tells you what it is, how rare it is, and how much it's worth. Every scan earns points based on rarity and value, so you level up and fill your garage with a collection of cards.
[!TIP] Designed to be forked. Anyone can run their own copy on their own phone for free, using their own Firebase project and their own Gemini API key. No server required.
| Feature | Details | |
|---|---|---|
| 📸 | Two ways to scan | Live camera with a viewfinder, or pick an image from your gallery |
| 🧠 | AI identification | Make, model, year, body style, estimated value, production numbers and a fun fact |
| 💎 | 7 rarity tiers | From Common all the way to Divine, which has an animated rainbow |
| 🏆 | Points and levels | Score depends on rarity, value, how few were built, age and AI certainty |
| 🏠 | Garage | Your collection as rarity-colored cards, paged for speed, with search, filters and sorting |
| 📊 | Profile page | Level, total garage value, unique models, scans this week, favorite brand, per-rarity breakdown, best scoring and most valuable cars |
| 🛠️ | Fix wrong scans | Tap "Not the right car?", type the real car and the AI fills in the details |
| 🔐 | Google sign-in | With delete and sign-out confirmations |
| 🌐 | Web-search grounding | Optional, lets the AI look up very new cars |
| 🔒 | Local data | Everything stays on your phone, separate per Google account |
[!NOTE] Re-scanning a model you already own only earns 10% of the normal points, so no farming the same parked Civic.
| Tier | Badge | Base points |
|---|---|---|
| Common | 10 | |
| Uncommon | 20 | |
| Rare | 40 | |
| Epic | 70 | |
| Legendary | 120 | |
| Mythical | 200 | |
| Divine | 350 |
[!NOTE] The badge colors above are approximations for this README. The exact in-app colors live in the theme code.
| Area | Library |
|---|---|
| UI | Jetpack Compose (Material 3) |
| Camera | CameraX |
| Storage | Room + Paging 3 |
| Auth | Firebase Auth + Credential Manager (Google sign-in) |
| Images | Coil |
| Networking | OkHttp |
| AI | Gemini API |
About 15 minutes. You need:
flowchart LR
A[1. Clone] --> B[2. Firebase]
B --> C[3. Gemini key]
C --> D[4. Run]
style A fill:#7F52FF,color:#fff,stroke:none
style B fill:#DD2C00,color:#fff,stroke:none
style C fill:#8E75B2,color:#fff,stroke:none
style D fill:#3DDC84,color:#000,stroke:none
git clone https://github.com/ItzjustElias/CarScanner.git
Open the folder in Android Studio and let Gradle sync. It will fail until step 2 is done, that's expected.
com.example.carscanner
(if you change the package name in app/build.gradle.kts, use that one instead).app > Tasks > android > signingReport, and copy the SHA1 of the debug variant.
Or run ./gradlew signingReport in a terminal.google-services.json (Project settings > Your apps) and put it in the app/ folder.[!WARNING] Do not commit
google-services.json. It's already in.gitignore.
[!IMPORTANT] Download
google-services.jsonafter enabling Google sign-in and adding the SHA-1, otherwise it won't contain the web client ID the app needs.
local.properties (Android Studio creates it) and add:GEMINI_API_KEY=your_key_here
# Optional:
GEMINI_MODEL=gemini-2.5-flash
GEMINI_SEARCH=true
See local.properties.example. This file is git-ignored.
Connect your phone with USB debugging on (or start an emulator) and press Run ▶️.
To keep the app installed, use Build > Build APK(s) and install the APK on your phone.
Setting (local.properties) | Default | What it does |
|---|---|---|
GEMINI_API_KEY | none | Your Gemini API key (required) |
GEMINI_MODEL | gemini-2.5-flash | Model used for scans. Change it if Google renames or retires it |
GEMINI_SEARCH | true | Lets the AI search the web for very new cars. Set to false if you hit quota errors. The app also falls back automatically |
flowchart TD
A[📸 Photo] --> B[🧠 AI picks a rarity tier]
B --> C{Very valuable or<br>very limited?}
C -- yes --> D[Floor enforced:<br>a $5M car can't be Common]
C -- no --> E[Base points for tier]
D --> E
E --> F[+ value bonus<br><i>logarithmic</i>]
F --> G[+ low production bonus]
G --> H[+ classic bonus<br><i>30+ and 50+ years</i>]
H --> I[× AI certainty]
I --> J{Already scanned<br>this model?}
J -- yes --> K[10% of points]
J -- no --> L[🏆 Full points]
style A fill:#4285F4,color:#fff,stroke:none
style L fill:#3DDC84,color:#000,stroke:none
style K fill:#9E9E9E,color:#fff,stroke:none
On top of the base points per tier:
The AI picks the tier, then the app enforces a floor for very valuable or very limited cars so a $5M car can't be rated Common.
[!TIP] Want to tweak the balance? All the numbers are in
domain/PointsCalculator.ktanddomain/Models.kt.
app/src/main/java/com/example/carscanner/
├── auth/ Google sign-in (Credential Manager + Firebase)
├── data/ Room database, Gemini API client, repository
├── domain/ rarity tiers, points and level rules
└── ui/
├── login/ sign-in screen
├── garage/ collection, search/filter, detail sheet, "fix this car"
├── scan/ camera, gallery picker, result screen
├── profile/ stats page
├── theme/ colors, typography, animated rarity styling
└── components/ shared widgets
[!CAUTION] Your API key is compiled into the app. That's fine for your own phone. Never publish an APK you built with your key, and never commit
local.properties. For a public app you would need a backend that holds the key.
[!WARNING] Photos are sent to Google's Gemini API for identification. Free-tier requests may be used by Google to improve its products, so avoid photographing license plates or people.
[!NOTE] The AI can be wrong, especially for rare, modified or very new cars. Values and production numbers are estimates, not market data. Use "Not the right car?" to fix a scan.
[!NOTE] Free-tier API limits apply and change over time. Check Google's rate limit docs and your usage in AI Studio.
default_web_client_id not foundgoogle-services.json has no web client ID. Enable Google sign-in in Firebase, add your SHA-1, re-download
the file, then clean and rebuild.
Fallback: copy the Web client ID from Firebase into a string resource and reference it in auth/AuthManager.kt.
The SHA-1 in Firebase doesn't match your build. Re-add it and re-download google-services.json.
Add GEMINI_API_KEY to local.properties and rebuild.
You hit the free quota. Wait for it to reset, or set GEMINI_SEARCH=false.
See the open issues for proposed features and known problems.
Contributions make open source great, and they are greatly appreciated. Issues and pull requests are welcome.
git checkout -b feature/amazing-feature)git commit -m 'Add amazing feature')git push origin feature/amazing-feature)[!WARNING] Please don't commit secrets or
google-services.json.
Distributed under the MIT License. See LICENSE for more information.
This project is not affiliated with Google, Firebase or any car manufacturer. Brand names belong to their respective owners.
An Android app that identifies cars from photos using AI, rates how rare they are, and turns car spotting into a collection game.
Kotlin
4
4 commits
updated Oct 13, 2026
An Android app that identifies cars from photos using AI, rates how rare they are,
and turns car spotting into a collection game.
Features · Rarity Tiers · Build It · Scoring · Troubleshooting · Contributing
Take a photo of a car (or pick one from your gallery) and CarScanner tells you what it is, how rare it is, and how much it's worth. Every scan earns points based on rarity and value, so you level up and fill your garage with a collection of cards.
[!TIP] Designed to be forked. Anyone can run their own copy on their own phone for free, using their own Firebase project and their own Gemini API key. No server required.
| Feature | Details | |
|---|---|---|
| 📸 | Two ways to scan | Live camera with a viewfinder, or pick an image from your gallery |
| 🧠 | AI identification | Make, model, year, body style, estimated value, production numbers and a fun fact |
| 💎 | 7 rarity tiers | From Common all the way to Divine, which has an animated rainbow |
| 🏆 | Points and levels | Score depends on rarity, value, how few were built, age and AI certainty |
| 🏠 | Garage | Your collection as rarity-colored cards, paged for speed, with search, filters and sorting |
| 📊 | Profile page | Level, total garage value, unique models, scans this week, favorite brand, per-rarity breakdown, best scoring and most valuable cars |
| 🛠️ | Fix wrong scans | Tap "Not the right car?", type the real car and the AI fills in the details |
| 🔐 | Google sign-in | With delete and sign-out confirmations |
| 🌐 | Web-search grounding | Optional, lets the AI look up very new cars |
| 🔒 | Local data | Everything stays on your phone, separate per Google account |
[!NOTE] Re-scanning a model you already own only earns 10% of the normal points, so no farming the same parked Civic.
| Tier | Badge | Base points |
|---|---|---|
| Common | 10 | |
| Uncommon | 20 | |
| Rare | 40 | |
| Epic | 70 | |
| Legendary | 120 | |
| Mythical | 200 | |
| Divine | 350 |
[!NOTE] The badge colors above are approximations for this README. The exact in-app colors live in the theme code.
| Area | Library |
|---|---|
| UI | Jetpack Compose (Material 3) |
| Camera | CameraX |
| Storage | Room + Paging 3 |
| Auth | Firebase Auth + Credential Manager (Google sign-in) |
| Images | Coil |
| Networking | OkHttp |
| AI | Gemini API |
About 15 minutes. You need:
flowchart LR
A[1. Clone] --> B[2. Firebase]
B --> C[3. Gemini key]
C --> D[4. Run]
style A fill:#7F52FF,color:#fff,stroke:none
style B fill:#DD2C00,color:#fff,stroke:none
style C fill:#8E75B2,color:#fff,stroke:none
style D fill:#3DDC84,color:#000,stroke:none
git clone https://github.com/ItzjustElias/CarScanner.git
Open the folder in Android Studio and let Gradle sync. It will fail until step 2 is done, that's expected.
com.example.carscanner
(if you change the package name in app/build.gradle.kts, use that one instead).app > Tasks > android > signingReport, and copy the SHA1 of the debug variant.
Or run ./gradlew signingReport in a terminal.google-services.json (Project settings > Your apps) and put it in the app/ folder.[!WARNING] Do not commit
google-services.json. It's already in.gitignore.
[!IMPORTANT] Download
google-services.jsonafter enabling Google sign-in and adding the SHA-1, otherwise it won't contain the web client ID the app needs.
local.properties (Android Studio creates it) and add:GEMINI_API_KEY=your_key_here
# Optional:
GEMINI_MODEL=gemini-2.5-flash
GEMINI_SEARCH=true
See local.properties.example. This file is git-ignored.
Connect your phone with USB debugging on (or start an emulator) and press Run ▶️.
To keep the app installed, use Build > Build APK(s) and install the APK on your phone.
Setting (local.properties) | Default | What it does |
|---|---|---|
GEMINI_API_KEY | none | Your Gemini API key (required) |
GEMINI_MODEL | gemini-2.5-flash | Model used for scans. Change it if Google renames or retires it |
GEMINI_SEARCH | true | Lets the AI search the web for very new cars. Set to false if you hit quota errors. The app also falls back automatically |
flowchart TD
A[📸 Photo] --> B[🧠 AI picks a rarity tier]
B --> C{Very valuable or<br>very limited?}
C -- yes --> D[Floor enforced:<br>a $5M car can't be Common]
C -- no --> E[Base points for tier]
D --> E
E --> F[+ value bonus<br><i>logarithmic</i>]
F --> G[+ low production bonus]
G --> H[+ classic bonus<br><i>30+ and 50+ years</i>]
H --> I[× AI certainty]
I --> J{Already scanned<br>this model?}
J -- yes --> K[10% of points]
J -- no --> L[🏆 Full points]
style A fill:#4285F4,color:#fff,stroke:none
style L fill:#3DDC84,color:#000,stroke:none
style K fill:#9E9E9E,color:#fff,stroke:none
On top of the base points per tier:
The AI picks the tier, then the app enforces a floor for very valuable or very limited cars so a $5M car can't be rated Common.
[!TIP] Want to tweak the balance? All the numbers are in
domain/PointsCalculator.ktanddomain/Models.kt.
app/src/main/java/com/example/carscanner/
├── auth/ Google sign-in (Credential Manager + Firebase)
├── data/ Room database, Gemini API client, repository
├── domain/ rarity tiers, points and level rules
└── ui/
├── login/ sign-in screen
├── garage/ collection, search/filter, detail sheet, "fix this car"
├── scan/ camera, gallery picker, result screen
├── profile/ stats page
├── theme/ colors, typography, animated rarity styling
└── components/ shared widgets
[!CAUTION] Your API key is compiled into the app. That's fine for your own phone. Never publish an APK you built with your key, and never commit
local.properties. For a public app you would need a backend that holds the key.
[!WARNING] Photos are sent to Google's Gemini API for identification. Free-tier requests may be used by Google to improve its products, so avoid photographing license plates or people.
[!NOTE] The AI can be wrong, especially for rare, modified or very new cars. Values and production numbers are estimates, not market data. Use "Not the right car?" to fix a scan.
[!NOTE] Free-tier API limits apply and change over time. Check Google's rate limit docs and your usage in AI Studio.
default_web_client_id not foundgoogle-services.json has no web client ID. Enable Google sign-in in Firebase, add your SHA-1, re-download
the file, then clean and rebuild.
Fallback: copy the Web client ID from Firebase into a string resource and reference it in auth/AuthManager.kt.
The SHA-1 in Firebase doesn't match your build. Re-add it and re-download google-services.json.
Add GEMINI_API_KEY to local.properties and rebuild.
You hit the free quota. Wait for it to reset, or set GEMINI_SEARCH=false.
See the open issues for proposed features and known problems.
Contributions make open source great, and they are greatly appreciated. Issues and pull requests are welcome.
git checkout -b feature/amazing-feature)git commit -m 'Add amazing feature')git push origin feature/amazing-feature)[!WARNING] Please don't commit secrets or
google-services.json.
Distributed under the MIT License. See LICENSE for more information.
This project is not affiliated with Google, Firebase or any car manufacturer. Brand names belong to their respective owners.