📱 Overview
VirtualsBlog adalah aplikasi mobile Android untuk platform blogging yang memungkinkan pengguna untuk membuat, membaca, dan berinteraksi dengan postingan blog. Aplikasi ini dibangun menggunakan Jetpack Compose dengan arsitektur MVVM dan Clean Architecture, mengintegrasikan backend API untuk manajemen data.
- ✅ User Registration dengan validasi form
- ✅ User Login dengan session management
- ✅ User Profile management (termasuk upload foto profil)
- ✅ Change Password
- ✅ Forgot Password dengan verifikasi OTP
- ✅ Reset Password setelah verifikasi OTP
- ✅ Secure logout functionality
- ✅ Create new blog posts dengan upload gambar
- ✅ View all blog posts with pagination (implied by GetPostsUseCase)
- ✅ Post detail view dengan konten lengkap dan komentar
- ✅ Category-based post organization
- ✅ Like/Unlike functionality (sistem like permanen)
- ✅ Comment system (create & delete)
- ✅ Search functionality (posts, users, categories)
- ✅ Edit existing blog posts
- ✅ Delete blog posts
- ✅ View posts by author
- ✅ View posts by category
- ✅ Modern Material Design 3 dengan dark/light theme
- ✅ Responsive design untuk berbagai ukuran layar
- ✅ Smooth animations dan transitions (implied by Jetpack Compose usage)
- ✅ Custom UI components (PostCard, UserAvatar, dll.)
- ✅ Loading states dan error handling di berbagai layar
Aplikasi ini menggunakan Clean Architecture dengan MVVM Pattern:
📁 app/src/main/java/com/virtualsblog/project/
├── 📁 data/ # Data Layer
│ ├── 📁 local/ # Local data sources
│ │ ├── 📁 dao/ # Room DAOs (UserDao, etc.)
│ │ ├── 📁 database/ # Room Database (BlogDatabase, BlogDatabaseMigrations)
│ │ └── 📁 entities/ # Room Entities (UserEntity, etc.)
│ ├── 📁 remote/ # Remote data sources
│ │ ├── 📁 api/ # Retrofit APIs (AuthApi, BlogApi)
│ │ └── 📁 dto/ # Data Transfer Objects
│ │ ├── 📁 request/ # (LoginRequest, RegisterRequest, ChangePasswordRequest, CreateCommentRequest, CreatePostRequest, ForgetPasswordRequest, ResetPasswordRequest, UpdateProfileRequest, VerifyOtpRequest)
│ │ └── 📁 response/ # (ApiResponse, AuthResponse, CategoryResponse, CommentResponse, PostResponse, SearchResponseData, UserResponse, VerifyOtpResponse)
│ ├── 📁 mapper/ # Data mappers (UserMapper, PostMapper, CategoryMapper, CommentMapper)
│ └── 📁 repository/ # Repository implementations (AuthRepositoryImpl, BlogRepositoryImpl, UserRepositoryImpl)
├── 📁 domain/ # Domain Layer
│ ├── 📁 model/ # Domain models (User, Post, Category, Comment, AuthState, SearchData)
│ ├── 📁 repository/ # Repository interfaces (AuthRepository, BlogRepository, UserRepository)
│ └── 📁 usecase/ # Use cases
│ ├── 📁 auth/ # (ChangePasswordUseCase, ForgotPasswordUseCase, GetCurrentUserUseCase, LoginUseCase, LogoutUseCase, RegisterUseCase, ResetPasswordUseCase, VerifyOtpUseCase)
│ ├── 📁 blog/ # (CreatePostUseCase, DeletePostUseCase, GetCategoriesUseCase, GetPostByIdUseCase, GetPostsByAuthorIdUseCase, GetPostsByCategoryIdUseCase, GetPostsForHomeUseCase, GetPostsUseCase, GetTotalPostsCountUseCase, SearchUseCase, ToggleLikeUseCase, UpdatePostUseCase)
│ ├── 📁 comment/ # (CreateCommentUseCase, DeleteCommentUseCase, GetCommentsUseCase)
│ └── 📁 user/ # (GetProfileUseCase, UpdateProfileUseCase, UploadProfilePictureUseCase)
├── 📁 presentation/ # Presentation Layer
│ ├── MainActivity.kt # Main Activity
│ ├── MainViewModel.kt # Main ViewModel
│ └── 📁 ui/
│ ├── 📁 component/ # Reusable UI components (PostCard, UserAvatar, CommentInput, CommentItem, etc.)
│ ├── 📁 navigation/ # Navigation setup (AuthNavGraph, BlogDestinations, BlogNavGraph)
│ ├── 📁 screen/ # Screen composables
│ │ ├── 📁 auth/ # (Login, Register, Profile, ChangePassword, ForgotPassword, ResetPassword, Terms, VerifyOtp)
│ │ ├── 📁 authorposts # (AuthorPostsScreen)
│ │ ├── 📁 category/ # (CategoriesScreen, CategoryPostsScreen)
│ │ ├── 📁 home/ # (HomeScreen)
│ │ ├── 📁 post/ # (CreatePostScreen, PostDetailScreen, EditPostScreen, PostListScreen)
│ │ ├── 📁 search/ # (SearchScreen)
│ │ └── 📁 splash/ # (SplashScreen)
│ └── 📁 theme/ # Theme & styling (Color, Shape, Theme, Type)
├── 📁 di/ # Dependency Injection (DatabaseModule, NetworkModule, PreferencesModule, RepositoryModule, UseCaseModule)
├── 📁 util/ # Utilities & extensions (Constants, DateUtil, Extensions, FileUtils, ImageUtil, NavigationEvent, NavigationState, Resource, UiEvent, ValidationUtil)
├── 📁 preferences/ # DataStore preferences (UserPreferences)
└── BlogApplication.kt # Application class
- Kotlin - Primary programming language
- Jetpack Compose - Modern UI toolkit
- Material Design 3 - Design system
- MVVM Pattern - Presentation layer architecture
- Clean Architecture - Overall app architecture
- Repository Pattern - Data access abstraction
androidx.compose.bom- Compose Bill of Materialsandroidx.navigation.compose- Navigation component for Composeandroidx.activity.compose- Activity integration with Composeandroidx.lifecycle.viewmodel.compose- ViewModel integrationandroidx.compose.material:material- For Material components like Pull-to-refresh
dagger.hilt.android- Dependency injection frameworkandroidx.hilt.navigation.compose- Hilt navigation integration
retrofit2- HTTP clientokhttp3- HTTP client implementationgson- JSON serialization/deserialization
androidx.room- Local databaseandroidx.datastore.preferences- Key-value storage
coil-compose- Image loading library for Compose
kotlinx.coroutines- Coroutines for async programmingkotlinx.serialization- Kotlin serialization
junit- Unit testing frameworkandroidx.test.ext.junit- Android testing extensionsandroidx.compose.ui.test- Compose UI testingmockito-core,mockito-kotlin- Mocking frameworkkotlinx.coroutines.test- Coroutines testing utilitiesandroidx.test.runner- AndroidX Test Runnercom.google.truth:truth- Assertion libraryandroidx.arch.core:core-testing- For testing Architecture Componentshilt-android-testing
com.github.chuckerteam.chucker:library- HTTP inspection
- Android Studio Meerkat | 2024.3.2
- Gradle 8.14.1
- Android SDK API level 24 (minimum) - 35 (target)
- JDK 17 atau lebih baru
- Kotlin 2.1.20 (sesuai kotlinc.xml dan libs.versions.toml di build.gradle.kts app)
git clone https://github.com/yourusername/virtualsblog-android.git
cd virtualsblog-android- Buka Android Studio
- Select "Open an existing Android Studio project"
- Navigate ke folder project dan pilih
# Android Studio akan otomatis sync, atau jalankan:
./gradlew buildKonfigurasi Base URL ada di file app/src/main/java/com/virtualsblog/project/util/Constants.kt:
object Constants {
valBASE_URL:String=BuildConfig.BASE_URLvalAPI_KEY:String=BuildConfig.API_KEY// ... other constants
}Untuk Base_Url dan API Key, tambahkan ke file local.properties di root proyek Anda (buat jika belum ada):
BASE_URL=Url_Backend_Api
API_KEY=API_Key_Anda
⚠️ Penting: Pastikanlocal.propertiesada di.gitignoreAnda agar tidak ter-commit ke repository.
Kemudian, Anda bisa mengambil nilai ini di build.gradle.kts (app) dan menyediakannya sebagai BuildConfig field atau resource string.
- Connect Android device atau start emulator
- Click "Run" button atau tekan
Shift + F10
Aplikasi ini mengintegrasikan dengan backend API. Endpoint utama ada di Constants.BASE_URL.
Beberapa endpoint yang digunakan:
// Authentication endpointsPOST /loginPOST /registerGET /profilePUT /profilePUT /profile/change-passwordPOST /forget-passwordPOST /verify-otpPOST /reset-passwordPUT /profile/upload// Blog endpointsGET /postsPOST /postsGET /posts/{id}PUT /posts/{id}DELETE /posts/{id}GET /categoriesGET /categories/{id}GET /search?keyword={keyword}GET /authors/{id}POST /posts/{id}/commentsDELETE /comments/{id}POST /posts/{id}/likesUntuk keamanan, simpan konfigurasi sensitif seperti API_KEY dan BASE_URL di local.properties:
API_KEY=Url_Backend_Api
BASE_URL=API_Key_AndaAkses nilai-nilai ini dalam file build.gradle.kts (app) dan teruskan sebagai BuildConfig fields atau string resources. Di Constants.kt, Anda kemudian akan mereferensikan BuildConfig.API_KEY dan BuildConfig.BASE_URL.
- SplashScreen - Initial loading dan auth check
- LoginScreen - User authentication
- RegisterScreen - New user registration
- ForgotPasswordScreen - Memulai proses lupa password
- VerifyOtpScreen - Verifikasi OTP untuk reset password
- ResetPasswordScreen - Membuat password baru setelah OTP valid
- TermsAndConditionsScreen - Menampilkan syarat dan ketentuan
- HomeScreen - Dashboard dengan recent posts dan statistik
- ProfileScreen - User profile management dan logout
- EditProfileScreen - Mengedit data profil pengguna (nama lengkap, username dan juga email)
- ChangePasswordScreen - Mengubah password pengguna saat login
- CreatePostScreen - Form untuk membuat post baru
- PostListScreen - Menampilkan semua postingan
- PostDetailScreen - Detail view untuk post, termasuk komentar dan like
- EditPostScreen - Form untuk mengedit post yang sudah ada
- CategoriesScreen - Menampilkan daftar semua kategori
- CategoryPostsScreen - Menampilkan postingan berdasarkan kategori yang dipilih
- SearchScreen - Mencari postingan, pengguna, dan kategori
- AuthorPostsScreen - Menampilkan postingan dari author tertentu
Navigasi diatur dalam BlogNavGraph.kt menggunakan NavHostController. Destinasi didefinisikan di BlogDestinations.kt.
// Contoh NavHost dari BlogNavGraph.ktNavHost(navController = navController, startDestination =BlogDestinations.SPLASH_ROUTE) {
composable(BlogDestinations.SPLASH_ROUTE) { SplashScreen(...) }
composable(BlogDestinations.LOGIN_ROUTE) { LoginScreen(...) }
// ...composable lainnya untuk register, home, post detail, profile, dll.
}// Light ThemevalPrimary=Color(0xFF6366F1)
valSecondary=Color(0xFF10B981)
valBackground=Color(0xFFFAFAFA)
valSurface=Color(0xFFFFFFFF)
// Dark ThemevalPrimaryDark=Color(0xFF818CF8)
valSecondaryDark=Color(0xFF34D399)
valBackgroundDark=Color(0xFF111827)
valSurfaceDark=Color(0xFF1F2937)- Display Large - 57.sp, Bold
- Headline Large - 32.sp, Bold
- Title Large - 22.sp, SemiBold
- Body Large - 16.sp, Normal
- Label Large - 14.sp, Medium
# Run unit tests
./gradlew testDebugUnitTest
# Run with coverage
./gradlew testDebugUnitTestCoverage# Run UI tests
./gradlew connectedAndroidTest
# Run specific test class (contoh)
./gradlew connectedAndroidTest -Pandroid.testInstrumentationRunnerArguments.class=com.virtualsblog.project.LoginScreenTestTest runner kustom CustomTestRunner digunakan untuk instrumented tests.
📁 app/src/test/ # Unit tests
└── 📁 java/com/virtualsblog/project/
└── ExampleUnitTest.kt
📁 app/src/androidTest/ # Instrumentation tests
└── 📁 java/com/virtualsblog/project/
├── CustomTestRunner.kt
├── ExampleInstrumentedTest.kt
├── HiltTestActivity.kt
├── LoginScreenTest.kt (dikomentari)
├── RegisterScreenTest.kt (dikomentari)
└── data/local/dao/UserDaoTest.kt
- API Security - Semua request menggunakan API key authentication via header (API Key diambil dari konfigurasi build yang aman).
- Session Management - Token disimpan menggunakan DataStore Preferences.
- Input Validation - Validasi client-side (di UseCases dan ViewModels) dan server-side.
- HTTPS - Komunikasi dengan backend API menggunakan HTTPS (diasumsikan dari BASE_URL).
- Lazy Loading - Penggunaan LazyColumn untuk list yang efisien.
- Image Optimization - Coil untuk async image loading dengan caching.
- Memory Management - Penggunaan ViewModel dan lifecycle-aware components.
- Network Optimization - OkHttp client dengan logging interceptor dan konfigurasi timeout.
- Code Obfuscation - ProGuard rules dikonfigurasi untuk build rilis (meskipun isMinifyEnabled saat ini false).
Struktur file proyek mengikuti panduan Clean Architecture dengan pemisahan yang jelas antara layer data, domain, dan presentation. Untuk detail lengkap, lihat bagian "Architecture" di atas dan daftar file yang diunggah. Beberapa file kunci meliputi:
.idea/: Konfigurasi IDE IntelliJ/Android Studio.app/build.gradle.kts: Konfigurasi build untuk modul aplikasi.app/src/main/AndroidManifest.xml: Manifest aplikasi.app/src/main/java/com/virtualsblog/project/:BlogApplication.kt: Kelas Application utama dengan anotasi Hilt.data/: Layer data (local, remote, mappers, repositories).domain/: Layer domain (models, repository interfaces, use cases).presentation/: Layer presentasi (UI, ViewModels, navigation).di/: Modul Dependency Injection Hilt.util/: Kelas utilitas.preferences/: Pengelolaan DataStore Preferences.
app/src/androidTest/: Tes instrumentasi.app/src/test/: Tes unit lokal.build.gradle.kts(root): Konfigurasi build level proyek.settings.gradle.kts: Pengaturan proyek Gradle.gradle.properties: Properti Gradle.gradle/wrapper/gradle-wrapper.properties: Konfigurasi Gradle Wrapper.
plugins {
alias(libs.plugins.android.application) apply false
alias(libs.plugins.kotlin.android) apply false
alias(libs.plugins.kotlin.compose) apply false
alias(libs.plugins.hilt.android) apply false
alias(libs.plugins.ksp) apply false
alias(libs.plugins.kotlin.serialization) apply false
}android {
namespace ="com.virtualsblog.project"
compileSdk =35
defaultConfig {
applicationId ="com.virtualsblog.project"
minSdk =24
targetSdk =35
versionCode =1
versionName ="1.0"
testInstrumentationRunner ="com.virtualsblog.project.CustomTestRunner"// Untuk mengambil API_KEY dari local.properties:// buildConfigField("String", "API_KEY", "\"${System.getenv("API_KEY") ?: project.findProperty("API_KEY") ?: "YOUR_DEFAULT_API_KEY_IF_NOT_FOUND"}\"")
}
// ... buildFeatures { compose = true }// ... buildTypes { release { isMinifyEnabled = false ... } }
}💡 Catatan: Pastikan Anda mengkonfigurasi
buildConfigFieldatauresValueuntukAPI_KEYdibuild.gradle.kts(app) agar bisa diakses dariConstants.ktataulocal.properties
org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
android.useAndroidX=true
kotlin.code.style=official
android.nonTransitiveRClass=true[versions]
agp = "8.10.0"# Atau versi AGP yang sesuaikotlin = "2.1.20"ksp = "2.1.20-2.0.0"# atau versi KSP yang sesuai dengan KotlincomposeBom = "2025.05.01"# atau BOM terbaruhilt = "2.51.1"# atau versi Hilt terbaruretrofit = "2.11.0"room = "2.6.1"# atau versi Room terbaru# ... versi lainnya# Clean project
./gradlew clean
# Build debug APK
./gradlew assembleDebug
# Build release APK
./gradlew assembleRelease
# Run all unit tests
./gradlew testDebugUnitTest
# Run all instrumentation tests
./gradlew connectedAndroidTest
# Generate test coverage (unit tests)
./gradlew testDebugUnitTestCoverage- Feature Development - Buat branch baru untuk setiap fitur.
- Code Review - Pull request dengan review dari tim.
- Testing - Pastikan unit tests dan UI tests lolos sebelum merge.
- CI/CD - (Opsional) Setup automated build dan deployment.
POST /loginContent-Type: application/jsonX-API-KEY: {YOUR_API_KEY_FROM_CONFIG}
{
"username": "string",
"password": "string"
}POST /registerContent-Type: application/jsonX-API-KEY: {YOUR_API_KEY_FROM_CONFIG}
{
"fullname": "string",
"email": "string",
"username": "string",
"password": "string",
"confirm_password": "string"
}📖 Note: Lihat
AuthApi.ktdanBlogApi.ktuntuk daftar endpoint yang lebih lengkap.X-API-KEYakan ditambahkan oleh interceptor.
{
"status": 200,
"success": true,
"message": "Success message",
"data": {
// Data spesifik endpoint
}
}- Mobile Developer - Android development dengan Kotlin & Compose
- Backend Developer - API development untuk data management
- UI/UX Designer - Interface design dan user experience
Built with ❤️ for Praktikum Mobile