KBBI is an unofficial Android dictionary app for Kamus Besar Bahasa Indonesia. The app combines a remote dictionary API with a bundled local word index so users can search words quickly, inspect meanings in detail, and keep a personal bookmark/history collection on-device.
This repository contains the Android client for KBBI. The current project setup is:
- Single Android application module:
:app - Kotlin + XML/View system UI
- MVVM + repository pattern
- Koin for dependency injection
- Room for local persistence
- Retrofit + OkHttp for API access
- Navigation Component with a bottom-navigation based main flow
- Product flavors for
developmentandproduction - Static analysis with Detekt and Ktlint
- GitHub Actions CI and Fastlane automation
- Search Indonesian words from the home screen
- Browse a bundled word list from
app/src/main/assets/entries.json - View detailed word entries and meanings
- Save bookmarked words locally
- Keep recent search history locally
- Animated splash screen and motion-based UI touches
- Edge-to-edge system bar support
- Language: Kotlin
- Build tooling: Gradle, Android Gradle Plugin
9.2.1, Kotlin2.3.21 - Java target: Java 17
- Minimum SDK: 23
- Target/Compile SDK: 37
- UI: Android Views, ViewBinding, Material Components, MotionLayout, Lottie
- Architecture: MVVM, Repository pattern, UseCase layer
- Async/data: Coroutines, LiveData, RxBinding
- Local storage: Room
- Networking: Retrofit, Gson, OkHttp logging interceptor
- Dependency injection: Koin
4.2.1 - Code quality: Detekt, Ktlint
- Distribution/automation: Fastlane, GitHub Actions
.
├── app/
│ ├── src/main/java/com/arrazyfathan/kbbi/
│ │ ├── core/ # Data, domain, repository, Room, Retrofit
│ │ ├── di/ # App-level Koin modules
│ │ ├── presentation/ # Activities, fragments, adapters, custom views
│ │ └── utils/ # Extensions and window/system-bar helpers
│ ├── src/main/assets/
│ │ └── entries.json # Bundled word list used by Word List screen
│ ├── src/main/res/ # XML layouts, drawables, animations, navigation
│ ├── build.gradle.kts
│ └── version.properties # Version naming and versionCode inputs
├── fastlane/ # Release/distribution automation
├── gradle/libs.versions.toml # Centralized dependency and plugin versions
└── .github/workflows/ # CI and tagged release pipeline
The app currently has three main destinations inside the bottom navigation:
- Home
Search for a word, see loading/error states, and store recent searches. - Word List
Filter the bundled local word index fromentries.json, then fetch details from the API. - Bookmarks
View and remove locally saved entries.
Detailed meaning results open in DetailActivity, where users can bookmark or remove saved words.
- Base URL:
https://kbbi-api-green.vercel.app - API repository: https://github.com/arrazyfathan/kbbi-api
- Room database: stores history and bookmark data in
kbbi_db - Asset file:
app/src/main/assets/entries.jsonprovides the local searchable word list
To build the project locally, use:
- Android Studio with current Android SDK tooling
- JDK 17
- Android SDK Platform 37
- An Android device or emulator for runtime testing
git clone https://github.com/arrazyfathan/kbbi.git
cd kbbiYour local.properties should point to a valid Android SDK installation, for example:
sdk.dir=/path/to/Android/sdk./gradlew helpIf Gradle sync succeeds, the project is ready to open in Android Studio.
The app defines one flavor dimension, stage, with two product flavors:
developmentUses application IDcom.arrazyfathan.kbbi.devproductionUses application IDcom.arrazyfathan.kbbi
Examples:
./gradlew assembleDevelopmentDebug
./gradlew assembleProductionDebugRelease APK names are customized automatically:
- Production:
kbbi-v<version>-release.apk - Non-production:
kbbi-<flavor>-v<version>-release.apk
Version values are driven by app/version.properties.
For local development, the normal entry point is the development debug build:
./gradlew installDevelopmentDebugOr from Android Studio, choose the developmentDebug variant and run the app configuration.
The project contains two suites of tests:
- Local Unit Tests (located in
app/src/test): Test pure logic and business interactors using mock/fake repositories directly on the host JVM. - Instrumented Integration Tests (located in
app/src/androidTest): Test database operations and Android-dependent integrations on a physical device or emulator.
To run JVM unit tests:
./gradlew testDevelopmentDebugUnitTestTo compile instrumented tests without running them:
./gradlew compileDevelopmentDebugAndroidTestKotlinTo run instrumented tests (requires a running emulator or connected device):
./gradlew connectedDevelopmentDebugAndroidTestWe use the JetBrains Kover plugin to measure unit test coverage. Since the project includes product flavors and signing rules, run the coverage tasks specifically for the development debug variant:
- Console Summary: Print coverage statistics directly to the terminal:
./gradlew app:koverLogDevelopmentDebug
- HTML Report: Generate a detailed HTML report:
The report is saved at
./gradlew app:koverHtmlReportDevelopmentDebug
app/build/reports/kover/htmlDevelopmentDebug/index.html.
Other useful check tasks:
./gradlew lintDevelopmentDebug
./gradlew detekt
./gradlew ktlintCheckYou can run a broader validation pass including unit tests and build tasks:
./gradlew testDevelopmentDebugUnitTest lintDevelopmentDebug assembleDevelopmentDebugRelease builds are intentionally blocked unless signing is configured. The Gradle build expects these values through either Gradle properties or environment variables:
ANDROID_KEYSTORE_PATH
ANDROID_KEYSTORE_PASSWORD
ANDROID_KEY_ALIAS
ANDROID_KEY_PASSWORD
Example:
export ANDROID_KEYSTORE_PATH=/absolute/path/to/release.keystore
export ANDROID_KEYSTORE_PASSWORD=your-store-password
export ANDROID_KEY_ALIAS=your-key-alias
export ANDROID_KEY_PASSWORD=your-key-password
./gradlew assembleProductionReleaseWithout those values, any signed release packaging task will fail by design.
The repository already includes Fastlane setup.
Install Ruby dependencies:
bundle installAvailable lanes:
bundle exec fastlane android testCurrent behavior:
android testruns Gradle tests
GitHub Actions workflow: .github/workflows/android.yml
The validate job runs:
./gradlew testDevelopmentDebugUnitTest lintDevelopmentDebug assembleDevelopmentDebug --stacktraceIf successful, it uploads the development debug APK as a workflow artifact.
When a git tag is pushed, the release job:
- Validates signing secrets
- Builds
assembleProductionRelease - Uploads the signed production APK as an artifact
- Publishes a GitHub release with generated release notes
Required GitHub secrets:
ANDROID_KEYSTORE_BASE64ANDROID_KEYSTORE_PASSWORDANDROID_KEY_ALIASANDROID_KEY_PASSWORD
The current app includes:
- Custom splash screen animation
- Motion/transition-driven interactions on the home screen
- Lottie-based loading and empty states
- Custom system bar and inset handling helpers
Latest published APK:
Designed and developed by 2022 arrazyfathan (Ar Razy Fathan Rabbani)
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.




