1117 lines
30 KiB
Markdown
1117 lines
30 KiB
Markdown
# Aplikasi Absensi Akademik Berbasis Koordinat dan Foto
|
|
|
|
Sistem Absensi Mahasiswa Universitas Bhayangkara Jakarta Raya
|
|
Berbasis Android dengan validasi lokasi GPS dan foto real-time
|
|
|
|
---
|
|
|
|
## INFORMASI PROYEK
|
|
|
|
Nama : Rakha Adi Saputro
|
|
NPM : 202310715083
|
|
Mata Kuliah : Pemrograman Mobile
|
|
Universitas : Universitas Bhayangkara Jakarta Raya
|
|
Tahun : 2025-2026
|
|
|
|
---
|
|
|
|
## DESKRIPSI SISTEM
|
|
|
|
Aplikasi absensi mahasiswa modern berbasis Android yang mengimplementasikan arsitektur MVVM (Model-View-ViewModel) dengan pendekatan offline-first. Sistem ini memastikan validitas kehadiran mahasiswa melalui verifikasi lokasi GPS dan pengambilan foto selfie secara real-time saat melakukan absensi.
|
|
|
|
Fitur utama:
|
|
- Validasi lokasi berbasis GPS dengan radius 500 meter dari titik kampus
|
|
- Pengambilan foto selfie wajib saat absensi
|
|
- Penyimpanan data lokal dengan sinkronisasi otomatis ke backend
|
|
- Sistem login offline dengan enkripsi data
|
|
- Riwayat absensi tersimpan secara lokal
|
|
- Anti-spam: Satu foto untuk satu kali absensi
|
|
|
|
---
|
|
|
|
## DEPENDENCY LENGKAP (build.gradle.kts)
|
|
|
|
### Core Android
|
|
```kotlin
|
|
// AndroidX Core
|
|
implementation("androidx.core:core-ktx:1.17.0")
|
|
// Kotlin standard library dan extensions
|
|
```
|
|
|
|
### Jetpack Compose
|
|
```kotlin
|
|
// Compose BOM (Bill of Materials) - Mengelola versi Compose
|
|
implementation(platform("androidx.compose:compose-bom:2024.09.00"))
|
|
|
|
// Compose UI
|
|
implementation("androidx.compose.ui:ui")
|
|
implementation("androidx.compose.ui:ui-graphics")
|
|
implementation("androidx.compose.ui:ui-tooling-preview")
|
|
|
|
// Material Design 3
|
|
implementation("androidx.compose.material3:material3")
|
|
|
|
// Material Icons Extended
|
|
implementation("androidx.compose.material:material-icons-extended:1.6.0")
|
|
```
|
|
|
|
### Lifecycle & ViewModel
|
|
```kotlin
|
|
// Lifecycle Runtime
|
|
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.9.4")
|
|
implementation("androidx.lifecycle:lifecycle-runtime-compose:2.7.0")
|
|
|
|
// ViewModel untuk Compose
|
|
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.7.0")
|
|
```
|
|
|
|
### Activity & Navigation
|
|
```kotlin
|
|
// Activity untuk Compose
|
|
implementation("androidx.activity:activity-compose:1.9.0")
|
|
```
|
|
|
|
### Location Services
|
|
```kotlin
|
|
// Google Play Services Location
|
|
implementation("com.google.android.gms:play-services-location:21.0.1")
|
|
```
|
|
|
|
### Database (Room)
|
|
```kotlin
|
|
// Room components
|
|
implementation("androidx.room:room-runtime:2.6.1")
|
|
implementation("androidx.room:room-ktx:2.6.1")
|
|
kapt("androidx.room:room-compiler:2.6.1") // Annotation processor
|
|
```
|
|
|
|
### Network
|
|
```kotlin
|
|
// Retrofit
|
|
implementation("com.squareup.retrofit2:retrofit:2.9.0")
|
|
implementation("com.squareup.retrofit2:converter-gson:2.9.0")
|
|
|
|
// OkHttp
|
|
implementation("com.squareup.okhttp3:logging-interceptor:4.11.0")
|
|
```
|
|
|
|
### Security
|
|
```kotlin
|
|
// Encrypted SharedPreferences
|
|
implementation("androidx.security:security-crypto:1.1.0-alpha06")
|
|
```
|
|
|
|
### Background Work
|
|
```kotlin
|
|
// WorkManager
|
|
implementation("androidx.work:work-runtime-ktx:2.9.0")
|
|
```
|
|
|
|
### Coroutines
|
|
```kotlin
|
|
// Kotlin Coroutines
|
|
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3")
|
|
```
|
|
|
|
### Image Loading
|
|
```kotlin
|
|
// Coil untuk Compose
|
|
implementation("io.coil-kt:coil-compose:2.6.0")
|
|
```
|
|
|
|
### JSON Processing
|
|
```kotlin
|
|
// Gson
|
|
implementation("com.google.code.gson:gson:2.10.1")
|
|
```
|
|
|
|
### Testing
|
|
```kotlin
|
|
// Unit Testing
|
|
testImplementation("junit:junit:4.13.2")
|
|
|
|
// Instrumented Testing
|
|
androidTestImplementation("androidx.test.ext:junit:1.3.0")
|
|
androidTestImplementation("androidx.test.espresso:espresso-core:3.7.0")
|
|
androidTestImplementation(platform("androidx.compose:compose-bom:2024.09.00"))
|
|
androidTestImplementation("androidx.compose.ui:ui-test-junit4")
|
|
|
|
// Debug
|
|
debugImplementation("androidx.compose.ui:ui-tooling")
|
|
debugImplementation("androidx.compose.ui:ui-test-manifest")
|
|
```
|
|
|
|
### Gradle Plugins
|
|
```kotlin
|
|
plugins {
|
|
alias(libs.plugins.android.application) // AGP 8.13.2
|
|
alias(libs.plugins.kotlin.android) // Kotlin 2.0.21
|
|
alias(libs.plugins.kotlin.compose) // Compose Compiler
|
|
id("org.jetbrains.kotlin.kapt") // KAPT untuk Room
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## ALASAN PEMILIHAN TEKNOLOGI
|
|
|
|
### Mengapa Jetpack Compose?
|
|
1. **Modern & Declarative**: Lebih intuitif dan less boilerplate dibanding XML
|
|
2. **Type-safe**: Compile-time error detection
|
|
3. **Reactive**: Automatic UI updates saat state berubah
|
|
4. **Performance**: Efficient rendering dengan recomposition
|
|
5. **Official**: Recommended oleh Google untuk new projects
|
|
6. **Community**: Strong community support dan active development
|
|
|
|
### Mengapa Room Database?
|
|
1. **Type-safe SQL**: Compile-time SQL query verification
|
|
2. **Coroutine Support**: Native async/await dengan suspend functions
|
|
3. **Reactive Queries**: Flow<T> untuk reactive updates
|
|
4. **Migration Support**: Easy database version management
|
|
5. **Performance**: Optimized SQLite wrapper
|
|
6. **Official**: Part of Android Jetpack
|
|
|
|
### Mengapa WorkManager?
|
|
1. **Guaranteed Execution**: Task akan dijalankan meski app tertutup
|
|
2. **Battery Efficient**: System-managed scheduling
|
|
3. **Constraints**: Network, battery, storage constraints
|
|
4. **Backward Compatible**: Works dari API 14+
|
|
5. **Retry Logic**: Built-in retry dengan backoff
|
|
6. **Official**: Recommended untuk background work
|
|
|
|
### Mengapa Retrofit + OkHttp?
|
|
1. **Type-safe**: Type-safe REST client
|
|
2. **Coroutine Support**: Native suspend functions
|
|
3. **Converter**: Auto JSON parsing dengan Gson
|
|
4. **Interceptor**: Logging, auth, retry logic
|
|
5. **Industry Standard**: Most popular Android HTTP client
|
|
6. **Maintained**: Active development dan support
|
|
|
|
### Mengapa Encrypted SharedPreferences?
|
|
1. **Security**: AES256-GCM encryption
|
|
2. **Hardware-backed**: Android Keystore System
|
|
3. **Transparent**: No manual encryption code needed
|
|
4. **Simple API**: Same as regular SharedPreferences
|
|
5. **Official**: Part of Jetpack Security
|
|
6. **Compliant**: Meets security best practices
|
|
|
|
### Mengapa Kotlin Coroutines?
|
|
1. **Lightweight**: Efficient thread management
|
|
2. **Structured Concurrency**: Prevents memory leaks
|
|
3. **Sequential Code**: Async code looks synchronous
|
|
4. **Exception Handling**: Structured exception propagation
|
|
5. **Cancellation**: Automatic cleanup
|
|
6. **Official**: First-class support in Android
|
|
|
|
### Mengapa Coil untuk Image Loading?
|
|
1. **Kotlin-first**: Written in Kotlin untuk Kotlin
|
|
2. **Compose-native**: AsyncImage composable
|
|
3. **Coroutine-based**: Non-blocking operations
|
|
4. **Modern**: Uses OkHttp, supports latest formats
|
|
5. **Lightweight**: Smaller APK size vs Glide/Picasso
|
|
6. **Fast**: Memory & disk caching
|
|
|
|
---
|
|
|
|
## PERBANDINGAN ALTERNATIF
|
|
|
|
### UI Framework
|
|
- **Jetpack Compose** vs XML Views
|
|
- Compose: Less code, reactive, modern
|
|
- XML: Mature, more resources, backward compatible
|
|
- **Pilihan**: Compose (future-proof, better DX)
|
|
|
|
### Database
|
|
- **Room** vs Realm vs SQLite
|
|
- Room: Type-safe, official, Jetpack integration
|
|
- Realm: Fast, cross-platform
|
|
- SQLite: Full control, verbose
|
|
- **Pilihan**: Room (best practices, official support)
|
|
|
|
### Image Loading
|
|
- **Coil** vs Glide vs Picasso
|
|
- Coil: Kotlin-first, Compose-native, modern
|
|
- Glide: Mature, feature-rich, large
|
|
- Picasso: Simple, lightweight, older
|
|
- **Pilihan**: Coil (best for Compose)
|
|
|
|
### HTTP Client
|
|
- **Retrofit** vs Ktor vs Volley
|
|
- Retrofit: Type-safe, widely used, mature
|
|
- Ktor: Kotlin-native, modern, less adoption
|
|
- Volley: Google-made, older, less features
|
|
- **Pilihan**: Retrofit (industry standard)
|
|
|
|
### State Management
|
|
- **StateFlow** vs LiveData vs RxJava
|
|
- StateFlow: Kotlin-native, Compose-friendly
|
|
- LiveData: Lifecycle-aware, older
|
|
- RxJava: Powerful, steep learning curve
|
|
- **Pilihan**: StateFlow (modern, simple, official)
|
|
|
|
---
|
|
|
|
## ARSITEKTUR APLIKASI
|
|
|
|
### Pattern & Struktur
|
|
MVVM (Model-View-ViewModel) dengan Offline-First Architecture
|
|
|
|
```
|
|
presentation/ UI Layer (Jetpack Compose)
|
|
├── auth/ Halaman Login & Registrasi
|
|
├── absensi/ Halaman Absensi Utama
|
|
└── history/ Halaman Riwayat Absensi
|
|
|
|
data/ Data Layer
|
|
├── local/ Local Storage
|
|
│ ├── database/ Room Database
|
|
│ ├── dao/ Data Access Object
|
|
│ └── entity/ Database Entity
|
|
├── repository/ Repository Pattern
|
|
├── network/ Network Service (n8n)
|
|
├── worker/ Background Sync Worker
|
|
└── model/ Data Models
|
|
|
|
utils/ Utility Classes
|
|
├── NetworkUtils Network Connection Check
|
|
└── ImageUtils Image Processing & Base64
|
|
```
|
|
|
|
---
|
|
|
|
## TEKNOLOGI & LIBRARY
|
|
|
|
### Platform & Bahasa
|
|
- **Platform**: Android
|
|
- **Bahasa**: Kotlin 2.0.21
|
|
- **Min SDK**: 28 (Android 9.0 Pie)
|
|
- Alasan: Support untuk Security Crypto, modern permission system, dan coverage market share yang memadai
|
|
- **Target SDK**: 36 (Android 14+)
|
|
- **Compile SDK**: 36
|
|
- **JDK**: Java 11 (source & target compatibility)
|
|
|
|
### UI Framework & Design System
|
|
**Jetpack Compose** - Modern Declarative UI Framework
|
|
- **Compose BOM**: 2024.09.00
|
|
- **androidx.compose.ui**: Core Compose UI
|
|
- **androidx.compose.ui.graphics**: Graphics primitives
|
|
- **androidx.compose.ui.tooling**: Preview & debugging tools
|
|
- **Keunggulan**:
|
|
- Less code dibanding XML
|
|
- Reactive & declarative
|
|
- Type-safe
|
|
- Hot reload support
|
|
- Interoperability dengan View system
|
|
|
|
**Material Design 3**
|
|
- **androidx.compose.material3**: Material Design 3 components
|
|
- **Components yang digunakan**:
|
|
- Scaffold (app structure)
|
|
- TopAppBar (navigation bar)
|
|
- Card (content containers)
|
|
- Button & OutlinedButton (actions)
|
|
- OutlinedTextField (form inputs)
|
|
- Text (typography)
|
|
- CircularProgressIndicator (loading states)
|
|
- AlertDialog (confirmations)
|
|
- **Fitur**: Dynamic color, adaptive layouts, modern color system
|
|
|
|
**Material Icons Extended**
|
|
- **Version**: 1.6.0
|
|
- **Library**: androidx.compose.material:material-icons-extended
|
|
- **Icons**: Person, Lock, Visibility, VisibilityOff, CameraAlt, MyLocation, History, Logout, Check, Close
|
|
- **Total Icons**: 2000+ icons tersedia
|
|
|
|
### Database & Storage Layer
|
|
**Room Database** - SQLite ORM (Object-Relational Mapping)
|
|
- **Version**: 2.6.1
|
|
- **Components**:
|
|
- **room-runtime**: Core library
|
|
- **room-ktx**: Kotlin extensions & coroutine support
|
|
- **room-compiler**: Annotation processor (KAPT)
|
|
- **Fitur yang digunakan**:
|
|
- @Entity (table definition)
|
|
- @Dao (data access object)
|
|
- @Query (SQL queries)
|
|
- @Insert, @Update, @Delete
|
|
- Flow<T> untuk reactive queries
|
|
- Suspend functions untuk coroutines
|
|
- Migration support
|
|
- **Table**: attendance_history
|
|
- **Keunggulan**: Compile-time verification, type-safe queries, reactive streams
|
|
|
|
**Encrypted SharedPreferences** - Secure Key-Value Storage
|
|
- **Library**: androidx.security:security-crypto:1.1.0-alpha06
|
|
- **Encryption**: AES256-GCM (Galois/Counter Mode)
|
|
- **Key Management**: MasterKey dengan Android Keystore System
|
|
- **Key Scheme**: AES256_GCM
|
|
- **Value Encryption**: AES256_GCM
|
|
- **Key Encryption**: AES256_SIV (Synthetic IV)
|
|
- **Fitur**: Transparent encryption/decryption, hardware-backed keys
|
|
- **Data yang disimpan**: Username, Password, isRegistered, isLogin (semua terenkripsi)
|
|
|
|
### Location Services
|
|
**Google Play Services Location**
|
|
- **Version**: 21.0.1
|
|
- **Library**: com.google.android.gms:play-services-location
|
|
- **API**: Fused Location Provider API
|
|
- **Fitur yang digunakan**:
|
|
- FusedLocationProviderClient (high-level API)
|
|
- LocationRequest (accuracy & interval settings)
|
|
- LocationCallback (location updates)
|
|
- Priority: PRIORITY_HIGH_ACCURACY
|
|
- **Validasi**:
|
|
- 12 campus points dengan koordinat GPS
|
|
- Haversine Formula untuk kalkulasi jarak
|
|
- Location.distanceBetween() (Android built-in)
|
|
- Max radius: 500 meter
|
|
- **Keunggulan**: Battery-efficient, most accurate location
|
|
|
|
### Network & Backend Integration
|
|
**Retrofit** - Type-safe HTTP Client
|
|
- **Version**: 2.9.0
|
|
- **Library**: com.squareup.retrofit2:retrofit
|
|
- **Fitur**: REST API calls, coroutine support, request/response converters
|
|
- **Usage**: POST data absensi ke n8n webhook
|
|
|
|
**Gson** - JSON Serialization/Deserialization
|
|
- **Gson Version**: 2.10.1
|
|
- **Retrofit Converter**: com.squareup.retrofit2:converter-gson:2.9.0
|
|
- **Fitur**: Automatic JSON parsing, custom type adapters
|
|
- **Usage**: Convert data objects ke JSON payload
|
|
|
|
**OkHttp** - HTTP Client & Interceptor
|
|
- **Version**: 4.11.0
|
|
- **Library**: com.squareup.okhttp3:logging-interceptor
|
|
- **Fitur**: HTTP logging, connection pooling, interceptors
|
|
- **Usage**: Debug network requests/responses, timeout configuration
|
|
- **Timeout Settings**: 30 detik connection & read timeout
|
|
|
|
**n8n Webhook Integration**
|
|
- **Backend**: n8n Self-hosted Workflow Automation
|
|
- **Host**: n8n.lab.ubharajaya.ac.id
|
|
- **Method**: HTTP POST
|
|
- **Content-Type**: application/json
|
|
- **Endpoint Production**: /webhook/23c6993d-1792-48fb-ad1c-ffc78a3e6254
|
|
- **Endpoint Testing**: /webhook-test/23c6993d-1792-48fb-ad1c-ffc78a3e6254
|
|
- **Payload**: JSON dengan foto Base64, koordinat, timestamp, mata kuliah
|
|
|
|
### Background Processing
|
|
**WorkManager** - Background Task Scheduler
|
|
- **Version**: 2.9.0
|
|
- **Library**: androidx.work:work-runtime-ktx
|
|
- **Fitur**:
|
|
- Guaranteed execution (even after app restart)
|
|
- Constraints (network, battery, storage)
|
|
- Retry logic dengan exponential backoff
|
|
- Work chaining
|
|
- CoroutineWorker integration
|
|
- **Usage**: AttendanceSyncWorker untuk sync data PENDING ke backend
|
|
- **Trigger**: Network available constraint
|
|
- **Strategy**: Periodic check & automatic retry
|
|
|
|
**Kotlin Coroutines** - Asynchronous Programming
|
|
- **Version**: 1.7.3
|
|
- **Library**: org.jetbrains.kotlinx:kotlinx-coroutines-android
|
|
- **Dispatchers**:
|
|
- **Dispatchers.Main**: UI operations & state updates
|
|
- **Dispatchers.IO**: Network requests & database operations
|
|
- **Dispatchers.Default**: CPU-intensive computations
|
|
- **Features**: suspend functions, async/await, structured concurrency
|
|
- **Usage**: Semua async operations (database, network, location)
|
|
|
|
**Flow & StateFlow** - Reactive Streams
|
|
- **Flow**: Cold stream untuk one-time operations
|
|
- **StateFlow**: Hot stream untuk UI state management
|
|
- **MutableStateFlow**: Mutable state holder
|
|
- **collectAsState()**: Compose integration untuk observe state
|
|
- **Usage**: ViewModel state management, database queries, UI updates
|
|
|
|
### Image Processing
|
|
**Coil** - Image Loading Library untuk Compose
|
|
- **Version**: 2.6.0
|
|
- **Library**: io.coil-kt:coil-compose
|
|
- **Fitur**:
|
|
- AsyncImage composable
|
|
- Memory & disk caching
|
|
- Image transformations
|
|
- Compose-first design
|
|
- Coroutine-based
|
|
- **Usage**: Load & display foto absensi di riwayat
|
|
|
|
**Custom Image Utils**
|
|
- **Base64 Encoding**: Convert Bitmap ke Base64 string
|
|
- **Bitmap Compression**: JPEG compression dengan quality 80%
|
|
- **File I/O**: Save/load foto dari internal storage
|
|
- **Camera Integration**: ActivityResultContracts.TakePicture()
|
|
- **Usage**: Prepare foto untuk kirim ke backend
|
|
|
|
### Architecture Components
|
|
**Lifecycle** - Lifecycle-Aware Components
|
|
- **lifecycle-runtime-ktx**: 2.9.4
|
|
- **lifecycle-runtime-compose**: 2.7.0
|
|
- **lifecycle-viewmodel-compose**: 2.7.0
|
|
- **Fitur**: LifecycleOwner, ViewModelScope, collectAsStateWithLifecycle
|
|
- **Usage**: Manage UI lifecycle, survive configuration changes
|
|
|
|
**ViewModel** - UI State Holder
|
|
- **Library**: androidx.lifecycle:lifecycle-viewmodel-compose
|
|
- **Features**: Survive configuration changes, ViewModelScope
|
|
- **ViewModels**: AuthViewModel, AbsensiViewModel, AttendanceHistoryViewModel
|
|
- **State Management**: StateFlow untuk expose state ke UI
|
|
|
|
**Activity Compose**
|
|
- **Version**: 1.9.0
|
|
- **Library**: androidx.activity:activity-compose
|
|
- **Features**: setContent {} untuk Compose, ComponentActivity, permission handling
|
|
- **Usage**: MainActivity sebagai entry point
|
|
|
|
### Build Tools & Gradle
|
|
**Gradle**
|
|
- **Version**: 8.13.2
|
|
- **Type**: Kotlin DSL (build.gradle.kts)
|
|
- **Plugin**: Android Gradle Plugin (AGP)
|
|
- **Features**: Dependency management, build variants, ProGuard/R8
|
|
|
|
**Kotlin Compiler**
|
|
- **Kotlin Version**: 2.0.21
|
|
- **Compose Compiler Plugin**: org.jetbrains.kotlin.plugin.compose
|
|
- **KAPT**: Kotlin Annotation Processing Tool (untuk Room compiler)
|
|
- **Target**: JVM 11
|
|
|
|
**Version Catalog**
|
|
- **File**: gradle/libs.versions.toml
|
|
- **Fitur**: Centralized dependency management, type-safe accessors
|
|
- **Benefits**: Single source of truth, easy updates, IDE support
|
|
|
|
### Testing Framework
|
|
**Unit Testing**
|
|
- **JUnit**: 4.13.2 (unit test framework)
|
|
- **Location**: src/test/java/
|
|
|
|
**Instrumented Testing**
|
|
- **AndroidX Test JUnit**: 1.3.0
|
|
- **Espresso Core**: 3.7.0
|
|
- **Compose UI Test**: androidx.compose.ui:ui-test-junit4
|
|
- **Location**: src/androidTest/java/
|
|
|
|
**Debug Tools**
|
|
- **Compose UI Tooling**: Preview & inspection
|
|
- **Compose UI Test Manifest**: Test configuration
|
|
|
|
### Utilities & Helpers
|
|
**NetworkUtils.kt**
|
|
- **Purpose**: Network connectivity checking
|
|
- **API**: ConnectivityManager
|
|
- **Usage**: Cek internet sebelum sync ke backend
|
|
|
|
**ImageUtils.kt**
|
|
- **Purpose**: Image processing & conversion
|
|
- **Functions**: bitmapToBase64, compression, file operations
|
|
- **Usage**: Prepare foto untuk upload
|
|
|
|
### Security & Permissions
|
|
**Android Permissions**
|
|
- ACCESS_FINE_LOCATION (GPS)
|
|
- ACCESS_COARSE_LOCATION (Network location)
|
|
- CAMERA (Take photos)
|
|
- INTERNET (Network communication)
|
|
|
|
**Security Features**
|
|
- Encrypted local storage
|
|
- HTTPS communication
|
|
- Hardware-backed key storage (Keystore)
|
|
- No hardcoded credentials
|
|
- Certificate transparency
|
|
|
|
---
|
|
|
|
## FITUR APLIKASI
|
|
|
|
### 1. SISTEM LOGIN OFFLINE
|
|
- Konsep: First-time setup dengan one-time registration
|
|
- Metode: Offline (tidak menggunakan server)
|
|
- Penyimpanan: Encrypted SharedPreferences
|
|
- Enkripsi: AES256-GCM dengan MasterKey
|
|
- Data tersimpan:
|
|
- Username (terenkripsi)
|
|
- Password (terenkripsi)
|
|
- isRegistered flag
|
|
- isLogin flag
|
|
- Flow:
|
|
- Pertama kali: Buat username & password
|
|
- Selanjutnya: Login dengan kredensial tersimpan
|
|
- Validasi: Dilakukan secara lokal
|
|
|
|
### 2. ABSENSI BERBASIS LOKASI
|
|
- Validasi radius: Maksimal 500 meter dari titik kampus
|
|
- Jumlah titik kampus: 12 lokasi strategis
|
|
- Titik kampus meliputi:
|
|
- Kampus Ubhara Jaya (Pusat)
|
|
- Fakultas Ilmu Komputer
|
|
- Fakultas Ekonomi dan Bisnis
|
|
- Fakultas Psikologi
|
|
- Perpustakaan Tanoto
|
|
- Grha Tanoto
|
|
- Masjid Ulul Albab
|
|
- Work Caffe Bekasi
|
|
- Lapangan Ubhara
|
|
- Sekretariat Kapal Baja
|
|
- Ruang Sedang Semu
|
|
- ATM BRI Ubhara Jaya
|
|
- Algoritma: Haversine Formula untuk hitung jarak
|
|
- Response: Menampilkan nama lokasi terdekat & jarak
|
|
|
|
### 3. PENGAMBILAN FOTO ABSENSI
|
|
- Mode: Kamera depan (selfie)
|
|
- Trigger: Langsung saat proses absensi
|
|
- Batasan: Satu foto untuk satu kali absensi (anti-spam)
|
|
- Penyimpanan: Internal storage aplikasi
|
|
- Format: JPEG dengan kompresi
|
|
- Pengiriman: Konversi ke Base64 untuk dikirim ke backend
|
|
|
|
### 4. PENYIMPANAN DATA LOKAL
|
|
Database: Room (SQLite)
|
|
Table: attendance_history
|
|
|
|
Schema:
|
|
- id: String (UUID, Primary Key)
|
|
- studentId: String (NPM mahasiswa)
|
|
- studentName: String (Nama mahasiswa)
|
|
- courseName: String (Nama mata kuliah)
|
|
- photoPath: String (Path foto di storage)
|
|
- dateTime: Long (Timestamp Unix)
|
|
- latitude: Double (Koordinat lintang)
|
|
- longitude: Double (Koordinat bujur)
|
|
- locationName: String (Nama lokasi terdekat)
|
|
- distanceMeter: Int (Jarak dari titik kampus)
|
|
- attendanceStatus: String (SUCCESS/FAILED)
|
|
- syncStatus: String (PENDING/SYNCED)
|
|
- createdAt: Long (Timestamp pembuatan)
|
|
|
|
### 5. SINKRONISASI BACKEND
|
|
- Service: n8n Webhook Automation
|
|
- Method: POST HTTP Request
|
|
- Format: JSON dengan foto Base64
|
|
- Strategy: Offline-first dengan background sync
|
|
- Worker: AttendanceSyncWorker (WorkManager)
|
|
- Retry: Otomatis saat koneksi internet tersedia
|
|
- Flow:
|
|
1. Simpan data ke local database
|
|
2. Cek koneksi internet
|
|
3. Jika online: Kirim langsung ke n8n
|
|
4. Jika offline: Tandai PENDING
|
|
5. Background worker cek pending data
|
|
6. Kirim ulang saat internet tersedia
|
|
7. Update status menjadi SYNCED
|
|
|
|
Payload ke n8n:
|
|
```json
|
|
{
|
|
"npm": "202310715083",
|
|
"nama": "Rakha Adi Saputro",
|
|
"mata_kuliah": "Nama Mata Kuliah",
|
|
"latitude": -6.224158,
|
|
"longitude": 107.009268,
|
|
"timestamp": "2025-01-14T10:30:00Z",
|
|
"foto_base64": "base64_encoded_image_string"
|
|
}
|
|
```
|
|
|
|
### 6. RIWAYAT ABSENSI
|
|
- Screen: AttendanceHistoryScreen
|
|
- Data source: Room Database (local)
|
|
- Layout: LazyColumn (efficient scrolling)
|
|
- Card components:
|
|
- Thumbnail foto absensi
|
|
- Nama mata kuliah
|
|
- Waktu absensi (formatted)
|
|
- Koordinat lokasi
|
|
- Jarak dari kampus
|
|
- Status sinkronisasi (PENDING/SYNCED)
|
|
- Filter: Semua data dari lokal
|
|
- Offline support: Full offline browsing
|
|
|
|
### 7. DATA MAHASISWA
|
|
Data mahasiswa yang digunakan fixed (hardcoded):
|
|
- NPM: 202310715083
|
|
- Nama: Rakha Adi Saputro
|
|
|
|
Catatan: Data ini tidak diambil dari login, tetapi langsung diset di aplikasi
|
|
|
|
---
|
|
|
|
## PERMISSIONS ANDROID
|
|
|
|
Aplikasi memerlukan izin berikut:
|
|
|
|
```xml
|
|
<uses-permission android:name="android.permission.INTERNET"/>
|
|
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
|
|
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
|
|
<uses-permission android:name="android.permission.CAMERA"/>
|
|
```
|
|
|
|
Hardware features:
|
|
```xml
|
|
<uses-feature android:name="android.hardware.camera" android:required="false"/>
|
|
```
|
|
|
|
---
|
|
|
|
## BACKEND INTEGRATION
|
|
|
|
### n8n Workflow Automation
|
|
- Platform: n8n (Self-hosted)
|
|
- Host: n8n.lab.ubharajaya.ac.id
|
|
- Endpoint Production: /webhook/23c6993d-1792-48fb-ad1c-ffc78a3e6254
|
|
- Endpoint Testing: /webhook-test/23c6993d-1792-48fb-ad1c-ffc78a3e6254
|
|
|
|
### Data Destination
|
|
1. Google Sheets
|
|
- URL: https://docs.google.com/spreadsheets/d/1jH15MfnNgpPGuGeid0hYfY7fFUHCEFbCmg8afTyyLZs
|
|
- Columns: NPM, Nama, Mata Kuliah, Latitude, Longitude, Timestamp, Foto
|
|
|
|
2. ntfy Notification Service
|
|
- URL: https://ntfy.ubharajaya.ac.id/EAS
|
|
- Purpose: Real-time notification untuk dosen/admin
|
|
|
|
### Workflow n8n
|
|
File: n8n-workflow-EAS.json
|
|
Flow:
|
|
1. Webhook Trigger (receive POST data)
|
|
2. Data Validation
|
|
3. Write to Google Sheets
|
|
4. Send notification via ntfy
|
|
5. Return response to mobile app
|
|
|
|
---
|
|
|
|
## STRUKTUR DATA FLOW
|
|
|
|
```
|
|
User Action (Absensi)
|
|
|
|
|
v
|
|
Validasi Lokasi GPS
|
|
|
|
|
v
|
|
Ambil Foto Selfie
|
|
|
|
|
v
|
|
Simpan ke Room Database (Local)
|
|
|
|
|
v
|
|
Update UI (Riwayat bertambah)
|
|
|
|
|
v
|
|
Cek Koneksi Internet
|
|
|
|
|
+---> [Online] ---> Kirim ke n8n Webhook
|
|
| |
|
|
| v
|
|
| Update syncStatus = SYNCED
|
|
|
|
|
+---> [Offline] ---> Set syncStatus = PENDING
|
|
|
|
|
v
|
|
WorkManager scheduled
|
|
|
|
|
v
|
|
[Internet tersedia]
|
|
|
|
|
v
|
|
Retry kirim data PENDING
|
|
|
|
|
v
|
|
Update syncStatus = SYNCED
|
|
```
|
|
|
|
---
|
|
|
|
## CARA KERJA SISTEM
|
|
|
|
### Flow Lengkap Absensi:
|
|
|
|
1. PERSIAPAN
|
|
- User buka aplikasi
|
|
- Jika belum login: tampilkan AuthScreen
|
|
- Jika sudah login: tampilkan AbsensiScreen
|
|
|
|
2. HALAMAN ABSENSI
|
|
- Tampilkan NPM dan Nama (hardcoded)
|
|
- Input mata kuliah
|
|
- Tombol ambil foto
|
|
- Request permissions (Camera & Location)
|
|
|
|
3. PROSES ABSENSI
|
|
- User klik tombol absensi
|
|
- Sistem cek permission camera
|
|
- Buka camera untuk selfie
|
|
- User ambil foto
|
|
- Foto ditampilkan sebagai preview
|
|
- Sistem ambil koordinat GPS otomatis
|
|
- Validasi jarak dari titik kampus
|
|
|
|
4. VALIDASI
|
|
- Cek jarak < 500 meter?
|
|
- Ya: Lanjut proses
|
|
- Tidak: Tampilkan error & batalkan
|
|
- Cek foto valid?
|
|
- Ya: Lanjut proses
|
|
- Tidak: Minta foto ulang
|
|
|
|
5. PENYIMPANAN
|
|
- Generate UUID untuk attendance ID
|
|
- Simpan foto ke internal storage
|
|
- Simpan data ke Room Database
|
|
- Set syncStatus = PENDING
|
|
|
|
6. SINKRONISASI
|
|
- Cek koneksi internet
|
|
- Jika online:
|
|
- Encode foto ke Base64
|
|
- Kirim POST ke n8n webhook
|
|
- Jika sukses: Update syncStatus = SYNCED
|
|
- Jika gagal: Tetap PENDING
|
|
- Jika offline:
|
|
- Skip sync
|
|
- Data tetap PENDING
|
|
- WorkManager akan retry nanti
|
|
|
|
7. BACKGROUND SYNC
|
|
- WorkManager cek setiap internet tersedia
|
|
- Ambil semua data PENDING
|
|
- Kirim satu per satu ke n8n
|
|
- Update status yang berhasil
|
|
- Retry yang gagal
|
|
|
|
8. RIWAYAT
|
|
- User bisa lihat semua absensi di HistoryScreen
|
|
- Data diambil dari Room Database
|
|
- Menampilkan status PENDING/SYNCED
|
|
- Full offline support
|
|
|
|
---
|
|
|
|
## KEAMANAN
|
|
|
|
### 1. Enkripsi Data
|
|
- Encrypted SharedPreferences dengan AES256-GCM
|
|
- MasterKey untuk enkripsi kredensial login
|
|
- Password tidak disimpan plain text
|
|
|
|
### 2. Validasi Lokasi
|
|
- Multi-point validation (12 titik kampus)
|
|
- Radius enforcement (500 meter maksimal)
|
|
- Real-time distance calculation
|
|
|
|
### 3. Anti-Fraud
|
|
- Satu foto untuk satu absensi
|
|
- Foto harus diambil real-time (tidak bisa dari gallery)
|
|
- Timestamp server-side di n8n
|
|
- Validasi koordinat di backend (opsional)
|
|
|
|
### 4. Offline Security
|
|
- Data lokal terenkripsi
|
|
- No sensitive data in plain text
|
|
- Secure file storage
|
|
|
|
---
|
|
|
|
## KONFIGURASI ENDPOINT
|
|
|
|
File: ApiConfig.kt
|
|
Location: data/network/ApiConfig.kt
|
|
|
|
```kotlin
|
|
object ApiConfig {
|
|
const val N8N_WEBHOOK_URL =
|
|
"https://n8n.lab.ubharajaya.ac.id/webhook/23c6993d-1792-48fb-ad1c-ffc78a3e6254"
|
|
|
|
// Untuk testing:
|
|
// const val N8N_WEBHOOK_URL =
|
|
// "https://n8n.lab.ubharajaya.ac.id/webhook-test/23c6993d-1792-48fb-ad1c-ffc78a3e6254"
|
|
|
|
const val CONNECTION_TIMEOUT = 30000 // 30 detik
|
|
const val READ_TIMEOUT = 30000 // 30 detik
|
|
}
|
|
```
|
|
|
|
Keuntungan centralized config:
|
|
- Mudah switch antara production & testing
|
|
- Tidak perlu ubah banyak file
|
|
- Maintenance lebih simple
|
|
- Deploy lebih aman
|
|
|
|
---
|
|
|
|
## ANDROID SDK CONFIGURATION
|
|
|
|
### SDK Versions
|
|
```kotlin
|
|
android {
|
|
compileSdk = 36
|
|
|
|
defaultConfig {
|
|
applicationId = "id.ac.ubharajaya.sistemakademik"
|
|
minSdk = 28
|
|
targetSdk = 36
|
|
versionCode = 1
|
|
versionName = "1.0"
|
|
}
|
|
}
|
|
```
|
|
|
|
### Min SDK 28 (Android 9.0 Pie) - Coverage & Features
|
|
**Alasan pemilihan Min SDK 28:**
|
|
1. **Market Coverage**: ~80% devices (2024-2025 data)
|
|
2. **Security Features**:
|
|
- Mandatory HTTPS
|
|
- BiometricPrompt API
|
|
- Security Crypto support
|
|
3. **Modern APIs**:
|
|
- ImageDecoder API
|
|
- DisplayCutout support
|
|
- Indoor positioning (WiFi RTT)
|
|
4. **Location Features**:
|
|
- Foreground location access
|
|
- Better battery optimization
|
|
5. **Camera Features**:
|
|
- Multi-camera API
|
|
- Session parameters
|
|
6. **Performance**:
|
|
- ART improvements
|
|
- Background restrictions
|
|
|
|
### Target SDK 36 (Android 14+) - Latest Features
|
|
**Benefits:**
|
|
1. Google Play requirement compliance
|
|
2. Latest security patches
|
|
3. Performance optimizations
|
|
4. New API features
|
|
5. Better battery management
|
|
6. Enhanced privacy controls
|
|
|
|
### Compile SDK 36
|
|
- Access to latest Android APIs
|
|
- Build tools compatibility
|
|
- Preview features
|
|
- Development libraries
|
|
|
|
### Java Compatibility
|
|
```kotlin
|
|
compileOptions {
|
|
sourceCompatibility = JavaVersion.VERSION_11
|
|
targetCompatibility = JavaVersion.VERSION_11
|
|
}
|
|
|
|
kotlinOptions {
|
|
jvmTarget = "11"
|
|
}
|
|
```
|
|
|
|
**Java 11 Features:**
|
|
- Lambda expressions
|
|
- Method references
|
|
- Stream API
|
|
- Optional class
|
|
- Try-with-resources
|
|
- Type inference (var)
|
|
|
|
---
|
|
|
|
## BUILD CONFIGURATION
|
|
|
|
### Build Types
|
|
|
|
#### Debug Build
|
|
```kotlin
|
|
buildTypes {
|
|
debug {
|
|
isMinifyEnabled = false
|
|
isDebuggable = true
|
|
applicationIdSuffix = ".debug"
|
|
versionNameSuffix = "-DEBUG"
|
|
}
|
|
}
|
|
```
|
|
**Features:**
|
|
- No code obfuscation
|
|
- Full logging enabled
|
|
- Faster build time
|
|
- Debug symbols included
|
|
- Network profiler enabled
|
|
|
|
#### Release Build
|
|
```kotlin
|
|
buildTypes {
|
|
release {
|
|
isMinifyEnabled = false // Set true for production
|
|
proguardFiles(
|
|
getDefaultProguardFile("proguard-android-optimize.txt"),
|
|
"proguard-rules.pro"
|
|
)
|
|
signingConfig = signingConfigs.getByName("release")
|
|
}
|
|
}
|
|
```
|
|
**Features:**
|
|
- Code shrinking (ProGuard/R8)
|
|
- Obfuscation
|
|
- Optimization
|
|
- Signing required
|
|
- Smaller APK size
|
|
|
|
### Build Features
|
|
```kotlin
|
|
buildFeatures {
|
|
compose = true
|
|
}
|
|
```
|
|
- Enables Jetpack Compose
|
|
- Compose compiler integration
|
|
- Preview support
|
|
|
|
### ProGuard/R8 Configuration
|
|
File: `proguard-rules.pro`
|
|
|
|
**Purpose:**
|
|
- Code shrinking (remove unused code)
|
|
- Obfuscation (rename classes/methods)
|
|
- Optimization (inline, etc.)
|
|
- APK size reduction
|
|
|
|
**Keep Rules for:**
|
|
- Room entities (@Entity)
|
|
- Retrofit interfaces
|
|
- Gson models
|
|
- Parcelable classes
|
|
|
|
### APK Outputs
|
|
**Debug APK:**
|
|
- Path: `app/build/outputs/apk/debug/app-debug.apk`
|
|
- Size: ~15-20 MB (with debug symbols)
|
|
- Command: `.\gradlew assembleDebug`
|
|
|
|
**Release APK:**
|
|
- Path: `app/build/outputs/apk/release/app-release.apk`
|
|
- Size: ~8-12 MB (minified)
|
|
- Command: `.\gradlew assembleRelease`
|
|
|
|
---
|
|
|
|
## GRADLE BUILD SYSTEM
|
|
|
|
### Requirements
|
|
- Android Studio Ladybug atau lebih baru
|
|
- JDK 11 atau lebih tinggi
|
|
- Android SDK 28-36
|
|
- Gradle 8.13.2
|
|
- Koneksi internet (untuk dependency download)
|
|
|
|
### Build Commands
|
|
|
|
Development Build:
|
|
```bash
|
|
.\gradlew assembleDebug
|
|
```
|
|
|
|
Release Build:
|
|
```bash
|
|
.\gradlew assembleRelease
|
|
```
|
|
|
|
Clean Build:
|
|
```bash
|
|
.\gradlew clean assembleDebug
|
|
```
|
|
|
|
Install ke Device:
|
|
```bash
|
|
.\gradlew installDebug
|
|
```
|
|
|
|
Run Tests:
|
|
```bash
|
|
.\gradlew test
|
|
```
|
|
|
|
### Output Location
|
|
APK Debug: app/build/outputs/apk/debug/app-debug.apk
|
|
APK Release: app/build/outputs/apk/release/app-release.apk
|
|
|
|
---
|
|
|
|
## TESTING
|
|
|
|
### Akun Testing
|
|
Saat pertama kali buka aplikasi:
|
|
- Buat username dan password bebas
|
|
- Data tersimpan secara offline
|
|
- Login selanjutnya gunakan kredensial tersebut
|
|
|
|
### Testing Lokasi
|
|
Opsi 1: Test di lokasi kampus (ideal)
|
|
Opsi 2: Mock location untuk development:
|
|
- Enable Developer Options
|
|
- Select mock location app
|
|
- Gunakan koordinat salah satu dari 12 titik kampus
|
|
|
|
### Testing n8n Webhook
|
|
Gunakan endpoint testing:
|
|
```
|
|
https://n8n.lab.ubharajaya.ac.id/webhook-test/23c6993d-1792-48fb-ad1c-ffc78a3e6254
|
|
```
|
|
|
|
Ganti di ApiConfig.kt untuk testing
|
|
|
|
### Monitoring
|
|
- Google Sheets: Cek data masuk
|
|
- ntfy: Cek notifikasi real-time
|
|
- Logcat: Monitor logs di Android Studio
|
|
|
|
---
|
|
|
|
## TROUBLESHOOTING
|
|
|
|
### Issue: Foto tidak terkirim ke backend
|
|
Solusi:
|
|
- Cek koneksi internet
|
|
- Cek endpoint n8n aktif
|
|
- Lihat syncStatus di riwayat (PENDING berarti belum terkirim)
|
|
- Background worker akan retry otomatis
|
|
|
|
### Issue: Lokasi tidak valid padahal di kampus
|
|
Solusi:
|
|
- Pastikan GPS aktif
|
|
- Tunggu GPS lock (butuh waktu)
|
|
- Cek permission lokasi granted
|
|
- Pastikan tidak menggunakan VPN yang mengubah lokasi
|
|
|
|
### Issue: Kamera tidak bisa dibuka
|
|
Solusi:
|
|
- Cek permission camera granted
|
|
- Restart aplikasi
|
|
- Pastikan camera tidak digunakan app lain
|
|
- Cek hardware camera berfungsi
|
|
|
|
### Issue: Data tidak tersimpan di database
|
|
Solusi:
|
|
- Cek storage permission
|
|
- Cek disk space mencukupi
|
|
- Lihat logcat untuk error Room
|
|
- Clear app data dan coba lagi
|
|
|
|
### Issue: WorkManager tidak sync
|
|
Solusi:
|
|
- Pastikan internet stabil
|
|
- Cek battery optimization (disable untuk app ini)
|
|
- Force sync dengan buka riwayat
|
|
- Restart device
|
|
|
|
---
|
|
### Author
|
|
- NAMA : RAKHA ADI SAPUTRO
|
|
- NPM : 202310715083
|