Modernizing an Android application is more than increasing its Gradle version. A genuine modernization replaces obsolete architecture, removes deprecated dependencies, improves performance, strengthens security, and creates a maintainable foundation for future features.
This implementation plan shows how to transform a legacy Malaysia Holiday app—originally built for the Eclipse/ADT era—into a high-performance native application using Kotlin 2.x, Jetpack Compose, Material 3, Coroutines, StateFlow, and clean MVVM architecture.
Modernization Goal
The original app targets the Android 4.0 era and uses Java 6/7, Gradle 1.2.3, and a WebView rendering jQuery Mobile 1.2.1 pages. Holiday information is embedded in static HTML. The new app will use Kotlin, native Compose UI, modern Android APIs, structured data, and testable business logic.
Legacy vs. Modern Android
| Aspect | Legacy App | Modern App |
|---|---|---|
| Language | Java 1.6/1.7 | Kotlin 2.1.0, Coroutines, and StateFlow |
| UI | WebView and jQuery Mobile | Jetpack Compose and Material 3 |
| Android SDK | Min SDK 9, target SDK 15 | Min SDK 26, target/compile SDK 35, with an API 36 migration path |
| Build | Gradle 1.2.3 and retired jcenter() | Gradle 8.11.1, AGP 8.7.3, Google, and Maven Central |
| Architecture | Monolithic Activity | Clean MVVM, ViewModels, and repositories |
| Content | Static 2016 HTML table | Structured 2025–2026 holidays, school terms, salary dates, and long weekends |
1. Audit Before Rebuilding
Document the existing screens, assets, permissions, preferences, analytics, advertisements, deep links, and data sources. Preserve the production application ID and signing key if the new version will update the existing Play Store listing.
2. Start with a Clean Kotlin Project
For an application this old, creating a new Compose project and migrating the useful behavior is usually clearer than stepping through every historical Gradle upgrade.
android {
namespace = "com.example.malaysiaholiday"
compileSdk = 35
defaultConfig {
applicationId = "com.example.malaysiaholiday"
minSdk = 26
targetSdk = 35
versionCode = 200
versionName = "2.0.0"
}
buildFeatures {
compose = true
buildConfig = true
}
}
Remove jcenter() and use supported repositories:
repositories {
google()
mavenCentral()
}
3. Replace the WebView with Compose
A holiday planner does not need a webpage wrapped inside an Activity. Native Compose screens improve accessibility, dark mode, responsive layouts, navigation, and rendering performance.
- Home dashboard and next-holiday countdown
- Public holiday calendar
- State and federal territory filters
- KPM school holidays for Kumpulan A and B
- Civil servant salary dates
- Long-weekend vacation planner
- Search, sharing, and settings
@Composable
fun HolidayCard(
holiday: Holiday,
onAddToCalendar: (Holiday) -> Unit
) {
ElevatedCard(modifier = Modifier.fillMaxWidth()) {
Column(
modifier = Modifier.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
Text(holiday.name, style = MaterialTheme.typography.titleMedium)
Text(holiday.date.toString())
TextButton(onClick = { onAddToCalendar(holiday) }) {
Text("Add to calendar")
}
}
}
}
4. Introduce Clean MVVM Architecture
The repository owns access to holiday information. The ViewModel turns that information into immutable UI state, while Compose renders the state and sends user actions back to the ViewModel.
data class HolidayUiState(
val isLoading: Boolean = true,
val selectedState: MalaysiaState? = null,
val query: String = "",
val holidays: List<Holiday> = emptyList(),
val errorMessage: String? = null
)
Reviewed by Admin
on
9:58 AM
Rating:

No comments: