Unggulan

UAS - MovFlix

Dokumentasi Aplikasi MovFlix

Nama : Christoforus Indra Bagus Pratama

NRP : 5025231124

Mata Kuliah : Pemrograman Perangkat Bergerak

Tanggal : 14 Juni 2026

Pertemuan : 16 - Final Project

Proyek : MovFlix - Aplikasi Katalog Film Android

Kode : Github

Presentasi : Link Canva

Video : Link Youtube

1. Deskripsi Aplikasi

MovFlix adalah aplikasi katalog film (movie catalogue) Android yang menampilkan daftar film, detail film, serta pemutaran trailer. Seluruh data film diambil secara real-time dari TMDB (The Movie Database) API. Aplikasi dibangun sepenuhnya menggunakan Jetpack Compose, framework UI declarative modern dari Android, untuk menghadirkan antarmuka yang responsif dan mulus.
Pengguna dapat menjelajahi film berdasarkan kategori (Trending, Now Playing, Popular, Top Rated), mencari film dengan filter genre, melihat detail lengkap sebuah film, dan menonton trailer langsung di dalam aplikasi melalui YouTube embed. MovFlix juga dilengkapi sistem autentikasi lokal (login, register, dan guest) serta fitur watchlist yang tersimpan terpisah per akun pengguna.
Bahasa Antarmuka: antarmuka utama menggunakan istilah Inggris yang umum (Home, Search, Watch Trailer) dengan beberapa bagian berbahasa Indonesia. Minimum SDK: aplikasi kompatibel dengan Android 7.0 (API Level 24) ke atas. Arsitektur: menggunakan pola MVVM dengan tema gelap (dark theme) sinematik.

2. Fitur-Fitur Utama Aplikasi

2.1 Autentikasi Lokal (Login, Register, Guest)
Fitur: Pengguna dapat membuat akun (register), masuk (login) dengan email & password, atau memilih Masuk sebagai Guest tanpa akun.
Implementasi: Data akun disimpan lokal di Room Database. Password tidak disimpan dalam bentuk teks asli, melainkan di-hash dengan SHA-256 + salt. Status login (session) disimpan menggunakan SharedPreferences sehingga pengguna tetap login setelah aplikasi ditutup.
2.2 Navigasi Swipe Berbasis Pager
Fitur: Tiga menu utama — Home, Search, dan Profile — dapat dipindah dengan mengusap layar (swipe) maupun menekan bottom navigation bar. Keduanya tersinkron dua arah.
Implementasi: Menggunakan HorizontalPager yang dipasangkan dengan NavigationBar melalui PagerState.
2.3 Beranda Kategori dengan Hero Slider
Fitur: Halaman Home menampilkan hero slider film trending yang berganti otomatis, lalu baris kategori Now Playing, Popular, dan Top Rated yang dapat di-scroll horizontal.
Collapsing Top Bar: Header akan tersembunyi saat layar di-scroll ke bawah dan muncul kembali saat di-scroll ke atas (enter-always scroll behavior). Saat menunggu data, ditampilkan shimmer skeleton.
2.4 Pencarian dengan Filter Genre
Fitur: Pencarian film secara debounced (tanpa menekan tombol submit) dan filter berdasarkan genre chips. Hasil ditampilkan dalam grid, lengkap dengan empty state yang jelas.
2.5 Detail Film dan Pemutar Trailer
Fitur: Halaman detail menampilkan backdrop, poster, rating, durasi, genre, sinopsis, dan tombol Watch Trailer.
Pemutar Trailer: Trailer dari TMDB (berupa YouTube video id) diputar full-screen landscape di dalam aplikasi menggunakan WebView yang memuat iframe embed YouTube. Pendekatan iframe statis dipilih karena lebih andal dibanding membuka URL embed langsung.
2.6 Watchlist Per-Akun
Fitur: Pengguna dapat menyimpan film ke watchlist. Watchlist terikat ke akun — setiap akun memiliki daftar sendiri, dan akan muncul kembali saat login dengan akun yang sama.
Batasan Guest: Akun guest tidak bisa menyimpan watchlist. Saat guest menekan tombol simpan, muncul dialog peringatan untuk login atau membatalkan. Penghapusan watchlist dilengkapi undo via Snackbar.
2.7 Halaman Profile
Fitur: Menampilkan nama dan email pengguna beserta daftar watchlist miliknya. Untuk guest, ditampilkan ajakan untuk login.

3. Arsitektur Aplikasi

MovFlix menggunakan arsitektur MVVM (Model-View-ViewModel) yang direkomendasikan Google. Arsitektur ini memisahkan logika bisnis dari antarmuka, sehingga kode lebih terstruktur, testable, dan mudah dirawat. Lapisan data menerapkan prinsip Single Source of Truth melalui Repository.

UI Layer (Presentation)

Jetpack Compose, Material 3, Navigation, HorizontalPager, Coil

ViewModel Layer (State Management)

ViewModel, StateFlow, collectAsState

Repository Layer (Data Abstraction)

MovieRepository, AuthRepository, ServiceLocator (DI)

Data Layer

Remote: Retrofit + OkHttp (TMDB API)  |  Local: Room (SQLite), SharedPreferences

3.1 Penjelasan Setiap Layer
Layer Deskripsi Tanggung Jawab
UI Layer Lapisan presentasi berbasis Jetpack Compose & Material 3 untuk UI deklaratif yang modern. Menampilkan data, menangkap input, navigasi antar layar
ViewModel Mengelola state UI dengan StateFlow dan menjembatani UI dengan Repository. Mengelola state, menangani event UI, menyediakan data ke UI
Repository Abstraksi sumber data. Menggabungkan data remote (TMDB) dan local (Room) menjadi satu sumber. Menyediakan data, logika bisnis (watchlist per-akun, kandidat trailer)
Data Layer Retrofit untuk REST API TMDB; Room untuk database lokal; SharedPreferences untuk session. Network request, akses & penyimpanan database
3.2 Dependency Injection
Aplikasi memakai DI manual sederhana melalui object ServiceLocator yang membuat instance singleton dari Retrofit, Room database, serta Repository. Pendekatan ini ringan dan cukup untuk lingkup proyek tanpa overhead Hilt/Dagger.

4. Struktur File dan Folder Proyek

Berikut struktur direktori utama proyek MovFlix beserta fungsi tiap bagiannya:
Struktur Proyek (ringkas)
FP-PPB/ └── app/src/main/ ├── kotlin/com/example/moviecatalogue/ │ ├── MainActivity.kt Entry point + setup navigation │ ├── MovieCatalogueApp.kt Application class │ ├── SplashScreen.kt Splash screen (logo) │ ├── data/ │ │ ├── auth/ PasswordHasher, SessionManager │ │ ├── local/ Room: MovieDao, UserDao, │ │ │ MovieDatabase, MovieEntity, UserEntity │ │ ├── remote/ ApiService (TMDB), Dtos │ │ └── repository/ MovieRepositoryImpl, AuthRepositoryImpl │ ├── di/ │ │ └── ServiceLocator.kt Dependency Injection │ ├── domain/ Model + interface (Movie, UserSession, │ │ MovieRepository, AuthRepository) │ └── ui/ │ ├── components/ MovieCard, MovieSlider, │ │ YouTubeTrailerPlayer │ ├── navigation/ Navigation.kt (NavHost + Pager) │ ├── screens/ │ │ ├── home/ HomeScreen, HomeViewModel │ │ ├── search/ SearchScreen, SearchViewModel │ │ ├── detail/ DetailScreen, DetailViewModel │ │ ├── profile/ ProfileScreen, ProfileViewModel │ │ └── auth/ LoginScreen, RegisterScreen, AuthViewModel │ └── theme/ Color, Theme, Typography ├── res/ Drawable, values └── AndroidManifest.xml
4.1 Penjelasan Folder Utama
data/remote/
ApiService.kt mendefinisikan endpoint TMDB (trending, now playing, popular, top rated, search, detail, videos, genres) dengan Retrofit. Dtos.kt berisi Data Transfer Object untuk parsing JSON respons API.
data/local/
Implementasi Room: MovieDao & UserDao (operasi CRUD), MovieDatabase (kelas database), MovieEntity (watchlist, ber-key gabungan id+userId) dan UserEntity (akun pengguna).
data/auth/
PasswordHasher.kt melakukan hashing password (SHA-256 + salt). SessionManager.kt menyimpan & mengekspos session pengguna sebagai StateFlow melalui SharedPreferences.
data/repository/ & domain/
MovieRepositoryImpl & AuthRepositoryImpl mengimplementasikan interface di domain/. Repository film menggabungkan API dan Room serta menyaring watchlist sesuai user aktif.
ui/navigation/
Navigation.kt berisi AppNavigation (NavHost: Splash, Login, Register, Main, Detail) dan MainScreen (HorizontalPager + bottom navigation).
ui/screens/ & ui/components/
Tiap fitur memiliki Screen (Composable) dan ViewModel-nya. Komponen yang dipakai berulang seperti MovieCard, MovieSlider, dan YouTubeTrailerPlayer berada di components/.

5. Penjelasan Detil Kode MainActivity.kt

MainActivity.kt adalah single activity yang menjadi entry point aplikasi. Tugasnya menyiapkan dependency, mengaktifkan tema, dan menampilkan graph navigasi. Berikut penjelasan tiap bagiannya.
5.1 Class MainActivity dan onCreate()
MainActivity.kt
class MainActivity : ComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // Mengaktifkan tampilan edge-to-edge (immersive)
        enableEdgeToEdge()

        // Dependency Injection via ServiceLocator
        val repository = ServiceLocator.provideRepository(applicationContext)
        val authRepository = ServiceLocator.provideAuthRepository(applicationContext)

        setContent {
            FinalProjectTheme {
                Surface(modifier = Modifier.fillMaxSize()) {
                    AppNavigation(
                        repository = repository,
                        authRepository = authRepository
                    )
                }
            }
        }
    }
}
Penjelasan:
  • ComponentActivity: base activity yang mendukung Jetpack Compose.
  • enableEdgeToEdge(): membuat konten menggambar hingga di belakang status bar & navigation bar untuk tampilan modern.
  • ServiceLocator.provideRepository / provideAuthRepository: mengambil instance singleton Repository film dan Repository autentikasi (Dependency Injection manual).
  • setContent { }: mendefinisikan seluruh UI Compose untuk activity ini.
  • FinalProjectTheme: membungkus aplikasi dengan tema gelap (Material 3) sekaligus mengatur warna system bar.
  • AppNavigation(...): memasang graph navigasi dengan kedua repository sebagai dependency.
5.2 AppNavigation — Graph Navigasi
Navigation.kt (ringkas)
@Composable
fun AppNavigation(repository: MovieRepository, authRepository: AuthRepository) {
    val navController = rememberNavController()
    val session by authRepository.session.collectAsState()
    val isGuest = session?.isGuest == true

    NavHost(navController, startDestination = Screen.Splash.route) {
        composable(Screen.Splash.route) {
            SplashScreen(onTimeout = {
                // Sudah login -> Main, belum -> Login
                val target = if (session != null) Screen.Main.route else Screen.Login.route
                navController.navigate(target) { popUpTo(Screen.Splash.route) { inclusive = true } }
            })
        }
        composable(Screen.Login.route) { /* LoginScreen */ }
        composable(Screen.Register.route) { /* RegisterScreen */ }
        composable(Screen.Main.route) { /* MainScreen (pager) */ }
        composable(Screen.Detail.route) { /* DetailScreen */ }
    }
}
Penjelasan: NavHost mendaftarkan seluruh rute. State session diamati sebagai StateFlow sehingga UI bereaksi otomatis saat login/logout. Splash menentukan tujuan awal: Main jika sudah ada sesi, atau Login jika belum.
5.3 MainScreen — Pager + Bottom Navigation
Navigation.kt (ringkas)
@Composable
fun MainScreen(/* repository, authRepository, isGuest, callbacks */) {
    val pagerState = rememberPagerState(pageCount = { bottomNavItems.size })
    val scope = rememberCoroutineScope()

    Scaffold(
        bottomBar = {
            NavigationBar {
                bottomNavItems.forEachIndexed { index, item ->
                    NavigationBarItem(
                        selected = pagerState.currentPage == index,
                        onClick = { scope.launch { pagerState.animateScrollToPage(index) } },
                        icon = { /* Home / Search / Profile */ },
                        label = { Text(item.label) }
                    )
                }
            }
        }
    ) { padding ->
        HorizontalPager(state = pagerState, modifier = Modifier.padding(padding)) { page ->
            when (page) {
                0 -> HomeScreen(...)
                1 -> SearchScreen(...)
                2 -> ProfileScreen(...)
            }
        }
    }
}
Penjelasan: HorizontalPager menampung tiga halaman yang bisa digeser (swipe). NavigationBar dan pager dihubungkan lewat pagerState.currentPage dan animateScrollToPage(), sehingga menekan menu dan menggeser layar saling sinkron.
5.4 SplashScreen
SplashScreen.kt (ringkas)
@Composable
fun SplashScreen(onTimeout: () -> Unit) {
    LaunchedEffect(Unit) {
        delay(2000)      // tampilkan logo 2 detik
        onTimeout()
    }
    Surface(modifier = Modifier.fillMaxSize(), color = Color.Black) {
        Box(contentAlignment = Alignment.Center) {
            Image(painter = painterResource(R.drawable.movflix_logo), contentDescription = "MovFlix Logo")
        }
    }
}
Penjelasan: LaunchedEffect menjalankan delay 2 detik untuk menampilkan logo, lalu memanggil onTimeout() yang memutuskan navigasi berikutnya (Login atau Main).

6. Alur Eksekusi Aplikasi

Berikut alur lengkap dari peluncuran hingga aplikasi siap digunakan:
1. Aplikasi Diluncurkan: Android memanggil MainActivity.onCreate().
2. Setup & DI: enableEdgeToEdge() dijalankan, lalu ServiceLocator menyediakan MovieRepository dan AuthRepository (singleton).
3. UI Dipasang: setContent memasang FinalProjectTheme dan AppNavigation.
4. Splash Screen: Logo MovFlix ditampilkan selama 2 detik.
5. Pengecekan Session: Setelah delay, aplikasi memeriksa session. Jika sudah login → Main; jika belum → Login.
6. Autentikasi: Pengguna login, register, atau memilih guest. Saat berhasil, session disimpan dan navigasi menuju Main.
7. Main Screen: HorizontalPager + bottom navigation dirender, halaman Home tampil pertama.
8. Pemuatan Data: Setiap ViewModel memanggil Repository untuk mengambil data film dari TMDB API (atau watchlist dari Room), lalu meng-update StateFlow.
9. UI Recompose: Perubahan state otomatis memicu recompose sehingga daftar film tampil. Aplikasi siap untuk interaksi.

7. Interaksi User dan Event Flow

MovFlix menggunakan event-driven architecture: interaksi di UI memanggil callback yang terhubung ke method ViewModel, yang lalu memperbarui state dan/atau database. Berikut alur tiap interaksi utama (disertai panduan manual penggunaan).
Register / Login
Cara pakai: Pada layar Login, isi email & password lalu tekan Masuk, atau tekan Daftar untuk membuat akun baru.
Flow: Input user → AuthViewModel.login()/register() → validasi → AuthRepository cek/simpan ke Room (password di-hash) → session disimpan → navigasi ke Main.
Masuk sebagai Guest
Cara pakai: Tekan Masuk sebagai Guest di layar Login.
Flow: AuthViewModel.loginAsGuest() → session guest disimpan → masuk ke Main. Tombol akun pada Home berubah menjadi Masuk.
Menjelajah & Mencari Film
Cara pakai: Geser antar tab atau scroll kategori di Home; buka tab Search dan ketik judul, pilih genre untuk memfilter.
Flow: ViewModel memanggil MovieRepository → Retrofit request ke TMDB → respons dipetakan ke domain model → StateFlow update → grid film recompose.
Membuka Detail & Menonton Trailer
Cara pakai: Tekan poster film untuk membuka detail, lalu tekan Watch Trailer.
Flow: DetailViewModel mengambil detail + daftar video dari TMDB → trailer (YouTube id) diputar full-screen di YouTubeTrailerPlayer (WebView iframe).
Menyimpan ke Watchlist
Cara pakai: Pada detail, tekan tombol Watchlist untuk menyimpan/menghapus.
Flow (user login): DetailViewModel.toggleWatchlist()MovieRepository.addToWatchlist() menyimpan ke Room dengan userId aktif → ikon berubah menjadi Saved.
Flow (guest): Muncul dialog "Login diperlukan" dengan pilihan Login atau Batal.
Melihat Profile & Logout
Cara pakai: Buka tab Profile untuk melihat nama, email, dan watchlist. Tekan ikon Logout untuk keluar.
Flow: ProfileViewModel membaca session & watchlist (Room) milik user; Logout memanggil AuthRepository.logout() → session dihapus → kembali ke Login.

8. Teknologi dan Dependencies

MovFlix dibangun dengan berbagai library modern dari ekosistem Android:
Teknologi Versi Kegunaan
Jetpack ComposeBOM 2024.09.00UI declarative framework berbasis Kotlin
Material 3LatestDesign system & komponen siap pakai (Scaffold, TopAppBar, dll)
Navigation Compose2.8.3Navigasi antar layar (NavHost, routes)
HorizontalPager(Compose Foundation)Navigasi swipe antar tab
Retrofit2.11.0HTTP client untuk REST API TMDB
OkHttp4.12.0Networking & interceptor (Authorization header)
Gson(converter 2.11.0)Parsing JSON respons API
Room2.6.1Database lokal (watchlist & akun)
KSP2.0.21-1.0.27Annotation processor untuk Room
Coil2.7.0Memuat gambar poster/backdrop
ViewModel + StateFlowLifecycle 2.8.6State management reaktif
Coroutines1.8.1Pemrograman asynchronous
WebView(Android SDK)Memutar trailer via YouTube iframe embed
SharedPreferences(Android SDK)Menyimpan session login
Sumber data: seluruh informasi film berasal dari TMDB API (https://api.themoviedb.org/3/). Min SDK 24, Target/Compile SDK 35, ditulis dalam Kotlin.

9. Kesimpulan

MovFlix menunjukkan penerapan teknologi Android modern untuk membangun aplikasi katalog film yang lengkap dan rapi. Dengan arsitektur MVVM, Jetpack Compose untuk UI, Retrofit untuk konsumsi TMDB API, dan Room untuk penyimpanan lokal, aplikasi memiliki fondasi yang kuat dan mudah dikembangkan.
Fitur seperti autentikasi lokal, watchlist per-akun, pencarian dengan filter, pemutaran trailer, dan navigasi swipe membuat aplikasi terasa modern dan ramah pengguna. Pemisahan tanggung jawab antar layer yang jelas memastikan kode mudah dirawat, diuji, dan diperluas dengan fitur baru di masa depan.

Komentar

Postingan Populer