🔢 MathLab — Android Learning Project
A showcase Android app that uses Kotlin + Compose , Java , and C++ (NDK/JNI)
together in one real project. Each language plays to its strengths.
┌─────────────────────────────────────────────────────────────┐
│ UI LAYER (Kotlin) │
│ Jetpack Compose screens • StateFlow • Navigation │
│ HomeScreen MathScreen StringScreen SortScreen History │
└──────────────────────┬───────────────┬──────────────────────┘
│ │
┌────────────▼───┐ ┌──────▼──────────┐
│ MainViewModel │ │ Room Database │
│ (Kotlin/MVVM) │ │ CalculationDao │
└───┬─────────┬──┘ └──────────────────┘
│ │
┌─────────▼──┐ ┌───▼──────────────────────┐
│ NativeBridge│ │ Java Data Structures │
│ (JNI/Kotlin)│ │ SortingAlgorithms.java │
└─────────┬──┘ │ MathStack.java │
│ │ MathLinkedList.java │
┌─────────▼──┐ │ CalculationHistory.java │
│ C++ Engine │ └──────────────────────────┘
│ MathEngine │
│ StringProc │
└─────────────┘
MathLab/
├── app/src/main/
│ ├── cpp/ ← C++ (NDK)
│ │ ├── CMakeLists.txt # Build config for C++ files
│ │ ├── MathEngine.h/.cpp # Prime, GCD, Fibonacci, etc.
│ │ ├── StringProcessor.h/.cpp # Reverse, palindrome, cipher
│ │ └── mathlab-jni.cpp # JNI bridge (C++ ↔ Kotlin)
│ │
│ └── java/com/mathlab/
│ ├── jni/
│ │ └── NativeBridge.kt # Kotlin declarations of C++ functions
│ │
│ ├── java/ ← Java code
│ │ ├── ds/
│ │ │ ├── MathStack.java # Generic Stack + postfix evaluator
│ │ │ ├── MathLinkedList.java
│ │ │ └── SortingAlgorithms.java # 5 algorithms + step tracking
│ │ └── patterns/
│ │ ├── CalculationObserver.java # Observer pattern interface
│ │ └── CalculationHistory.java # Singleton + Observer subject
│ │
│ ├── data/ ← Kotlin/Room
│ │ ├── model/CalculationRecord.kt # Room @Entity
│ │ └── db/
│ │ ├── CalculationDao.kt # Room @Dao
│ │ └── AppDatabase.kt # Room @Database (Singleton)
│ │
│ └── ui/ ← Compose UI
│ ├── MainViewModel.kt # Bridges all three language layers
│ ├── Navigation.kt # Bottom nav + NavHost
│ ├── theme/Theme.kt # Material3 colors
│ └── screens/
│ ├── HomeScreen.kt # Landing + animated language cards
│ ├── MathScreen.kt # C++ math operations
│ ├── StringScreen.kt # C++ string processing
│ ├── SortScreen.kt # Java sort visualizer
│ └── HistoryScreen.kt # Room DB history
Android Studio Ladybug (2024.2.1) or newer
NDK installed: Android Studio → SDK Manager → SDK Tools → NDK (Side by side)
CMake installed: same location as NDK above
Clone / copy this project folder
Open Android Studio → Open → select the MathLab folder
Let Gradle sync complete
Connect a device or start an emulator (API 26+)
Click ▶ Run
File → Project Structure → SDK Location → verify NDK path
Or add to local.properties:
ndk.dir=/path/to/your/Android/sdk/ndk/26.x.x
Concept
Where
JNI naming convention
mathlab-jni.cpp
jstring ↔ std::string conversion
jstringToStdString() helper
Returning arrays across JNI boundary
sieve() function
Sieve of Eratosthenes
MathEngine::sieveOfEratosthenes()
Caesar cipher
StringProcessor::caesarCipher()
Concept
Where
Generics <T>
MathStack<T>, MathLinkedList<T>
Singleton pattern
CalculationHistory.getInstance()
Observer pattern
CalculationObserver interface + CalculationHistory
Sorting with step tracking
SortingAlgorithms.java
Floyd's cycle detection
MathLinkedList.hasCycle()
Concept
Where
StateFlow + collectAsState()
MainViewModel → all screens
viewModelScope.launch coroutines
Every async operation
animateFloatAsState
Sort bar chart animation
AnimatedVisibility
Result card show/hide
Room DB with Flow
CalculationDao → allRecords
Bottom navigation
Navigation.kt
Some ideas to practice with:
C++ : Add a matrix multiplication engine
Java : Implement a Binary Search Tree or Graph
Kotlin : Add a Compose Canvas drawing screen
Room : Add categories/tags to filter history
Coroutines : Add a benchmark screen comparing algorithm speeds
Compose Animation : Animate the linked list nodes visually
Kotlin: val result = NativeBridge.isPrime(97L)
↓ (calls external fun)
JNI: Java_com_mathlab_jni_NativeBridge_isPrime(env, obj, 97)
↓ (delegates to C++ class)
C++: MathEngine::isPrime(97) → returns true
↓ (JNI returns jboolean)
Kotlin: result == true ✓